探索 ShazamKit
Explore ShazamKit
2021年6月10日
一句话判断
ShazamKit 把 Shazam 的音频指纹识别能力开放给所有开发者了——不只是识别歌曲,还能用自定义音频库匹配任何声音,但别忘了 Apple 收取的 API 调用限制。
这场 Session 讲了什么
ShazamKit 是 WWDC 2021 最让人兴奋的新框架之一。它把 Shazam 的核心技术——音频指纹匹配——以 SDK 的形式开放给第三方开发者。你可以在自己的 app 中实现「听音识曲」功能,而不需要自建音频识别引擎。
ShazamKit 支持两种使用模式。第一种是使用 Apple 的 Shazam 音乐目录(包含数百万首歌曲),适合做音乐识别类 app。第二种是使用自定义音频目录(Custom Catalog),你可以上传自己的音频文件生成参考指纹,然后匹配任何声音——比如广告监测、电视节目同步、线下活动互动。
技术架构上,ShazamKit 的工作原理是:录制一段几秒的音频,提取频谱特征生成指纹,然后与目录中的指纹进行比对。匹配速度非常快(通常在 1-2 秒内),而且可以离线运行(使用 Custom Catalog 时)。
值得深挖的点
Custom Catalog 的适用场景
Custom Catalog 是 ShazamKit 最有价值的能力。想象一下:一个电视节目可以把自己的音频生成指纹目录,观众打开 app 识别当前正在播放的片段,app 可以展示相关的互动内容(投票、问答、购买链接)。这在国外被称为「第二屏体验」。
生成 Custom Catalog 需要使用 ShazamKit 的命令行工具或者 API,把音频文件转换为 .shazamsignature 格式。每个音频文件生成一个 Reference Signature,然后打包成 Catalog。Catalog 文件可以打包到 app 中离线使用,也可以托管在服务端按需下载。
匹配精度与音频长度的关系
ShazamKit 的匹配精度取决于录制的音频长度。Session 建议:音乐识别至少需要 3 秒的录制,Custom Catalog 匹配建议 5 秒以上。录制时间越长,匹配越准确。但在嘈杂环境中,即使录制 10 秒也可能匹配失败——ShazamKit 对背景噪音的抗干扰能力有限。
代码片段
// 基础音乐识别
import ShazamKit
class MusicRecognizer: NSObject, SHSessionDelegate {
let session = SHSession()
let audioEngine = AVAudioEngine()
override init() {
super.init()
session.delegate = self
}
func startListening() {
let audioSession = AVAudioSession.sharedInstance()
try? audioSession.setCategory(.record)
try? audioSession.setActive(true)
let inputNode = audioEngine.inputNode
let format = inputNode.outputFormat(forBus: 0)
inputNode.installTap(onBus: 0, bufferSize: 4096, format: format) {
[weak self] buffer, time in
self?.session.matchStreamingBuffer(buffer,
at: time)
}
try? audioEngine.start()
}
func stopListening() {
audioEngine.inputNode.removeTap(onBus: 0)
audioEngine.stop()
}
// SHSessionDelegate 回调
func session(_ session: SHSession, didFind match: SHMatch) {
guard let item = match.items.first?.mediaItem else { return }
let title = item.title ?? "未知歌曲"
let artist = item.artist ?? "未知艺术家"
let artwork = item.artworkURL
print("识别到: \(title) - \(artist)")
}
func session(_ session: SHSession, didNotFindMatchFor signature: SHSignature, error: Error?) {
print("未找到匹配")
}
}
// 使用 Custom Catalog 匹配自定义音频
func setupCustomCatalog() {
// 从 app bundle 中加载预生成的 catalog
guard let catalogURL = Bundle.main.url(
forResource: "MyCustomCatalog",
withExtension: "shazamcatalog"
) else { return }
do {
let catalog = try SHCustomCatalog(contentsOf: catalogURL)
let session = SHSession()
session.delegate = self
// 将自定义目录添加到 session
// session 会同时匹配 Shazam 目录和自定义目录
try catalog.add(to: session)
} catch {
print("加载自定义目录失败: \(error)")
}
}
// 从音频文件生成 Custom Catalog(通常在服务端完成)
// 使用 ShazamKit 的命令行工具:
// shazamkit catalog create --input audio/ --output catalog.shazamcatalog
//
// 或者在 macOS 上用代码生成:
func generateSignature(from audioURL: URL) -> SHSignature? {
let asset = AVAsset(url: audioURL)
let generator = SHSignatureGenerator()
// 这个方法只在 macOS 上可用
// iOS 上需要使用预生成的 catalog
return try? generator.signature(from: asset)
}
最佳实践
不要持续运行音频录制。ShazamKit 的麦克风使用是高功耗操作。建议让用户手动触发识别(点击按钮开始,再次点击停止),或者设置一个 10-15 秒的超时自动停止。
如果你的 app 使用 Custom Catalog,把 catalog 文件压缩后放在 CDN 上按需下载。一个包含 100 首歌的 catalog 大约 5-10MB。首次下载后缓存到本地,后续匹配就不需要网络了。
还有什么值得关注
- ShazamKit 支持同步获取歌曲的 Apple Music 链接,如果你的 app 集成了 MusicKit,可以直接播放识别到的歌曲。
SHMediaItem包含了丰富的元数据:歌曲名、艺术家、专辑、发行年份、流派等。- Custom Catalog 支持增量更新——可以只下载新增的音频指纹,不需要重新下载整个 catalog。