💬

AVSpeechSynthesizerがなぜか動かなかったが、AVAudioSessionと一緒に使うと動く

2025/01/11に公開

結論

import SwiftUI
import AVFoundation

struct HomeView: View {
  @State private var text = "こんにちは、今日はいい天気ですね!"
  var speechSynthesizer = AVSpeechSynthesizer()
    
  var body: some View {
    VStack(spacing: 20) {
      Text(text)
        .font(.system(size: 24, weight: .bold))
      Button(action: {
        do {
          // ↓がなぜか必要
          let audioSession = AVAudioSession.sharedInstance()
          try audioSession.setCategory(.playAndRecord, mode: .measurement, options: .duckOthers)
        } catch {
        }
        let speechUtterance = AVSpeechUtterance(string: text)
        // ↓siriの設定を優先するみたいなやつ
        speechUtterance.prefersAssistiveTechnologySettings = true
        speechSynthesizer.speak(speechUtterance)
      }, label: {
        Text("Speak")
          .frame(width: 160, height: 40)
          .font(.title)
          .padding()
          .background(Color.orange)
          .foregroundColor(.white)
          .cornerRadius(10)
      })
    }
    .padding()
  }
}

経緯

iphoneに固定の文字列を喋らせる方法を探してまして、下記の動画に辿りつきました
https://developer.apple.com/jp/videos/play/wwdc2020/10022/


ちょっと文字が被ってみづらいですが、たった3行でできるようです。
ですが、自分の持ってるiphone se第三世代(ios 18.2.1)では再生されませんでした。
※同じ会社の人のiphoneで試してもらった時は、再生されたようです。

ログには、

#FactoryInstall Unable to query results, error: 5

という気になるエラーが出力されますが、これでググっても特に有力な情報は発見できず。

ここで、たまたま、同時に調べていた、文字起こしの処理を動かした後だと、なぜかちゃんと再生されることに気づきました。
その文字起こしのコードを極限まで削ると、先ほどのコードになりました。

今の所、原因や仕組みは全くわかってないですが、同様に困ってる人がいそうな気がしたので、記事にしてみました。

しくみのテックブログ

Discussion