打造出色的 ShazamKit 体验
Create a great ShazamKit experience
2023年6月5日
一句话判断
SHManagedSession 把音频录制和识别的代码量砍到了几行——如果你之前因为 AVAudioEngine 的复杂性而放弃接入 ShazamKit,现在是重新考虑的时候了。
这场 Session 讲了什么
Session 聚焦 ShazamKit 在 2023 年的三项更新:
1. SHManagedSession(管理式会话): 全新的高级 API,自动处理麦克风权限申请、音频引擎配置、音频缓冲区采集。开发者只需创建 session、调用 result 方法、处理返回结果。相比之前手动配置 AVAudioEngine 的方式,代码量大幅减少。
Managed Session 支持两种使用方式:
result()方法:单次识别,返回 match/noMatch/error 三种结果。resultsasync sequence:持续识别流,适合长时间监听场景。
还提供了 prepare() 方法用于预热——提前分配资源和预录制,让后续的识别请求响应更快。
2. Shazam Library API 重新设计: 对 Shazam 音乐库的访问能力进行了重新定义和增强,具体包括更好的媒体项目管理能力。
3. 最佳实践:
Session 提供了完整的示例项目,展示如何从传统 SHSession 迁移到 SHManagedSession。
Session 中有个很直观的 Demo:一个”学跳舞”App,用麦克风识别正在播放的歌曲,然后自动匹配对应的舞蹈教学视频。这个场景很好地展示了 ShazamKit 与其他 API(如音乐播放、视频播放)的组合使用。
值得深挖的点
prepare() 的时机选择值得思考。不调用 prepare 时,第一次 result() 请求需要先分配资源、启动录制,然后才能开始识别。调用 prepare 后,资源和录制都提前就绪,result() 能更快返回匹配结果。如果你的 App 有一个”准备识别”的 UI 状态(比如用户进入了识别页面但还没点击按钮),这就是调用 prepare 的最佳时机。
从 SHSession 到 SHManagedSession 的迁移路径设计得很顺畅。Session 展示了具体的迁移步骤:替换实例类型、删除音频引擎配置代码、删除权限请求代码、简化停止逻辑。整个过程不涉及业务逻辑变更,纯粹是基础设施的简化。
Signature 的隐私保护设计值得注意。音频被转换为 Signature 后是不可逆的——无法从 Signature 还原原始录音。这意味着 ShazamKit 在传输和匹配过程中不会泄露用户的音频内容。
代码片段
使用 SHManagedSession 进行单次识别:
import ShazamKit
class Matcher {
private let managedSession = SHManagedSession()
func recognize() async {
do {
// 单次识别,自动处理麦克风权限和录音
let result = try await managedSession.result()
switch result {
case .match(let match):
// 获取匹配的媒体信息
if let item = match.mediaItems.first {
print("识别到:\(item.title ?? "未知") - \(item.artist ?? "未知")")
}
case .noMatch:
print("未找到匹配")
}
} catch {
print("识别出错:\(error)")
}
}
func stop() {
managedSession.cancel() // 取消当前识别并停止录音
}
}
使用 async sequence 进行持续识别:
func startContinuousRecognition() async {
managedSession.prepare() // 预热,加快首次识别速度
do {
for try await result in managedSession.results {
switch result {
case .match(let match):
// 处理每次匹配结果
handleMatch(match)
case .noMatch:
// 继续监听
break
}
}
} catch {
// 处理错误或用户主动取消
print("识别结束:\(error)")
}
}
从传统代码迁移到 Managed Session 的变化:
// 迁移前:手动配置音频引擎
// let session = SHSession()
// let audioEngine = AVAudioEngine()
// audioEngine.inputNode.installTap(...) // 配置音频缓冲区
// audioEngine.prepare()
// audioEngine.start()
// ... 大量样板代码
// 迁移后:三行搞定
let managedSession = SHManagedSession()
let result = try await managedSession.result()
// 就这么简单
最佳实践
- 在用户进入识别界面的时刻调用
prepare(),在点击识别按钮时调用result(),这样可以最小化识别延迟。 - Info.plist 中必须添加
NSMicrophoneUsageDescription,Managed Session 会自动使用这个描述来请求权限。 - 长时间监听场景用
resultsasync sequence 而不是循环调用result(),前者更高效且能持续返回多个匹配。 cancel()会同时停止录音和取消正在进行的匹配,在页面消失或 App 进入后台时调用。- 匹配结果中的
mediaItems可能包含多个条目(比如同一首歌的不同版本),用first不一定总是最佳选择,根据业务需求决定如何展示。 - ShazamKit 匹配即使在嘈杂环境(如餐厅)中也能工作,但极度嘈杂或音量过低的环境下识别率会下降。
还有什么值得关注
- 2022 年引入的 Shazam CLI 工具和自定义目录(Custom Catalogs)功能仍然可用,适合需要大规模音频指纹管理的场景。
- 自定义目录中的 frequency skewing 功能可以帮助区分相似音频片段,对音乐类 App 特别有用。
- Signature 是不可逆的,这在某些需要留存原始音频的场景中可能是个限制——你需要在本地同时保存原始录音。
- ShazamKit 的匹配依赖网络连接,离线状态下无法使用。
- 搭配 MusicKit API,可以在识别歌曲后直接播放完整版或添加到播放列表,构建完整的音乐发现体验。