🎙 SwiftUI × WhisperKit 音声文字起こしアプリ開発記録

― 録音音声がスローになる問題の正体と解決 ―


🧩 起きていた問題:録音音声が「スロー再生」される

iOSで開発中の音声文字起こしアプリにて、録音後の文字起こし結果が明らかに間延びしているという問題が発生。音声ファイルを再生すると、**再生スピードが異常に遅い(約0.6〜0.7倍速)**と判明。


🔍 原因究明:AudioConverterとサンプルレートの罠

原因は、マイクの実際の入力サンプルレートが 48000Hzにも関わらず、
AVAudioConverter で 16000Hz に無理やり変換していたこと。

swiftコピーする編集するtry session.setPreferredSampleRate(16000)
print("🎤 実際の入力サンプルレート: \(session.sampleRate)") // → 実際は48000.0

つまり、3秒の音声が約9秒に間延びして記録されるという事態に。


✅ 解決策:変換後のバッファサイズを正確に扱う

修正ポイントは次の2つ:

1. バッファ容量を変換比に応じて計算せず、固定で確保

swiftコピーする編集するlet outputBuffer = AVAudioPCMBuffer(pcmFormat: converter.outputFormat, frameCapacity: 2048)

2. frameLengthを使ってサンプル抽出

swiftコピーする編集するlet samples = Array(
    UnsafeBufferPointer(start: outputBuffer.floatChannelData![0], count: Int(outputBuffer.frameLength))
)

✍️ 教訓と今後の注意点

✔️ サンプルレートは「希望」ではない

swiftコピーする編集するtry session.setPreferredSampleRate(16000)

上記は希望にすぎず、実際のサンプルレートは session.sampleRate で確認する必要がある。


✔️ 変換バッファは常に frameLength を基準に処理すべし

swiftコピーする編集するoutputBuffer.frameLength

これを無視して長さ計算を誤ると、音声データがスロー/速すぎになる。


✔️ 音声チャンク処理は「秒数」ではなく「サンプル数」で制御

swiftコピーする編集するlet targetSampleCount = Int(sampleRate * 5) // 5秒チャンク

これがマイク入力の実サンプルレートとずれていれば、チャンクがズレる。


🎉 結果

録音音声のスピードが正常化し、文字起こしの精度も大幅に向上!
リアルタイム文字起こしとして、音声品質・変換精度ともに安定した動作が得られました。


🔚 まとめ

  • 「音の歪み」は設定ミスの蓄積から生まれる
  • ログ出力で 実際の環境値を必ず確認
  • WhisperKit を正しく活かすには 音声信号処理の基本が不可欠

🔗 次回予告

次回は:

  • 無音検出によるチャンク最適化
  • 録音ファイルの MP3 変換
  • バックグラウンド録音対応

などを深掘り予定です。ご期待ください!