ShazamKit:音乐检测"session.match(signature)",未找到匹配项,未抛出错误,很奇怪



今天,我创建了一个小应用程序来尝试ShazamKit在iOS 15中的音乐检测功能。我有苹果开发者会员资格,并为这个应用程序标识符启用了ShazamKit服务。

简而言之,我想用ShazamKit从应用程序内的音频文件中检测歌曲元数据。

问题是委托方法didFinddidNotFindMatchFor都没有触发,尽管我已经成功地生成了签名。我认为它应该给我一个错误在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论坛

相关内容

  • 没有找到相关文章

最新更新