Javascript 删除createMediaElementSource

Javascript 删除createMediaElementSource,javascript,mediaelement,Javascript,Mediaelement,我在谷歌上搜索过这个问题,但什么也找不到。 我需要删除source=createMediaElementSource,以便再次创建它。我使用的是一个音频分析器,每次使用ajax加载指定曲目时都必须加载该分析器。只要你转到另一页,然后再返回,分析器就不见了。因此,我需要以某种方式重新初始化它 我的代码: var analyserElement = document.getElementById('analyzer'); var canvas, ctx, source, context, analy

我在谷歌上搜索过这个问题,但什么也找不到。 我需要删除
source=createMediaElementSource
,以便再次创建它。我使用的是一个音频分析器,每次使用ajax加载指定曲目时都必须加载该分析器。只要你转到另一页,然后再返回,分析器就不见了。因此,我需要以某种方式重新初始化它

我的代码:

var analyserElement = document.getElementById('analyzer');
var canvas, ctx, source, context, analyser, fbc_array, bars, bar_x,
    bar_width, bar_height;

function analyzerSetElements() {
    var analyserElement = document.getElementById('analyzer');
}

function analyzerInitialize() {
    if (context == undefined) {
    context = new AudioContext();
    }
    analyser = context.createAnalyser();
    canvas = analyserElement;
    ctx = canvas.getContext('2d');
    source = context.createMediaElementSource(audio);
    source.connect(analyser);
    analyser.connect(context.destination);
    frameLooper();
}

function analyzerStop(){
    context = undefined;
    analyser = undefined;
    source = undefined;
}

function frameLooper() {
    canvas.width = canwidth;
    canvas.height = canheight;
    ctx.imageSmoothingEnabled = false;
    fbc_array = new Uint8Array(analyser.frequencyBinCount);
    analyser.getByteFrequencyData(fbc_array);
    ctx.clearRect(0, 0, canvas.width, canvas.height); // Clear the canvas
    ctx.fillStyle = "white"; // Color of the bars
    function valBetween(v, min, max) {
        return (Math.min(max, Math.max(min, v)));
    }
    var beatc = fbc_array[2] / 4;
    var beatround = Math.round(beatc);
    //if (beatround < 10) {
    //    ctx.globalAlpha = '0.1125';
    //}
    //else {
    //    ctx.globalAlpha = '0.' + beatround;
    //}
    bars = canbars;
    for (var i = 0; i < bars; i += canmultiplier) {
        bar_x = i * canspace;
        bar_width = 2;
        bar_height = -3 - (fbc_array[i] / 2);
        ctx.fillRect(bar_x, canvas.height, bar_width, bar_height);
    }
    window.requestAnimationFrame(frameLooper);
    console.log('Looped')
}
var analyserElement=document.getElementById('analyzer');
var画布、ctx、源、上下文、分析器、fbc_数组、条、条,
钢筋宽度、钢筋高度;
函数分析器setElements(){
var analyserElement=document.getElementById('analyzer');
}
函数分析器初始化(){
如果(上下文==未定义){
上下文=新的AudioContext();
}
Analyzer=context.createAnalyzer();
画布=分析元素;
ctx=canvas.getContext('2d');
source=context.createMediaElementSource(音频);
源。连接(分析仪);
分析器.连接(上下文.目的地);
frameLooper();
}
函数分析器stop(){
上下文=未定义;
分析仪=未定义;
来源=未定义;
}
函数frameLooper(){
canvas.width=canwidth;
canvas.height=canheight;
ctx.imageSmoothingEnabled=假;
fbc_阵列=新UINT8阵列(分析仪频率b计数);
分析仪。GetByTefFrequencyData(fbc_阵列);
ctx.clearRect(0,0,canvas.width,canvas.height);//清除画布
ctx.fillStyle=“white”//条的颜色
函数值(v、最小值、最大值){
返回值(Math.min(max,Math.max(min,v));
}
var-beatc=fbc_数组[2]/4;
var beatround=数学圆(beatc);
//if(beatround<10){
//ctx.globalAlpha='0.1125';
//}
//否则{
//ctx.globalAlpha='0.'+beatround;
//}
钢筋=钢筋;
对于(变量i=0;i
因此,在运行
analyzerInitialize()
之后运行
analyzerStop()
时,仍然会出现以下错误:

audio.js:179未捕获的DomeException:无法执行 “AudioContext”上的“createMediaElementSource”:HTMLMediaElement已存在 以前已连接到其他MediaElementSourceNode


我如何使它运行
analyzerInitialize()
永远不会失败?

我也面临同样的问题。不幸的是,我没有找到如何从音频元素创建
MediaElementSourceNode
。不过,可以通过使用
WeakMap
来记住
MediaElementSourceNode
来解决此问题:

var MEDIA_ELEMENT_NODES=new WeakMap();
函数分析器初始化(){
如果(上下文==未定义){
上下文=新的AudioContext();
}
Analyzer=context.createAnalyzer();
画布=分析元素;
ctx=canvas.getContext('2d');
if(媒体元素节点有(音频)){
source=媒体\元素\节点.get(音频);
}否则{
source=context.createMediaElementSource(音频);
媒体元素节点集(音频、源);
}
源。连接(分析仪);
分析器.连接(上下文.目的地);
frameLooper();
}

使用
WeakMap
可以避免内存问题。

您可以将
上下文
设置为全局定义的变量,而不是重新定义变量

context = context || new AudioContext();
source = source || context.createMediaElementSource(audio);

您可能需要在卸载时断开()或其他连接。如何断开?你能给我正确的语法吗?我不知道,我没有把它弄得够乱,但是类似于
window.onunload=function(){source.disconnect();}(更干净、更专业)。看见您也可以在
connect()
之前调用它……这也会停止音乐,我不希望这样。