由于HTML的异步性质,我假设(可能不正确?)页面加载的时间线如下:
- 。。。etc将html加载到DOM
- 遇到
<audio>
标签 - 预加载被指定为"自动";触发器缓冲
- 继续将html加载到DOM中。。。等等
- 激发
window.onload
事件回调 - 一段时间后异步:找到音频资源,开始缓冲,或者返回服务器错误;激发
readystatechange
事件回调
而我希望值为"auto"的preload
属性将延迟window.onload
事件从触发或延迟标记到DOM处理,直到找到音频资源并开始缓冲,或者返回服务器错误并取消加载。
我无法想象为音频资源保留window.onload
,但我看到页面处理在过去因闪存资源加载或跟踪脚本加载而停止。
TLDR:window.onload
在资源加载方面的确切时间表是什么——特别是音频标签?
window.onload
事件似乎是在媒体src
完全加载之前调用的。使用在How do you check if a HTML5 audio element are loaded;包括.webkitAudioDecodedByteCount
<!DOCTYPE html>
<html>
<head>
<script>
window.addEventListener("load", function() {
var media = document.querySelector("audio");
console.log("window onload event"
, media.webkitAudioDecodedByteCount
, media.readyState)
})
function myOnCanPlayFunction() {
console.log("Can play", event.target.webkitAudioDecodedByteCount
, event.target.seekable.start(0)
, event.target.seekable.end(0));
}
function myOnCanPlayThroughFunction() {
console.log("Can play through", event.target.webkitAudioDecodedByteCount
, event.target.seekable.start(0)
, event.target.seekable.end(0));
}
function myOnLoadedData() {
console.log("Loaded data", event.target.webkitAudioDecodedByteCount
, event.target.seekable.start(0)
, event.target.seekable.end(0));
}
</script>
</head>
<body>
<audio oncanplay="myOnCanPlayFunction()"
oncanplaythrough="myOnCanPlayThroughFunction()"
onloadeddata="myOnLoadedData()"
src="/path/to/audio/file"
preload autoplay buffered controls></audio>
</body>
</html>
plnkr版本1http://plnkr.co/edit/zIIDDLZeVU7NHdfAtFka?p=preview
使用AudioContext
的XMLHttpRequest
、onended
事件的替代方法;Promise
;递归请求,按顺序播放文件数组。参见AudioContext.decodeAudioData()
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script>
var sources = ["/path/to/audio/src/1"
, "/path/to/audio/src/2"];
var src = sources.slice(0); // copy original array
function getAudio(url) {
return new Promise(function(resolve, reject) {
var audioCtx = new(window.AudioContext || window.webkitAudioContext)();
var source = audioCtx.createBufferSource();
var request = new XMLHttpRequest();
request.open("GET", url, true);
request.responseType = "arraybuffer";
request.onload = function() {
var audioData = request.response;
audioCtx.decodeAudioData(audioData).then(function(decodedData) {
source.buffer = decodedData;
source.connect(audioCtx.destination);
console.log(source, decodedData);
// do stuff when current audio has ended
source.onended = function() {
console.log("onended:", url);
if (src.length)
resolve(src)
else resolve("complete")
}
source.start(0);
});
}
request.send();
})
}
var audio = (function tracks(s) {
return getAudio(s.shift())
.then(function(data) {
if (Array.isArray(data) && data.length) return tracks(data)
else return data
})
}(src));
// do stuff when all `src` have been requested, played, ended
audio.then(function(msg) {
console.log(msg)
})
</script>
</head>
<body>
</body>
</html>
plnkr版本2http://plnkr.co/edit/zIIDDLZeVU7NHdfAtFka?p=preview