Web Audio API从暂停状态恢复
Web Audio API resume from pause
我经常读到使用Web audio API暂停/恢复音频文件是不可能的
但现在我看到了一个的例子,他们实际上让暂停和恢复成为可能。我试图弄清楚他们是如何做到的。我认为source.looping = false
可能是关键,但事实并非如此
现在,我的音频总是从一开始就重新播放。
这是我当前的代码
var context = new (window.AudioContext || window.webkitAudioContext)();
function AudioPlayer() {
this.source = context.createBufferSource();
this.analyser = context.createAnalyser();
this.stopped = true;
}
AudioPlayer.prototype.setBuffer = function(buffer) {
this.source.buffer = buffer;
this.source.looping = false;
};
AudioPlayer.prototype.play = function() {
this.source.connect(this.analyser);
this.analyser.connect(context.destination);
this.source.noteOn(0);
this.stopped = false;
};
AudioPlayer.prototype.stop = function() {
this.analyser.disconnect();
this.source.disconnect();
this.stopped = true;
};
有人知道该怎么做吗?
Oskar的回答和ayke的评论非常有用,但我缺少一个代码示例。所以我写了一个:http://jsfiddle.net/v3syS/2/我希望它能有所帮助。
var url = 'http://thelab.thingsinjars.com/web-audio-tutorial/hello.mp3';
var ctx = new webkitAudioContext();
var buffer;
var sourceNode;
var startedAt;
var pausedAt;
var paused;
function load(url) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
request.onload = function() {
ctx.decodeAudioData(request.response, onBufferLoad, onBufferError);
};
request.send();
};
function play() {
sourceNode = ctx.createBufferSource();
sourceNode.connect(ctx.destination);
sourceNode.buffer = buffer;
paused = false;
if (pausedAt) {
startedAt = Date.now() - pausedAt;
sourceNode.start(0, pausedAt / 1000);
}
else {
startedAt = Date.now();
sourceNode.start(0);
}
};
function stop() {
sourceNode.stop(0);
pausedAt = Date.now() - startedAt;
paused = true;
};
function onBufferLoad(b) {
buffer = b;
play();
};
function onBufferError(e) {
console.log('onBufferError', e);
};
document.getElementById("toggle").onclick = function() {
if (paused) play();
else stop();
};
load(url);
在当前浏览器(Chrome 43、Firefox 40)中,AudioContext:现在有"暂停"answers"恢复"方法
var audioCtx = new AudioContext();
susresBtn.onclick = function() {
if(audioCtx.state === 'running') {
audioCtx.suspend().then(function() {
susresBtn.textContent = 'Resume context';
});
} else if(audioCtx.state === 'suspended') {
audioCtx.resume().then(function() {
susresBtn.textContent = 'Suspend context';
});
}
}
(修改了来自的示例代码https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/suspend)
实际上,web-audio API可以为您完成暂停和播放任务。它知道音频上下文的当前状态(运行或挂起),所以你可以用这种简单的方式来做到这一点:
susresBtn.onclick = function() {
if(audioCtx.state === 'running') {
audioCtx.suspend()
} else if(audioCtx.state === 'suspended') {
audioCtx.resume()
}
}
我希望这能有所帮助。
在不花任何时间检查示例的源代码的情况下,我认为您将希望使用AudioBufferSourceNode的noteGrainOn方法(https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#methodsandparams-AudioBufferSourceNode)
只需记录您调用noteOff时进入缓冲区的距离,然后在新的AudioBufferSourceNode上恢复时从那里执行noteGrainOn。
这有道理吗?
编辑:有关更新的API调用,请参阅下面的注释
2019年第2版:有关更新的API调用,请参见MDN;https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode/start
对于chrome修复,每次你想播放声音时,都将其设置为:
if(audioCtx.state === 'suspended') {
audioCtx.resume().then(function() {
audio.play();
});
}else{
audio.play();
}
在WebAudio API中缺乏内置的暂停功能对我来说似乎是一个主要的疏忽。将来可能会使用计划中的MediaElementSource来实现这一点,这将使您能够将一个元素(支持暂停)连接到Web Audio。目前,大多数解决方案似乎都是基于记住播放时间(比如imbrizi的回答中所描述的)。当循环声音时(实现循环是否无间隙?),以及当允许动态更改声音的播放速率时(因为两者都会影响定时),这样的解决方法会出现问题。另一个同样破解且技术上不正确,但更简单的解决方法是:
source.playbackRate = paused?0.0000001:1;
不幸的是,0不是playbackRate的有效值(这实际上会暂停声音)。然而,出于许多实际目的,一些非常低的值,如0.000001,已经足够接近,并且不会产生任何声音输出。
UPDATE:这只对Chrome有效。Firefox(v29)尚未实现MediaElementAudioSourceNode.mediaElement
属性。
假设您已经有AudioContext引用和媒体源(例如通过AudioContext.createMediaElementSource()
方法调用),您可以在源上调用MediaElement.play()
和MediaElement.pause()
,例如
source.mediaElement.pause();
source.mediaElement.play();
不需要破解和变通方法,它是受支持的。如果您使用<audio>
标记作为源,则不应直接在JavaScript中的音频元素上调用pause,这将停止播放。
2017年,使用ctx.currentTime可以很好地跟踪歌曲中的点。下面的代码使用一个按钮(songStartPause)在播放和暂停之间切换;暂停按钮。为了简单起见,我使用了全局变量。变量musicStartPoint记录您在歌曲中的时间。音乐api以秒为单位记录时间。
将您的初始音乐起点设置为0(歌曲开头)
var ctx = new webkitAudioContext();
var buff, src;
var musicLoaded = false;
var musicStartPoint = 0;
var songOnTime, songEndTime;
var songOn = false;
songStartPause.onclick = function() {
if(!songOn) {
if(!musicLoaded) {
loadAndPlay();
musicLoaded = true;
} else {
play();
}
songOn = true;
songStartPause.innerHTML = "||" //a fancy Pause symbol
} else {
songOn = false;
src.stop();
setPausePoint();
songStartPause.innerHTML = ">" //a fancy Play symbol
}
}
使用ctx.currentTime从歌曲开始的时间减去歌曲结束的时间,并将此时间长度附加到您最初在歌曲中的距离。
function setPausePoint() {
songEndTime = ctx.currentTime;
musicStartPoint += (songEndTime - songOnTime);
}
加载/播放功能。
function loadAndPlay() {
var req = new XMLHttpRequest();
req.open("GET", "//mymusic.com/unity.mp3")
req.responseType = "arraybuffer";
req.onload = function() {
ctx.decodeAudioData(req.response, function(buffer) {
buff = buffer;
play();
})
}
req.send();
}
function createBuffer() {
src = ctx.createBufferSource();
src.buffer = buff;
}
function connectNodes() {
src.connect(ctx.destination);
}
最后,播放函数告诉歌曲从指定的musicStartPoint开始(并立即播放),还设置songOnTime变量。
function play(){
createBuffer()
connectNodes();
songOnTime = ctx.currentTime;
src.start(0, musicStartPoint);
}
*旁注:我知道在点击功能中设置songOnTime可能看起来更干净,但我认为尽可能接近src.start获取时间代码是有意义的,就像我们如何尽可能接近src.stop获取暂停时间一样。
我没有关注完整的讨论,但我很快就会关注。我只是简单地浏览了HAL演示来理解。对于那些现在确实喜欢我的人,我想告诉他们1-如何使此代码现在工作。2-从这个代码中获得暂停/播放的技巧。
1:将noteOn(xx)替换为start(xx),并将任何有效的url放在sound.load()中。我想这就是我所做的全部。控制台中会出现一些非常直接的错误。跟随他们。或者不:有时你可以忽略它们,现在它起作用了:它与某个函数中的-webkit前缀有关。给出了新的。2:在某个时刻,当它工作时,你可能想暂停声音。它会起作用的。但是,正如大家所知,新的施压会导致一个错误。因此,this.play()中发生故障的source_.start(0)之后的代码不会执行。我只是在一个尝试/捕获中附上了这些行:
this.play = function() {
analyser_ = context_.createAnalyser();
// Connect the processing graph: source -> analyser -> destination
source_.connect(analyser_);
analyser_.connect(context_.destination);
try{
source_.start(0);
}
catch(e){
this.playing = true;
(function callback(time) {
processAudio_(time);
reqId_ = window.webkitRequestAnimationFrame(callback);
})();
}
它很有效:你可以使用播放/暂停。我想提一下,这个HAL模拟真的很不可思议。遵循这些简单的步骤,这是值得的!
- NodeJS-readline暂停和恢复事件发射器(逐行读取)
- 如何暂停和恢复jquery间隔
- 我如何暂停和恢复这个动画,它可以用纯CSS完成吗
- 暂停和恢复setTimeouts数组
- Web Audio API从暂停状态恢复
- WebRTC 暂停和恢复流
- 在灯箱中打开视频时显示暂停状态
- 需要能够暂停和恢复设置超时
- 为javascript循环执行实现暂停和恢复机制
- 用于音频的 Flash HTML5 画布条件.暂停和恢复功能
- 切换HTML按钮暂停和恢复功能
- 如何暂停和恢复旋转木马滑块
- 在angularjs中使用$timeout时,如何暂停和恢复计时器
- 如果音频文件处于暂停状态如何重新播放音频文件
- 暂停和恢复setInterval
- Node.js使用setTimeout()暂停和恢复流
- 如何暂停和恢复javascript计时器
- 在JavaScript/HTML5中暂停后恢复视频播放
- 使用Javascript控制swf文件的加载,并能够暂停和恢复加载
- 暂停和恢复CasperJS, PhantomJS脚本