2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

JavaScript で音声を順に再生する方法

Posted at

音声が複数個あっても順に再生したい!!!

非同期処理って難しいですね…
テキストを音声化して再生するといった動作を実装したのですがそこでハマったことをメモとして書き出していきます。

概要

  1. 音楽ファイルを用意する
  2. 音楽ファイルを DataURI Scheme 形式(base64) にエンコードする
  3. await を使って順に再生するように実装する

1. 音楽ファイルを用意する

適当な音楽ファイルを用意して読み込みます。
File API とか使えば読み込めるかと思います。
今回はサーバーにテキストを送ると音声データが返ってくる仕様だったので読み込む動作は割愛します。

2. 音楽ファイルを DataURI Scheme 形式(base64) にエンコードする

ローカルから読み込む場合は、File API の URL.createObjectURL() 使えばエンコードできると思います。
今回は送られてきた音声データを base64 にエンコードして返してくれるように自作 API を実装しました。

3. await を使って順に再生するように実装する

ここでループ回して await 使って音声再生… で終わると思っていたのですが、音声がすべて同時に再生されてしまい、うまくいきませんでした。
そこで Promise オブジェクトを作成し、音声の再生終了後までループが止まるように実装したところ、うまく動かすことができました。

for (const d of data) {
    const targetSoundBase64 = d.base64;

    // 音声の再生が終わるまでループを回さないように止めておく
    await new Promise((resolve) => {
        const sound = new Audio("data:audio/wav;base64," + targetSoundBase64);
        sound.play();
        sound.addEventListener('ended', async () => {
            // 音声終了後にいきなり次の音声が再生されてると違和感がすごいのでちょっとスリープかける
            await sleep(100);
            resolve();
        }, {once: true});
    });
}

最初は音声の秒数を取得してその曲が終わるタイミングで次の曲が再生されるように setTimeout を使おうかと考えていたのですが、こっちのほうがいい感じのコードになるかなと思われます。

まとめ

テキストチャットの音声化のような複数の音声データを順に再生するような状況になった場合、このように実装すればいいのではないでしょうか。

非同期処理、わかるようでわからず難しいなーと感じました。
もっと勉強頑張ります😇

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?