🎤 iOS の AudioService で完全に理解する記事(Whisper / Speech API / PCM / バッファ)
この記事では、あなたの AudioService がやっている処理を
初心者にも理解できるように、かつエンジニア面接でも語れるレベル でまとめます。
内容は以下:
- iOS は何をしているのか(3つの処理)
- なぜフロントで音声処理が必要なのか
- バッファとは何か(超重要)
- Hz / PCM など音声の基礎
- コード全体を一言で説明すると?
- 面接での模範回答
- バッファを会話レベルで完全に理解する
🟥【1】このコードで “何が起きているか” を面接で言える形でまとめる
AudioService が実際にやっていることは たった3つ。
✔① マイクから音をリアルタイムで取り出して処理している
- iPhone のマイクは “生の波形データ(PCM)” を出す
- それを AVAudioEngine が受け取り
- 一定サイズのバッファ(小分けの配列) として渡してくれる
✔② Whisper 用の音声形式(16kHz / mono / Float32)に変換しながら WAV に保存
- iPhone マイク:48kHzステレオ
- Whisper:16kHz モノラル
- → 変換必須
そのために使うのが AVAudioConverter。
✔③ 同時に Apple Speech API(リアルタイム文字起こし)にバッファを渡す
録音しながら同時に文字起こしもする。
処理の流れ:
- 録音:変換しながらファイル保存
- 認識:元のバッファを Speech API に送る
つまり:
録音処理と文字起こし処理を完全に並列で行っている
🟦【2】なんでフロント(iOS)でこんな処理を書くの?
理由は3つ。
✔① 生の音声を全部サーバーに送ると重すぎる
- 生音:1分で約4MB
- 4G 回線だと遅い
- ポケットWiFiで固まったように見える
だから:
録音 → iOS側でファイル作成 → 完成したファイルを送る
これが正解。
✔② Whisper は「ファイル」を必要とする
Whisper API は:
- 生ストリームを受け取れない(WebSocket 以外)
- WAV / M4A などの“1ファイル”を送る必要がある
だから iOS 側でファイルを作る処理は必須。
✔③ Apple Speech API は iOS でしか動かない
- ローカルの Siri 音声認識API
- サーバーでリアルタイム処理は不可能
リアルタイム文字起こしを UI に表示したいなら:
iOS 内で処理するしかない
🟩【3】バッファとは?(最低限理解)
バッファとは:
音声データを一定サイズごとに切った“小さな配列”
例:
44.1kHz の音(44100個/秒)を…
4096 ずつ小分けにして渡す:
- buffer #1: 0〜4095
- buffer #2: 4096〜8191
- buffer #3: …
iOS コードだとこれ:
inputNode.installTap(onBus: 0, bufferSize: 4096, format: inputFormat) {
buffer, _ in
これで毎回:
- 4096サンプルの PCM データ
- 波形を数字で表した配列
- メモリ上に一時的に置かれる箱
が buffer に入る。
バッファが必要な理由
- 音声は無限に来る → 小分けにしないと処理できない
- Whisper も Speech API もバッファ単位で処理
- CPU 負荷軽減
- リアルタイム処理(0.02秒ごとなど)に必須
🟦【4】Hz(ヘルツ)とは?音声のサンプル頻度
1秒間に何個の音データを取ったかを表す。
| Hz | 意味 |
|---|---|
| 48kHz | iPhoneマイク標準 |
| 16kHz | Whisperが必要とする値 |
| 8kHz | 電話の音質 |
Whisper は16kHz前提なので変換が必須。
🟦【5】音声形式(PCM / Float32)最低限の覚え方
✔ PCM(Pulse Code Modulation)
- 加工なし
- 生の波形データ
- 数値の配列そのまま
✔ Float32
- 波形を 0.0〜1.0 の実数で表したもの
- Whisper は Float32 を使う
✔ LINEARPCM
- WAV の中身の標準
- 再生可能な音声形式
🟥【6】このコードの全体構造を超短く説明すると…
iPhoneのマイクから音を取り出す
→ 48kHz → 16kHzに変換
→ WAVファイルとして保存
→ 同時に Speech API に流してリアルタイム文字起こし
→ 録音が終わったらファイルをサーバーへ送る
→ Whisperで高精度の文字起こし
これだけ。
🟩【7】もし面接で聞かれたらどう答える?(模範回答)
「何をやっていますか?」
iOS側でマイク入力をリアルタイムで取得し、
Whisper用の16kHz モノラル PCM に変換しながら WAV として保存しています。
同時に Speech API にバッファを渡してリアルタイム文字起こしも行っています。
「なぜフロントでやるの?」
Whisper API はファイル入力が必要で、生のストリームを送れません。
またリアルタイム認識は Apple Speech API のみ可能で、iOS側でしか動かないためです。
そのため録音・変換・文字起こしはフロントで行う必要があります。
「Hzやバッファとは?」
マイクは大量の波形データを生成するため、扱いやすいよう一定サイズに区切ったものがバッファです。
Hz は1秒間に何個のサンプルを取るかの指標で、Whisper は16kHzを前提としているため iPhone の48kHzから変換しています。
これで “理解してるエンジニア” と確実に見なされる回答 になります。
🟦【追加】バッファをもっと深掘り(会話での説明を記事化)
あなたの質問:
バッファって、連続した波形を小分けにして渡せるようにした“変数”ってこと?
回答は:
ほぼ正しい。あと1つだけ加えれば完璧。
🟥 結論:バッファとは「連続する波形データを一定区間で切った“配列”」
🟩 音はアナログで無限に続く波
/\/\/\/\/\/\__/\/\/\...
🟦 マイクはこれを「数字(サンプリング)」に変換
例:48kHz
→ 1秒に 48,000個の数値
[0.15, 0.18, 0.17, ..., 0.20]
🟥 しかし48,000個を1回で渡すのは無理
だから OS が 4096個ずつに区切って渡す。
buffer #1 = [0〜4095]
buffer #2 = [4096〜8191]
buffer #3 = ...
🟧 バッファとは?
✔ 音声の連続データを小分けにした 一時的なPCMの配列
✔ 固有の変数ではなく、「今この瞬間の音の塊が入った箱」
🟥 バッファの存在理由まとめ
- 音声は無限なので一気に処理できない
- WhisperもSpeech APIもバッファ単位で処理
- CPU負荷分散のため
- リアルタイム処理のため(20msごとなど)