しめ鯖日記

swift, iPhoneアプリ開発, ruby on rails等のTipsや入門記事書いてます

ShazamKitで音声認識を試してみる

下の記事を参考にShazamKitを動かしてみました。

ichi.pro

ShazamKitは音楽認識ライブラリで、マイク経由で曲を渡すと曲名を出してくれたりします。
ShazamKitのiOS15から登場したライブラリで、SDKAndroidでも使えるようです。

developer.apple.com

初期設定

まずは使いたいアプリのBundleIDのShazamKitを有効化します。
AppleのMemberCenterにアクセスしてShazamKitを使いたいBundleIDを登録してから「App Services」にあるShazamKitにチェックを入れて保存します。

f:id:llcc:20210927135717p:plain

実装

新規にプロジェクトを作成します。
BundleIDは先程登録したIDを使います。

f:id:llcc:20210927140444p:plain

音声認識の際にマイクを使うので、Info.plistにNSMicrophoneUsageDescriptionを追加してマイクを使う理由を記述します。

f:id:llcc:20210927140043p:plain

まずはマイクの音を取り込む実装をします。
ViewControllerを下のように修正します。

class ViewController: UIViewController {
    let engine = AVAudioEngine()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let audioSession = AVAudioSession.sharedInstance()
        try? audioSession.setCategory(.record)
        try? audioSession.setActive(true, options: .notifyOthersOnDeactivation)
        
        let inputNode = engine.inputNode
        try? engine.start()
    }
}

起動するとマイクの音声を読み取る事ができるようになります。

f:id:llcc:20210927141056p:plain

次は読み取った音声を元に曲名を調べる実装をします。
ViewControllerを下のように変更します。

import UIKit
import ShazamKit

class ViewController: UIViewController {
    let session = SHSession() // 追加
    let engine = AVAudioEngine()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let audioSession = AVAudioSession.sharedInstance()
        try? audioSession.setCategory(.record)
        try? audioSession.setActive(true, options: .notifyOthersOnDeactivation)
        
        let inputNode = engine.inputNode
        try? engine.start()
        
        // ここから追加
        session.delegate = self
        let format = inputNode.outputFormat(forBus: .zero)
        inputNode.installTap(onBus: .zero, bufferSize: 1024, format: format) { buffer, _ in
            self.session.matchStreamingBuffer(buffer, at: nil)
        }
    }
}

extension ViewController: SHSessionDelegate {
    func session(_ session: SHSession, didFind match: SHMatch) {
        print(#function)
        print(match.mediaItems)
    }
    
    func session(_ session: SHSession, didNotFindMatchFor signature: SHSignature, error: Error?) {
        print(#function)
        print(error)
    }
}

音声をShazamKitにわたす処理は下の箇所で行っています。

inputNode.installTap(onBus: .zero, bufferSize: 1024, format: format) { buffer, _ in
    self.session.matchStreamingBuffer(buffer, at: nil)
}

読み取り成功時や失敗時はSHSessionDelegateのメソッドが呼ばれます。

extension ViewController: SHSessionDelegate {
    func session(_ session: SHSession, didFind match: SHMatch) {
        print(#function)
        print(match.mediaItems)
    }
    
    func session(_ session: SHSession, didNotFindMatchFor signature: SHSignature, error: Error?) {
        print(#function)
        print(error)
    }
}

曲を流すと下のように正しく曲が認識されました。

f:id:llcc:20210927141534p:plain

日本の曲も試した所、正しく認識する事ができました。

f:id:llcc:20210927141813p:plain