Speech Frameworkについて

音声で買い物リストを入力できるアプリを作る中で、Apple純正の **Speech Framework** を使った音声認識を実装したので、調べたことをまとめていきます。

## 🧠 Speech Framework とは？
AppleがiOS 10以降で提供している、音声認識（Speech-to-Text）機能です。
ユーザーの音声をリアルタイムまたは録音ファイルからテキストに変換できます。

## 🔧 開発前の準備
### 1. フレームワークのインポート

```swift
import Speech
```
Speech Framework を使うには、まずこの1行が必要です。
これで SFSpeechRecognizer（音声をテキストに変換（音声認識）する機能） などのクラスが使えるようになります。


### 2. Info.plist に権限を追加
音声認識にはマイクの使用と音声認識の許可が必要です。以下の2つを Info.plist に追加します：

```xml
<key>NSMicrophoneUsageDescription</key>
<string>音声入力のためにマイクを使用します。</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string>音声認識を使用します。</string>
```
これがないとアプリがクラッシュするので必須です。


### 3. 音声認識の権限をリクエスト
アプリの起動時や音声入力を使う前に、ユーザーに音声認識の許可を求めます：

```swift
SFSpeechRecognizer.requestAuthorization { status in
    switch status {
    case .authorized:
        print("音声認識許可OK")
    case .denied, .restricted, .notDetermined:
        print("音声認識が使えません")
    @unknown default:
        fatalError()
    }
}
```


## 🛠 実装の流れ
### 1. クラス内に必要なプロパティを定義

```swift
    // 音声認識を行うためのメインオブジェクト。
    // locale に "ja-JP" を指定することで、日本語の音声をテキストに変換するよう設定している。
    private let speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "ja-JP"))

    // マイクから取得した音声データをリアルタイムで音声認識エンジンに送るためのリクエストオブジェクト。
    // 音声データをバッファとして追加していく役割。
    private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest?

    // 音声認識処理の状態や結果を管理するタスクオブジェクト。
    // 音声認識の進行状況を監視したり、結果を取得したり、途中でキャンセルしたりできる。
    private var recognitionTask: SFSpeechRecognitionTask?

    // マイクから音声を取得するためのオーディオエンジン（録音機能）
    // AVFoundation に含まれる低レベルのオーディオ処理エンジンで、リアルタイムで音声をキャプチャする。
    private let audioEngine = AVAudioEngine()
```

### 2. 音声認識を開始するメソッド
```swift
// 音声認識を開始する関数
func startRecording() throws {
    let node = audioEngine.inputNode
    let recordingFormat = node.outputFormat(forBus: 0)

    // 音声認識のリクエストを初期化（リアルタイム認識用）
    recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
    recognitionRequest?.shouldReportPartialResults = true // 部分結果も取得する

    // マイクから取得した音声データを recognitionRequest に流す
    node.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer, _ in
        self.recognitionRequest?.append(buffer)
    }

    // 音声エンジンを準備して開始
    audioEngine.prepare()
    try audioEngine.start()

    // 認識タスクを開始し、結果をクロージャで受け取る
    recognitionTask = speechRecognizer?.recognitionTask(with: recognitionRequest!) { result, error in
        if let result = result {
            let spokenText = result.bestTranscription.formattedString
            print("音声認識結果: \(spokenText)") // 結果をログ出力
        }

        // エラー発生または認識が終了した場合は停止処理
        if error != nil || result?.isFinal == true {
            self.audioEngine.stop()
            node.removeTap(onBus: 0)
            self.recognitionRequest = nil
            self.recognitionTask = nil
        }
    }
}
```

### 3. 停止処理
```swift
// 音声認識と録音を停止する関数
func stopRecording() {
    audioEngine.stop() // 音声エンジンの停止（録音終了）
    audioEngine.inputNode.removeTap(onBus: 0) // マイク入力のタップを解除
    recognitionRequest?.endAudio() // 音声入力の終了を通知
    recognitionTask?.cancel() // 認識処理をキャンセル
}
```

## ✅ 実装してみた感想・注意点
・日本語の認識精度はかなり高い
・シミュレーターでは動かないので、実機テスト必須
・録音セッションが長くなると認識が途切れることがある（短く区切ると安定）

## 🧩 まとめ
**Speech Framework** を使うと、iOSアプリに簡単に音声認識を組み込めました。
買い物リストの音声入力など、ユーザーの手間を減らすインターフェースとしてとても有効なので、積極的に取り入れたいと思いました。