0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Vue.js】環境によって audio が再生されない問題とその対処法(音声リソースの解放)

Posted at

🎧 問題の概要

Vue.jsで構築したアプリケーションで、複数の音声を再生するツールを開発していました。

音声は以下のような仕様で再生される設計です:

  • 各音声に対して「再生ボタン」が1つずつ
  • 各ボタンを押すと、対応する音声ファイルを1回だけ再生

このとき、一部の環境で音声が再生されないバグが発生しました。

❗ 発生した問題

以下のような症状が報告されました:

  • Google Chromeでは正常に動作
  • Microsoft Edgeでは一部再生されない
  • 特定の端末で、数ページに1回の頻度で発生
  • Console上にエラーログは出力されない
  • キャッシュ削除後に再生できるようになる場合もある

🛠️ 原因と推測

音声再生部分のロジックは共通のAudioインスタンスを使い回す構造で、再生終了後もオーディオリソースが残っていた可能性があります。

このため、以下のような状況で不具合が発生していたと推測されます:

  • オーディオがGC(ガベージコレクション)されずに残り続ける
  • ブラウザの制限により新しいAudioインスタンスの生成・再生がブロックされる
  • Edgeなど、環境によってこの影響が顕著に表れる

✅ 解決策:音声再生完了後にリソースを明示的に解放

再生完了時点で、使用したAudioインスタンスを明示的に破棄することで、問題を解決できました。

1. doneFlag を監視して音声を解放

音声の再生が完了したことを示すフラグ done_flag をwatchし、true になったタイミングでAudioを解放します。

// Vue コンポーネント内
watch: {
  nowPlay(newVal) {
    if (newVal) {
      this.releaseAudio(); // 再生完了後にAudioリソースを解放
    }
  }
}

2. releaseAudio() メソッドでインスタンスを解放

methods: {
  releaseAudio() {
    if (this.audio) {
      this.audio.pause();       // 再生停止
      this.audio.src = '';      // ソースクリア
      this.audio = null;        // インスタンス解放
      console.log("release");
    }
  }
}

3. コンポーネント破棄時にも解放処理を追加

beforeDestroy() {
  this.releaseAudio(); // コンポーネント破棄前に確実にAudioを解放
}

🎉 効果

この修正を加えた以降、すべての環境で音声が安定して再生されるようになりました。
特にEdgeや、キャッシュが絡んでいた端末でも、再現性のある不具合が完全に解消されました。

💬 補足

今回の仕様では「1回再生した音声は2回目以降再生できない」設計だったため、解放処理は特に有効でした。

同様の構成で音声プレイヤーを使う場合も、再生終了後にAudioを明示的に破棄することをおすすめします。

一見エラーが出ないために原因が特定しづらく、ブラウザごとの差異に注意が必要です。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?