Create Seamless Loop of Audio - Web(打造音网的无缝环路)
问题描述
我要创建音频文件的无缝循环。但在我到目前为止使用的所有方法中,结束和开始之间存在明显的差距。
这是我到目前为止尝试的内容:
第一种方法是在HTML中使用音频,它会循环,但从曲目末尾转到开头时仍然会有明显的延迟。
<audio loop autoplay>
<source src="YXVkaW8ubXAz" type="audio/mpeg">
<audio>
然后我在JavaScript中尝试,结果相同:
let myAudio = new Audio(file);
myAudio.loop = true;
myAudio.play();
之后我尝试了这个(根据this answer)
myAudio.addEventListener(
'timeupdate',
function() {
var buffer = .44;
if (this.currentTime > this.duration - buffer) {
this.currentTime = 0;
this.play();
}
},
false
);
我摆弄了一下缓冲区,但我得到它只是为了缩小差距,而不是把它完全排除在外。
我求助于库SeamlessLoop
(GitHub),让它在Chromium浏览器中无缝循环(但不是在最新的Safari中)。没有在其他浏览器中测试)。我为此使用的代码:
let loop = new SeamlessLoop();
// My File is 58 Seconds long. Btw there aren't any gaps in the file.
loop.addUri(file, 58000, 'sound1');
loop.callback(soundsLoaded);
function soundsLoaded() {
let n = 1;
loop.start('sound' + n);
}
编辑:我尝试了另一种方法:通过两个不同的音频元素循环它:
var current_player = "a";
var player_a = document.createElement("audio");
var player_b = document.createElement("audio");
player_a.src = "c291bmRzL2JhY2tfbXVzaWMub2dn";
player_b.src = player_a.src;
function loopIt(){
var player = null;
if(current_player == "a"){
player = player_b;
current_player = "b";
}
else{
player = player_a;
current_player = "a";
}
player.play();
/*
3104.897 is the length of the audio clip in milliseconds.
Received from player.duration.
This is a different file than the first one
*/
setTimeout(loopIt, 3104.897);
}
loopIt();
但由于浏览器中的毫秒数不一致或不够精细,这不能很好地工作,但它的工作效果确实比音频的正常"循环"属性好得多。
有人能将我引导到正确的方向以无缝循环音频吗?
推荐答案
您可以改用Web Audio API。这有几个注意事项,但它将允许您准确地向下循环到单个样本级别。
需要注意的是,您必须将整个文件加载到内存中。对于大文件,这可能不切实际。但是,如果文件只有几秒钟,应该不会有任何问题。第二个问题是,您必须手动编写控制按钮(如果需要),因为API采用的是低级方法。这意味着播放、暂停/停止、静音、音量等。扫描和可能暂停本身都是一项挑战。
最后,并非所有浏览器support Web Audio API-在这种情况下,您将不得不使用常规的Audio API,甚至Flash,但如果您的目标是现代浏览器,这在当今应该不是什么大问题。
示例
这将加载一个4小节的鼓循环,并在循环时没有任何间隙地播放。主要步骤如下:
- 它从启用CORS的源加载音频(这一点很重要,请使用与您的页面相同的域,或者设置外部服务器以允许跨域使用,就像本例中Dropbox为我们所做的那样)。
- AudioContext然后解码加载的文件
- 解码后的文件用于源节点
- 源节点已连接到输出
- 已启用循环,并从内存播放缓冲区。
var actx = new (AudioContext || webkitAudioContext)(),
src = "aHR0cHM6Ly9kbC5kcm9wYm94dXNlcmNvbnRlbnQuY29tL3MvZmRjZjJsd3NhNzQ4cWF2L2RydW00NC53YXY=",
audioData, srcNode; // global so we can access them from handlers
// Load some audio (CORS need to be allowed or we won't be able to decode the data)
fetch(src, {mode: "cors"}).then(function(resp) {return resp.arrayBuffer()}).then(decode);
// Decode the audio file, then start the show
function decode(buffer) {
actx.decodeAudioData(buffer, playLoop);
}
// Sets up a new source node as needed as stopping will render current invalid
function playLoop(abuffer) {
if (!audioData) audioData = abuffer; // create a reference for control buttons
srcNode = actx.createBufferSource(); // create audio source
srcNode.buffer = abuffer; // use decoded buffer
srcNode.connect(actx.destination); // create output
srcNode.loop = true; // takes care of perfect looping
srcNode.start(); // play...
}
// Simple example control
document.querySelector("button").onclick = function() {
if (srcNode) {
srcNode.stop();
srcNode = null;
this.innerText = "Play";
} else {
playLoop(audioData);
this.innerText = "Stop";
}
};
<button>Stop</button>
这篇关于打造音网的无缝环路的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:打造音网的无缝环路


- 在不使用循环的情况下查找数字数组中的一项 2022-01-01
- 如何向 ipc 渲染器发送添加回调 2022-01-01
- 从原点悬停时触发 translateY() 2022-01-01
- 是否可以将标志传递给 Gulp 以使其以不同的方式 2022-01-01
- 如何显示带有换行符的文本标签? 2022-01-01
- 我不能使用 json 使用 react 向我的 web api 发出 Post 请求 2022-01-01
- 使用 iframe URL 的 jQuery UI 对话框 2022-01-01
- 为什么悬停在委托事件处理程序中不起作用? 2022-01-01
- 如何调试 CSS/Javascript 悬停问题 2022-01-01
- 为什么我的页面无法在 Github 上加载? 2022-01-01