今天,我创建了一个小应用程序来尝试ShazamKit在iOS 15中的音乐检测功能。我有苹果开发者会员资格,并为这个应用程序标识符启用了ShazamKit服务。
简而言之,我想用ShazamKit从应用程序内的音频文件中检测歌曲元数据。
问题是委托方法didFind
和didNotFindMatchFor
都没有触发,尽管我已经成功地生成了签名。我认为它应该给我一个错误在didNotFindMatchFor
委托方法,如果没有找到匹配至少,但它没有。
这是一个相当新的功能,没有那么多相关的东西我能找到。谢谢你的帮助。
更多信息:我确实发现一些使用audioEngine的东西,但是使用麦克风的输出,如果用户用耳机听音乐,那是不可能的。在我的情况下,我想使用文件本身,因为我的生产应用程序是一个音乐播放器,它在沙盒中存储了很多音频文件。
import ShazamKit
import UIKit
class ViewController: UIViewController {
lazy var recoButton: UIButton = {
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 120, height: 60))
button.layer.cornerRadius = 8
button.backgroundColor = .brown
button.setTitle("Recognize", for: .normal)
button.addTarget(self, action: #selector(recognizeSong), for: .touchUpInside)
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(recoButton)
recoButton.center = view.center
}
@objc func recognizeSong(_ sender: UIButton) {
print("reco button tapped")
// ShazamKit is available from iOS 15
if #available(iOS 15, *) {
// session
let session = SHSession()
// delegate
session.delegate = self
do {
// get track
guard let url = Bundle.main.url(forResource: "Baby One More Time", withExtension: "mp3") else {
print("url is NULLLL")
return }
// create audio file
let file = try AVAudioFile(forReading: url)
let frameCapacity = AVAudioFrameCount(file.length / 26)
// Audio -> Buffer
guard let buffer = AVAudioPCMBuffer(pcmFormat: file.processingFormat, frameCapacity: frameCapacity) else {
print("Failed to create a buffer")
return }
// Read file into buffer
try file.read(into: buffer)
// SignatureGenerator
let generator = SHSignatureGenerator()
try generator.append(buffer, at: nil)
// create signature
let signature = generator.signature()
// try to match
session.match(signature)
} catch {
print(error)
}
} else {
// unavailable alert
}
}
}
extension ViewController: SHSessionDelegate {
func session(_ session: SHSession, didFind match: SHMatch) {
print("Match found!")
// get results
let items = match.mediaItems
items.forEach { item in
print(item.title ?? "title")
print(item.artist ?? "artist")
print(item.artworkURL?.absoluteURL ?? "artwork url")
}
}
func session(_ session: SHSession, didNotFindMatchFor signature: SHSignature, error: Error?) {
if let error = error {
print(error)
}
}
}
今天的测试&观察。我发现我们需要用内置转换器(AVAudioConverter)将输入音频格式转换为AVAudioFormat(standardFormatWithSampleRate: 44100, channels: 1)
。然后创建输出缓冲区,这次可以识别音乐。
我选择了10多个音乐文件进行测试运行,除了一个之外,它们都可以被检测到。有趣的是这个音乐文件可以被Shazam应用程序检测到,我不知道是什么原因,因为未检测到的音乐歌曲没有显示错误。
无论如何,现在是工作。更新代码如下,它只是用于测试目的的几个函数的组合,您应该将它们分成不同的函数用于生产。
@objc func recognizeSong(_ sender: UIButton) {
print("reco button tapped")
// ShazamKit is available from iOS 15
if #available(iOS 15, *) {
// session
let session = SHSession()
session.delegate = self
guard let url = Bundle.main.url(forResource: "You Belong With Me", withExtension: "mp3") else {
return
}
guard let audioFormat = AVAudioFormat(standardFormatWithSampleRate: 44100, channels: 1) else {
return
}
let generator = SHSignatureGenerator()
do {
let audioFile = try AVAudioFile(forReading: url)
guard let inputBuffer = AVAudioPCMBuffer(pcmFormat: audioFile.processingFormat, frameCapacity: 44100 * 10),
let outputBuffer = AVAudioPCMBuffer(pcmFormat: audioFormat, frameCapacity: 44100 * 10) else {
return
}
// Read file into buffer
let inputBlock : AVAudioConverterInputBlock = { inNumPackets, outStatus in
do {
try audioFile.read(into: inputBuffer)
outStatus.pointee = .haveData
return inputBuffer
} catch {
if audioFile.framePosition >= audioFile.length {
outStatus.pointee = .endOfStream
return nil
} else {
outStatus.pointee = .noDataNow
return nil
}
}
}
guard let converter = AVAudioConverter(from: audioFile.processingFormat, to: audioFormat) else {
return
}
let status = converter.convert(to: outputBuffer, error: nil, withInputFrom: inputBlock)
if status == .error || status == .endOfStream {
return
}
try generator.append(outputBuffer, at: nil)
if status == .inputRanDry {
return
}
} catch {
print(error)
}
// create signature
let signature = generator.signature()
// try to match
session.match(signature)
} else {
// unavailable alert
}
}
}
参考文献:Apple论坛