Failed to execute 'createMediaElementSource' on 'AudioContext': HTMLMediaElement already connected previously to a different MediaElementSourceNode
Web Audio APIを初めて使うと次のエラーが出る場合があります。
Uncaught DOMException: Failed to execute 'createMediaElementSource' on 'AudioContext': HTMLMediaElement already connected previously to a different MediaElementSourceNode.
このエラーを日本語にすると
DOMExceptionが発生しました: 'AudioContext'で 'createMediaElementSource'を実行できませんでした:HTMLMediaElementはすでに別のMediaElementSourceNodeに接続されています。
という意味です。早い話、createMediaElementSource()を2回実行しないでねってことです。
エラーの回避方法
HTMLMediaElementをWeakMapオブジェクトで管理します。
var audioEle; var audioSourceNode; var wm = new WeakMap(); if(audioSourceNode){ audioSourceNode.disconnect(); } // WeakMapでHTMLMediaElementを管理する if (wm.has(audioEle)) { audioSourceNode = wm.get(audioEle); } else { audioSourceNode = audioCtx.createMediaElementSource(audioEle); wm.set(audioEle, audioSourceNode); }
使用例
次のコードは音声ファイルを読み込んで自動再生します。
<!doctype html> <html> <head> <meta charset="UTF-8"> </head> <body ondrop="onDrop(event);" ondragover="onDragOver(event);"> <script> var audioCtx; var analyserNode; var audioSourceNode; var audioEle; var wm = new WeakMap(); var firstFlag = true; window.onload= function(){ audioEle = document.getElementById('myAudio'); audioEle.autoplay = true; audioEle.preload = 'auto'; } function onDragOver(event){ event.preventDefault(); } function onDrop(event){ onAddFile(event); event.preventDefault(); } function onAddFile(event) { var files; var reader = new FileReader(); if(event.target.files){ files = event.target.files; }else{ files = event.dataTransfer.files; } reader.onload = function (event) { if(firstFlag){ // AudioContextの生成 audioCtx = new AudioContext(); firstFlag = false; } audioEle.onloadeddata = function (){ if(audioSourceNode){ audioSourceNode.disconnect(); } // WeakMapでHTMLMediaElementを管理する if (wm.has(audioEle)) { audioSourceNode = wm.get(audioEle); } else { audioSourceNode = audioCtx.createMediaElementSource(audioEle); wm.set(audioEle, audioSourceNode); } // AnalyserNodeの生成 if(analyserNode){ analyserNode.disconnect(); } analyserNode = audioCtx.createAnalyser(); audioSourceNode.connect(analyserNode); analyserNode.connect(audioCtx.destination); }; audioEle.onerror = function (e) { alert("このファイルは読み込めません。"); } audioEle.src = reader.result; }; if (files[0]){ reader.readAsDataURL(files[0]); } } </script> <input type="file" id="inputfile" onchange="onAddFile(event);" style="padding:0;width:240px;"> <br> <br> <audio id="myAudio" controls></audio> <br> </body> </html>
複数回、音声ファイルを読み込んでもエラーがでないようになりました。
では、各自の作業に戻りましょう :-)
参考サイト
WeakMap (MDN web docs)
スポンサーリンク
関連記事
公開日:2019年02月12日
記事NO:02729