创建无缝音频循环 - Web
Create Seamless Loop of Audio - Web
我想创建一个音频文件的无缝循环。但在我目前使用的所有方法中,结束和开始之间存在明显的差距。
这是我到目前为止尝试过的:
第一种方法是使用 HTML 中的音频并循环播放,但从曲目的结尾到开头仍然存在明显的延迟。
<audio loop autoplay>
<source src="audio.mp3" 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 = "sounds/back_music.ogg";
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();
但是由于浏览器中的毫秒数不够一致或不够精细,因此效果不是很好,但它确实比音频的正常 "loop" 属性 好得多。
任何人都可以指导我朝着正确的方向无缝循环播放音频吗?
您可以改用 Web Audio API。这有一些注意事项,但它可以让您准确地循环到单个样本级别。
注意事项是您必须将整个文件加载到内存中。这对于大文件可能不实用。如果文件只有几秒钟,应该没有问题。
第二个是您必须手动编写控制按钮(如果需要),因为 API 具有低级方法。这意味着播放、pause/stop、静音、音量等。扫描和可能的暂停本身就是一个挑战。
最后,并非所有浏览器 support Web Audio API - 在这种情况下,您将不得不回退到常规音频 API 甚至 Flash,但如果您的目标是现代浏览器,这不应该是现在的大问题。
例子
这将加载一个 4 小节鼓循环并在循环播放时没有任何间隙。主要步骤是:
- 它从支持 CORS 的源加载音频(这很重要,要么使用与您的页面相同的域,要么设置外部服务器以允许跨源使用,就像 Dropbox 在本例中为我们所做的那样)。
- AudioContext 然后解码加载的文件
- 解码文件用于源节点
- 源节点连接到输出
- 循环已启用,缓冲区从内存中播放。
var actx = new (AudioContext || webkitAudioContext)(),
src = "https://dl.dropboxusercontent.com/s/fdcf2lwsa748qav/drum44.wav",
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>
有一个非常简单的解决方案,只需使用 loopify 它利用 html5 网络音频 api 并且可以很好地处理许多格式,而不仅仅是 wav开发者说。
<script src="loopify.js" type="text/javascript"></script>
<script>
loopify("yourfile.mp3|ogg|webm|flac",ready);
function ready(err,loop){
if (err) {
console.warn(err);
}
loop.play();
}
</script>
这会自动播放文件,如果你想要开始和停止按钮,例如看看他的demo
我想创建一个音频文件的无缝循环。但在我目前使用的所有方法中,结束和开始之间存在明显的差距。
这是我到目前为止尝试过的:
第一种方法是使用 HTML 中的音频并循环播放,但从曲目的结尾到开头仍然存在明显的延迟。
<audio loop autoplay>
<source src="audio.mp3" 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 = "sounds/back_music.ogg";
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();
但是由于浏览器中的毫秒数不够一致或不够精细,因此效果不是很好,但它确实比音频的正常 "loop" 属性 好得多。
任何人都可以指导我朝着正确的方向无缝循环播放音频吗?
您可以改用 Web Audio API。这有一些注意事项,但它可以让您准确地循环到单个样本级别。
注意事项是您必须将整个文件加载到内存中。这对于大文件可能不实用。如果文件只有几秒钟,应该没有问题。
第二个是您必须手动编写控制按钮(如果需要),因为 API 具有低级方法。这意味着播放、pause/stop、静音、音量等。扫描和可能的暂停本身就是一个挑战。
最后,并非所有浏览器 support Web Audio API - 在这种情况下,您将不得不回退到常规音频 API 甚至 Flash,但如果您的目标是现代浏览器,这不应该是现在的大问题。
例子
这将加载一个 4 小节鼓循环并在循环播放时没有任何间隙。主要步骤是:
- 它从支持 CORS 的源加载音频(这很重要,要么使用与您的页面相同的域,要么设置外部服务器以允许跨源使用,就像 Dropbox 在本例中为我们所做的那样)。
- AudioContext 然后解码加载的文件
- 解码文件用于源节点
- 源节点连接到输出
- 循环已启用,缓冲区从内存中播放。
var actx = new (AudioContext || webkitAudioContext)(),
src = "https://dl.dropboxusercontent.com/s/fdcf2lwsa748qav/drum44.wav",
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>
有一个非常简单的解决方案,只需使用 loopify 它利用 html5 网络音频 api 并且可以很好地处理许多格式,而不仅仅是 wav开发者说。
<script src="loopify.js" type="text/javascript"></script>
<script>
loopify("yourfile.mp3|ogg|webm|flac",ready);
function ready(err,loop){
if (err) {
console.warn(err);
}
loop.play();
}
</script>
这会自动播放文件,如果你想要开始和停止按钮,例如看看他的demo