使用canvas+web audio制作动态音频时出现Failed to execute 'createMediaElementSource' on 'AudioContext': HTMLMediaElement already connected previously to a different MediaElementSourceNode报错。该如何解决呢,代码如下:
class="player_page"> <canvas id="canvas"> canvas> div> ```html
let ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
let audioArray = [
'../music/1.mp3',
'../music/2.mp3',
'../music/3.mp3',
'../music/4.mp3',
'../music/4.mp3',
'../music/4.mp3',
'../music/4.mp3',
'../music/4.mp3'
];
let audioNum = 0;
let oAudio = document.getElementById('music_mp3');
oAudio.crossOrigin = 'anonymous';
oAudio.src = audioArray[audioNum];
// 获取canvas元素宽高
let WIDTH = canvas.width;
let HEIGHT = canvas.height;
let Play=document.getElementById('play');
Play.onclick=function(){
let oCtx = new AudioContext();
let audioSrc = oCtx.createMediaElementSource(oAudio);
let analyser=oCtx.createAnalyser();
audioSrc.connect(analyser);
analyser.connect(oCtx.destination);
analyser.fftSize=512;
let bufferLength=analyser.frequencyBinCount;
let dataArray=new Uint8Array(bufferLength);
let barWidth=(WIDTH/bufferLength)-1;
let barHeight;
function draw(){
analyser.getByteFrequencyData(dataArray);
let x=0;
ctx.clearRect(0,0,WIDTH,HEIGHT);
for(let i=0;ifillStyle='rgb(228,255,255)';
ctx.fillRect(x,HEIGHT,barWidth,-barHeight);
x+=barWidth+1;
}
window.requestAnimationFrame(draw);
};
draw();
}
这个错误通常是因为在使用 HTMLMediaElement 创建音频源时,该元素已经被连接到了其他 MediaElementSourceNode 。
解决方案是在连接 MediaElementSourceNode 前,将 HTMLMediaElement 与任何现有连接断开,或者在使用完 HTMLMediaElement 后,使用MediaElementSourceNode.disconnect()方法断开连接。
例如:
这应该解决您的问题。如果仍然存在问题,请考虑检查您的代码,以确保没有在同一时间连接多个 MediaElementSourceNode 到 HTMLMediaElement。
意思就是 MediaElement 已经被其他的资源打开占用了 无法二次执行创建 oCtx.createMediaElementSource,可以设置一个变量 用来判断是否执行过 如果执行过就跳过create这一步 或者先释放掉链接 然后再执行
方法一
现在有这么一个方法可以排除,就是提前将audioContext.destination和mediaElementSource.disconnect(),然后再重新使用AudioContext的createMediaElementSource来创建新的链接。
首先,可以尝试检测是否已经存在连接:
// check if already connected if (audioContext.getOutputTimestamp().contextTime !== 0 && mediaElementSource.mediaElement !== null) { // disconnect existing connections mediaElementSource.disconnect(); audioContext.destination.disconnect(); }
方法二
在使用canvas+web audio时,如果HTMLMediaElement已经连接到AudioContext,则会出现此错误。解决办法是先断开当前的连接,然后再重新连接。可以使用下面的代码:
//断开连接
if (audioCtx.state === 'running') {
audioCtx.disconnect();
}
//重新连接
var source = audioCtx.createMediaElementSource(audio);
source.connect(audioCtx.destination);
方法三
Failed to execute 'createMediaElementSource' on 'AudioContext': HTMLMediaElement already connected previously to a different MediaElementSourceNode报错,一般是由于重复连接了同一个audio元素导致的,可以在使用完前一个audio元素后执行disconnect()方法来解决该问题。例如:
let audio = new Audio(); // 创建新音频
let audioContext = new AudioContext(); // 创建AudioContext实例
let sourceNode = audioContext.createMediaElementSource(audio); // 使用createMediaElementSource方法连接Audio到AudioContext
// 这里可以使用sourceNode来处理音频,此处省略。
sourceNode.disconnect(); // 断开之前的sourceNode的连接
这个错误是由于您在同一个 HTMLMediaElement 上多次调用 createMediaElementSource 方法造成的。
一个 HTMLMediaElement 只能连接到一个 AudioContext 中的 MediaElementSourceNode 一次。因此,您需要在每次使用之前确保该 HTMLMediaElement 未连接到任何其他的 MediaElementSourceNode。
下面是修复代码的示例:
let audioCtx = new (window.AudioContext || window.webkitAudioContext)();
let audioElement = document.getElementById("myAudioElement");
function createMediaElementSource() {
if (audioCtx.state === 'suspended') {
audioCtx.resume();
}
if (audioElement.srcObject) {
audioElement.srcObject = null;
}
let mediaElementSource = audioCtx.createMediaElementSource(audioElement);
// ... 其他的处理 ...
}
希望这对您有帮助
这个问题就判断是否有audioContext(即改为全局)
medioElementSource是否已经创建(即改为全局)
这个错误通常是因为创建了多个音频上下文或者已经连接了其他的 MediaElementSourceNode,导致无法再次创建。
解决方法:
只创建一个 AudioContext 实例,并且在整个音频处理生命周期内使用它。
在每次创建音频源前,断开与之前的 MediaElementSourceNode 的连接。
代码示例如下:
let ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
let audioArray = [
'../music/1.mp3',
'../music/2.mp3',
'../music/3.mp3',
'../music/4.mp3',
'../music/4.mp3',
'../music/4.mp3',
'../music/4.mp3',
'../music/4.mp3'
];
let audioNum = 0;
let oAudio = document.getElementById('music_mp3');
oAudio.crossOrigin = 'anonymous';
oAudio.src = audioArray[audioNum];
// 获取canvas元素宽高
let WIDTH = canvas.width;
let HEIGHT = canvas.height;
let Play=document.getElementById('play');
let oCtx = new AudioContext();
Play.onclick=function(){
if(oCtx.state === 'running'){
oCtx.suspend();
}else{
oCtx.resume();
}
let audioSrc = oCtx.createMediaElementSource(oAudio);
let analyser=oCtx.createAnalyser();
audioSrc.connect(analyser);
analyser.connect(oCtx.destination);
analyser.fftSize=512;
let bufferLength=analyser.frequencyBinCount;
let dataArray=new Uint8Array(bufferLength);
let barWidth=(WIDTH/bufferLength)-1;
let barHeight;
function draw(){
analyser.getByteFrequencyData(dataArray);
let x=0;
ctx.clearRect(0,0,WIDTH,HEIGHT);
for(let i=0;i<bufferLength;i++){
barHeight=dataArray[i];
ctx.fillStyle='rgb(228,255,255)';
ctx.fillRect(x,HEIGHT,barWidth,-barHeight);
x+=barWidth+1;
提供参考实例:https://www.xyhtml5.com/5561.html
【实例同你现象类似,可参考下解题思路】
这个报错通常是因为你已经把一个 HTMLMediaElement 连接到了 AudioContext 的其他 MediaElementSourceNode。为了解决这个问题,可以采取以下措施:
在使用 createMediaElementSource 函数前先断开与该 HTMLMediaElement 相关的所有连接。
使用替代方法,例如 AudioBufferSourceNode,把音频数据读入到 AudioContext 中。
使用 detach 函数来断开与该 HTMLMediaElement 相关的所有连接,然后再重新连接。
检查是否有其他代码在该 HTMLMediaElement 上创建了 MediaElementSourceNode,如果是,请将其关闭或删除。
这些方法中的任意一个都可以帮助你解决 Failed to execute 'createMediaElementSource' on 'AudioContext': HTMLMediaElement already connected previously to a different MediaElementSourceNode 的报错。根据你的代码实现情况选择一个适合的方法。
该报错通常是由于在同一个页面中创建多个AudioContext实例导致的。如果已经创建了一个AudioContext实例,则不能再创建多个实例。
解决方法:只需在整个页面上创建一个AudioContext实例即可。将以下代码放置在页面的最顶部:
let oCtx = new (window.AudioContext || window.webkitAudioContext)();
然后,在代码中使用该实例:
let audioSrc = oCtx.createMediaElementSource(oAudio);
let analyser = oCtx.createAnalyser();
audioSrc.connect(analyser);
analyser.connect(oCtx.destination);
这样,就不会再出现Failed to execute 'createMediaElementSource' on 'AudioContext': HTMLMediaElement already connected previously to a different MediaElementSourceNode报错了。