🙉

iPhoneで音声が出ない(React, Next.js)

2024/08/28に公開

前回の記事でギャルと話せるアプリを作ったことを書きましたが、デプロイしたところiPhoneのSafari上ではギャルの声が出ないという問題が起きました。
https://zenn.dev/koda_momo/articles/ec29df2a1d97e7

今回は音声が出ない時のReact, Next.jsでの対応方法についてまとめたいと思います。

前提:利用していた音声再生のメソッド

今回は下記方法で音声を再生させていました。

const uttr = new SpeechSynthesisUtterance(data);
uttr.lang = "ja-JP";
speechSynthesis.speak(uttr);

原因

iPhoneのSafariでは、ユーザーから何かしらアクションしないと、音声が再生されない仕組みになっているそうです。このロックを解除するにはユーザーからアクションを受けて、一回何かしらを再生させる必要があります。

対応方法

今回は画面を最初にタッチした際に(ユーザーのアクション)、一旦無音の音声再生を走らせるようにしました。無音でも一度再生メソッドを走らせることができれば、その後は自由に再生ができるようになります。

  // 音声を流すことが有効か否か(2回以上走るの防止用)
  const [ableVoiceOutput, setAbleVoiceOutput] = useState(false);

  const enableVoiceOutput = useCallback(() => {
    const speechSynthesis = window.speechSynthesis;
    const utterance = new SpeechSynthesisUtterance("");
    speechSynthesis.speak(utterance);
    setAbleVoiceOutput(true);
    window.removeEventListener("touchend", enableVoiceOutput);
  }, []);

  useEffect(() => {
    if (!ableVoiceOutput) {
      // 画面をタッチした際、無音の音声再生メソッドを走らせるように予約しておく
      window.addEventListener("touchend", enableVoiceOutput);
    }
  }, [ableVoiceOutput, enableVoiceOutput]);

おわりに

ただ、意図的にロックされているものを無理やり解除するのはナンセンスだと思うので
アクセシビリティ的にはもっとユーザーが「自分の意思で再生した」と分かるようにした方が良いですね。

Discussion