React Native集成最新ShazamKit遇SHMatcher错误求解决方案及示例
React Native集成ShazamKit实现音乐识别问题解决
问题描述
我已经为React Native创建了桥接,但难以理解ShazamKit文档,希望获取在React Native应用中使用最新版ShazamKit实现麦克风音乐识别的思路、帮助或源码。我尝试了以下Swift桥接代码,却出现错误:Cannot find 'SHMatcher' in scope。
原代码:
// my swift file import Foundation import ShazamKit import AVFoundation import React @objc(ShazamBridge) class ShazamBridge: NSObject { private let audioEngine = AVAudioEngine() private let session = SHSession() private var signatureGenerator = SHSignatureGenerator() @objc func startListening(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) { let inputNode = audioEngine.inputNode let recordingFormat = inputNode.outputFormat(forBus: 0) inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer: AVAudioPCMBuffer, when: AVAudioTime) in self.signatureGenerator.append(buffer, at: nil) } audioEngine.prepare() do { try audioEngine.start() } catch { reject("Error", "Audio engine could not start", error) } resolve("Listening started") } @objc func stopListeningAndIdentify(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) { audioEngine.stop() audioEngine.inputNode.removeTap(onBus: 0) let matcher = SHMatcher() let signature = signatureGenerator.signature() matcher.addSignature(signature) session.match(matcher, completion: { (matches, error) in if let error = error { reject("Error", "Failed to match audio", error) } else if let match = matches?.first { resolve(match.mediaItem.title) } else { resolve(nil) } }) } }
错误原因
最新版ShazamKit中,SHMatcher已被废弃,无需创建该实例。直接使用SHSession的match(_ signature: SHSignature, completion: ...)方法即可完成音频匹配。
修正后的完整代码
import Foundation import ShazamKit import AVFoundation import React @objc(ShazamBridge) class ShazamBridge: NSObject { private let audioEngine = AVAudioEngine() private let session = SHSession() private var signatureGenerator = SHSignatureGenerator() @objc func startListening(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) { // 检查麦克风权限 switch AVAudioSession.sharedInstance().recordPermission { case .granted: setupAudioTap(resolve: resolve, reject: reject) case .denied: reject("PERMISSION_DENIED", "麦克风权限已被拒绝", nil) case .undetermined: AVAudioSession.sharedInstance().requestRecordPermission { granted in DispatchQueue.main.async { if granted { self.setupAudioTap(resolve: resolve, reject: reject) } else { reject("PERMISSION_DENIED", "麦克风权限请求被拒绝", nil) } } } @unknown default: reject("PERMISSION_ERROR", "权限状态未知", nil) } } private func setupAudioTap(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) { let inputNode = audioEngine.inputNode let recordingFormat = inputNode.outputFormat(forBus: 0) // 移除已存在的tap,避免重复添加 inputNode.removeTap(onBus: 0) inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { [weak self] buffer, when in self?.signatureGenerator.append(buffer, at: when) } audioEngine.prepare() do { try audioEngine.start() resolve("Listening started") } catch { reject("AUDIO_ENGINE_ERROR", "音频引擎启动失败", error) } } @objc func stopListeningAndIdentify(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) { audioEngine.stop() audioEngine.inputNode.removeTap(onBus: 0) let signature = signatureGenerator.signature() // 重置签名生成器,以便下次使用 signatureGenerator = SHSignatureGenerator() session.match(signature) { matches, error in DispatchQueue.main.async { if let error = error { reject("MATCH_ERROR", "音频匹配失败", error) } else if let match = matches?.first { resolve([ "title": match.mediaItem.title ?? "未知标题", "artist": match.mediaItem.artist ?? "未知艺术家", "album": match.mediaItem.albumTitle ?? "未知专辑" ]) } else { resolve(nil) } } } } // 暴露给React Native的模块配置 @objc static func requiresMainQueueSetup() -> Bool { return true } }
关键说明
- 权限配置:在iOS项目的
Info.plist中添加以下权限描述:<key>NSMicrophoneUsageDescription</key> <string>需要访问麦克风以识别音乐</string> <key>NSShazamKitUsageDescription</key> <string>需要使用ShazamKit识别音乐</string> - 音频引擎管理:添加了麦克风权限检查,避免无权限时崩溃;每次启动监听前移除旧的tap,防止重复添加导致的错误
- 签名重置:每次匹配完成后重置
SHSignatureGenerator,确保下次监听生成新的签名 - 结果返回:扩展了返回数据,包含标题、艺术家、专辑信息,更实用;所有回调切换到主队列,符合React Native的线程要求
- 模块配置:实现
requiresMainQueueSetup方法,确保模块在主队列初始化,避免线程问题
内容的提问来源于stack exchange,提问作者amirhosein
相关产品推荐
相关产品推荐

