Speechフレームワークで音声認識→動画に自動で字幕をつける
やりたいこと:
Speechフレームワークで(日本語の)音声認識を行い、その結果を使って動画に字幕を自動でつける。
(このスクショは記事用に参考として適用してみただけです。映像と期待すべき認識結果が画像だけで伝わるかなということで。)
Speechフレームワークで音声認識を行う記事は多々あるのでそのへんは省略。動画との連動をどうやるか、認識がなかなかうまくいかないのをどうするか諸々検討したことについて書き留めておく。
動画から音声を抽出
SFSpeechRecognizerはバッファを渡してリアルタイムに認識する方法と、音声ファイルを渡してオフライン(※ネットワークの話ではなくて非リアルタイムの意味)で認識する方法がある。今回の用途だと再生のたびに音声認識を回すのはCPUの無駄なので、後者で処理する。
そのために動画から音声データをファイルとして抜き出す。実装方法としては動画のAVAssetオブジェクトから、AVAssetExportSessionを用いてこんな感じでファイルにexportするだけ。
let exportSession = AVAssetExportSession(asset: self, presetName: AVAssetExportPresetAppleM4A)!
if FileManager.default.fileExists(atPath: url.path) {
try! FileManager.default.removeItem(at: url)
}
exportSession.canPerformMultiplePassesOverSourceMediaData = true
exportSession.outputURL = url
exportSession.outputFileType = .m4a
exportSession.exportAsynchronously(completionHandler: handler)
1分の制約への対処
SFSpeechRecognizerは1分までしか音声認識してくれないという制約がある。
Plan for a one-minute limit on audio duration. Speech recognition can place a relatively high burden on battery life and network usage. In iOS 10, utterance audio duration is limited to about one minute, which is similar to the limit for keyboard-related dictation.
これを回避するために、AVAssetExportSessionのtimeRangeプロパティを使って音声ファイルを1分以内に切り出してexportすればよさそう。
// 参考記事のコード。Swiftバージョン/iOSバージョンが古いかも
let startTime = CMTimeMake(0, 1)
let stopTime = CMTimeMake(5, 1)
let exportTimeRange = CMTimeRangeFromTimeToTime(startTime, stopTime)
exporter.timeRange = exportTimeRange
ファイルの切れ目のところにちょうど音声がまたがる可能性があるので、多少オーバーラップさせて切らないといけない。ので認識結果の処理が面倒そう。(※今回は自分ではここまでやっていない)
認識結果のタイムスタンプ
最後まで読んでいただきありがとうございます!もし参考になる部分があれば、スキを押していただけると励みになります。 Twitterもフォローしていただけたら嬉しいです。 https://twitter.com/shu223/