让我说我不想拥有一个具有可变音频源的应用程序作为音频标签,如下所示:
<audio preload="auto" src="1.mp3" controls="" class="muzz"></audio>
<audio preload="auto" src="track.mp3" controls="" class="muzz"></audio>
根据播放的内容,应将其传递给createMediaElementSource,然后将声音发送到分析器,并使用它完成各种操作,但不起作用:
var trackName;
//get the source of clicked track
$(".muzz").on("play", function(){
trackName = $(this).attr("src");
console.log("got a source: ", trackName);
audio = new Audio();
audio.src=trackName;
context = new AudioContext();
analyser = context.createAnalyser();
source = context.createMediaElementSource(audio);
source.connect(analyser);
analyser.connect(context.destination);
letsDraw();
});
控制台日志显示正确的源名称,letsDraw()方法应该绘制音频播放的频谱图:
function letsDraw(){
console.log("draw called");
window.requestAnimationFrame(letsDraw);
fbc_array = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(fbc_array); //get frequency from the analyser node
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle="white";
ctx.font = "bold 12px Arial";
ctx.fillText("currently playing:" + trackName, 10, 20);//this works
bars = 150;
for(var i = 0; i < analyser.frequencyBinCount; i++){ //but this doesn't
/*fill the canvas*/
x = i *2;
barWidth = 1;
barHeight = -(fbc_array[i]/1.8);
//colours react to the frequency loudness
hue = parseInt(500 * (1 - (barHeight / 200)), 10);
ctx.fillStyle = 'hsl(' + hue + ',75%,50%)';
ctx.fillRect(x, canvas.height, barWidth, barHeight);
}
}
它可以正常使用一套音频源,但是因为可变来源而失败,任何想法都会非常受欢迎。
当然,控制台中根本没有任何错误。
答案 0 :(得分:3)
在第一个代码块的顶部,试试这个:
var trackName,
context = new AudioContext();
从点击处理程序中删除context = new AudioContext();
。
页面应该只有一个AudioContext。
答案 1 :(得分:3)
我没有得到的是为什么你把src放在一个新的Audio对象中,就像你已经拥有它们一样。
从<audio>
个标记创建源代码也更好。您只需创建一个在页面加载时运行的函数(因此,当页面上的所有内容都准备就绪时,您将无法获得有关尚未存在的元素的任何错误等。)
在我开始编写一段代码之前,您期望发生什么?是否可以同时播放两个标签,或者如果单击另一个播放则应该停止播放?如果它不应该同时播放,你最好制作一个<audio>
标签并创建两个按钮,每个按钮设置标签的src。
您的代码的另一个问题是您已经拥有<audio>
元素,并且当您希望它们播放时,您只需创建一个新的音频元素并将src附加到它。这背后的逻辑是什么?
编辑:
Here is an example使用只有一个<audio>
元素的多个来源。
HTML代码应如下所示:
<audio id="player" src="" autoplay="" controls=""></audio>
<div id="buttons">
<!--The javascript code will generate buttons with which you can play the audio-->
</div>
然后你使用这个JS代码:
onload = function () { //this will be executed when the page is ready
window.audioFiles = ['track1.mp3', 'track2.mp3']; //this is gonna be the array with all file names
window.player = document.getElementById('player');
window.AudioContext = window.AudioContext || window.webkitAudioContext;
context = new AudioContext();
source = context.createMediaElementSource(player);
analyser = context.createAnalyser();
source.connect(analyser);
analyser.connect(context.destination);
//now we take all the files and create a button for every file
for (var x in audioFiles) {
var btn = document.createElement('button');
btn.innerHTML = audioFiles[x];
btn.onclick = function () {
player.src = audioFiles[x];
//so when the user clicks the button, the new source gets appended to the audio element
}
document.getElementById('buttons').appendChild(btn);
}
}
希望评论解释得足够好
EDIT2:
您想知道如何为多个元素执行此操作。您要做的是在页面加载时创建所有音频元素,并为其创建所有源。这将减少开始播放音频时的混乱。代码为here。
你需要做的就是拥有为你拥有的每个媒体文件运行的for循环,它将为相应的源创建一个音频元素,然后为它创建一个sourcenode(createMediaElementSource
),并将该sourcenode连接到分析器。
我还想谈谈你的可视化代码。如果不覆盖字体,颜色或任何内容,则不需要执行每个动画帧。一旦初始化就足够了。