🎧 問題の概要
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を明示的に破棄することをおすすめします。
一見エラーが出ないために原因が特定しづらく、ブラウザごとの差異に注意が必要です。