iOS10で公開されたSpeechフレームワークを使って日本語PodCastをテキスト化してみました。 結果から言うと、テキスト化は可能でしたが、品質はかなり悪く実用として厳しかったです。 某IT系PodCastのファイルを食わせて見たんですが、 「ジャバスクリプト」とか「ディープラーニング」とか一般的でない語彙はほぼ認識できませんでした。
SFSpeechiRecognizerというクラスを使います。 音声ファイルを指定すると、iOSデバイスからAppleサーバへリクエストが投げられ、 結果のテキストが得られます。
受け付ける音声ファイルの長さは60sec以内にしないといけないので、 PodCastのmp3などの音声ファイルを20secで区切って順番に処理する戦略をとります。 この方法でAPI制限に引っかかることはありませんでした。
基本のソースコードはAppleのSampleCodeを見るか、WWDC2016のセッションを見るか、 ググるとわかりますので端折ります。
SpeakToMe: Using Speech Recognition with AVAudioEngine
ここでは、mp3ファイルを20secのファイルに区切る処理のソースだけを示しておきます。
import Foundation import AudioToolbox import AVFoundation open class AudioDivider { init(url:URL) { self.url = url } private var url:URL public final class func diskCachePath(cacheName: String) -> String { let dstPath = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first! return (dstPath as NSString).appendingPathComponent(cacheName) } public func execute() -> [URL] { var urls:[URL] = [] var inref: ExtAudioFileRef? var outref: ExtAudioFileRef? var st:OSStatus st = ExtAudioFileOpenURL(url as CFURL, &inref) var index = 0 let pcmfmt:AVAudioFormat = AVAudioFormat.init(commonFormat: AVAudioCommonFormat.pcmFormatInt16, sampleRate: 44100.0, channels: 1, interleaved: false) // read format setting guard let inref_unwrap = inref else { assert(false) } st = ExtAudioFileSetProperty(inref_unwrap, kExtAudioFileProperty_ClientDataFormat, UInt32(MemoryLayout<AudioStreamBasicDescription>.size), pcmfmt.streamDescription) let bufferByteSize:UInt32 = 1024 var srcBuffer = [UInt8](repeating:0, count: 1024) // file loop var eof:Bool = false while true { let cachepath:String = AudioDivider.diskCachePath(cacheName:"") let outpath:String = "\(cachepath)/divider\(index).wav" let outurl:URL = URL(fileURLWithPath: outpath) urls.append(outurl) st = ExtAudioFileCreateWithURL(outurl as CFURL, kAudioFileWAVEType, pcmfmt.streamDescription, nil, AudioFileFlags.eraseFile.rawValue, &outref) guard let outref_unwrap = outref else { assert(false) } var writeFrame:UInt32 = 0 // data loop while true { let ab = AudioBuffer(mNumberChannels: 1, mDataByteSize: bufferByteSize, mData: &srcBuffer) var abl = AudioBufferList(mNumberBuffers: 1, mBuffers: ab) var numFrames: UInt32 = 0 if pcmfmt.streamDescription.pointee.mBytesPerFrame > 0 { numFrames = bufferByteSize / pcmfmt.streamDescription.pointee.mBytesPerFrame } st = ExtAudioFileRead(inref_unwrap, &numFrames, &abl) if numFrames <= 0 { eof = true break } st = ExtAudioFileWrite(outref_unwrap, numFrames, &abl) writeFrame += numFrames // terminate the file in 20sec if writeFrame > 44100 * 20 { break } } ExtAudioFileDispose(outref_unwrap) index += 1 if eof { break } } ExtAudioFileDispose(inref_unwrap) return urls } }
Speech API - Speech Recognition | Google Cloud Platform
は精度がいいらしいですが、無料枠が1ヶ月で1hourしかないため、試す気になりませんでした。 ※1ヶ月で1hourまで無料 以降、$0.006/15sec (=$1.44/1hour)