ホーム > カテゴリ > HTML5・JavaScript >

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