Safari 使用 HTML5 音频标签时表现得很奇怪
Safari behaving very weirdy with HTML5 audio tag
我正在构建一个站点,其中有一个 HTML5 音频元素,我在其中使用 javascript 根据用户点击的曲目动态更新源。这是由网络音频 API 包装的,它执行 fft 并使用它来控制三个 js 中的场景。
该站点在 chrome 和 firefox 中运行正常,但在 safari 中音频问题严重。
第一个问题是如果动态更新 safari 将不接受源作为音频的子节点,您必须将 src 放在音频标签中。我正在检查我的 js 中的 safari/IOS 并根据结果设置 opus 或 mp3 音频源。我尝试使用 m4a 作为文件格式,但它无法播放,尽管浏览器支持 m4a?
持续存在的问题是:
.pause()
方法对音频元素不起作用,当用户恢复播放时,它只是从曲目开头再次播放。
尝试设置 .currentTime 以允许用户跳过曲目在 safari 中没有任何作用。然而,它正在读取 currentTime 作为其设置播放头的位置。
当 animate() 函数(使用 requestAnimationFrame 递归调用)为 运行 时,它在开始播放任何内容之前非常慢,延迟一分钟以上,与 ios 相同,但不像严重并且 ios 没有遇到其他问题。
场景中的多边形计数约为 250k,这是相当高的,但是如果 canvas 中的多边形计数使音频播放缓慢,尽管在requestAnimationFrame 不是 运行.
请原谅草率的代码,我没有太多时间写这个:
const playTrack = (trackNumber) => {
audio.src = `assets/audio/${trackNumber}.${fileType}`;
audio.load();
audio.play();
};
audio.ontimeupdate = () => {
const left = audio.currentTime * segment;
playHead.style.width = `${left}px`;
};
playbar.addEventListener("click", (e) => {
const pos = e.x - container.left;
audio.currentTime = pos / segment;
}, false);
tracks.forEach(track => {
track.addEventListener("click", (e) => {
e.preventDefault();
//pause or load
if (!audio.paused && nowPlaying === track) {
//pause track
audio.pause();
track.children[0].classList.remove('fa-pause');
track.children[0].classList.add('fa-play');
} else if (audio.paused && nowPlaying === track) {
//play track
audio.play();
track.children[0].classList.remove('fa-play');
track.children[0].classList.add('fa-pause');
} else {
//load and play track
instructions.style.display = "none";
trackNumber = parseInt(track.getAttribute('data-value'), 10);
playTrack(trackNumber);
nowPlaying = track;
iconFlick(track);
}
trackDuration = duration[trackNumber];
segment = width / trackDuration;
if (clickFirst === 0) {
clickFirst = 10;
setupNodes(audio)
}
trackGlobal = track;
});
const setupNodes = (audio) => {
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
const source = audioCtx.createMediaElementSource(audio);
analyser = audioCtx.createAnalyser();
source.connect(analyser);
analyser.fftSize = 256;
bufferLength = analyser.frequencyBinCount;
dataArray = new Uint8Array(bufferLength);
audioBegin = 1;
analyser.connect(audioCtx.destination);
};
如果你发现了什么,请告诉我,这让我很困惑。
如果您不使用 <audio>
标签,您可能会有更好的运气和更多的控制权。如果您想要这些控件,则需要制作自己的播放按钮和滑块。并单独使用Web Audio API下载并解码播放曲目。
var url = "whatever.mp3";
var source = audioCtx.createBufferSource();
var buffers = {};
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
request.onload = function () {
audioCtx.decodeAudioData(request.response, function (buffer) {
source.buffer = buffer;
source.connect(audioCtx.destination);
source.start(audioCtx.currentTime);
// save this for later, so you can replay it without downloading
buffers[url] = buffer;
}, function () {
console.warn("error loading sound url: " + url);
});
}
request.send();
我正在构建一个站点,其中有一个 HTML5 音频元素,我在其中使用 javascript 根据用户点击的曲目动态更新源。这是由网络音频 API 包装的,它执行 fft 并使用它来控制三个 js 中的场景。
该站点在 chrome 和 firefox 中运行正常,但在 safari 中音频问题严重。
第一个问题是如果动态更新 safari 将不接受源作为音频的子节点,您必须将 src 放在音频标签中。我正在检查我的 js 中的 safari/IOS 并根据结果设置 opus 或 mp3 音频源。我尝试使用 m4a 作为文件格式,但它无法播放,尽管浏览器支持 m4a?
持续存在的问题是:
.pause()
方法对音频元素不起作用,当用户恢复播放时,它只是从曲目开头再次播放。
尝试设置 .currentTime 以允许用户跳过曲目在 safari 中没有任何作用。然而,它正在读取 currentTime 作为其设置播放头的位置。
当 animate() 函数(使用 requestAnimationFrame 递归调用)为 运行 时,它在开始播放任何内容之前非常慢,延迟一分钟以上,与 ios 相同,但不像严重并且 ios 没有遇到其他问题。
场景中的多边形计数约为 250k,这是相当高的,但是如果 canvas 中的多边形计数使音频播放缓慢,尽管在requestAnimationFrame 不是 运行.
请原谅草率的代码,我没有太多时间写这个:
const playTrack = (trackNumber) => {
audio.src = `assets/audio/${trackNumber}.${fileType}`;
audio.load();
audio.play();
};
audio.ontimeupdate = () => {
const left = audio.currentTime * segment;
playHead.style.width = `${left}px`;
};
playbar.addEventListener("click", (e) => {
const pos = e.x - container.left;
audio.currentTime = pos / segment;
}, false);
tracks.forEach(track => {
track.addEventListener("click", (e) => {
e.preventDefault();
//pause or load
if (!audio.paused && nowPlaying === track) {
//pause track
audio.pause();
track.children[0].classList.remove('fa-pause');
track.children[0].classList.add('fa-play');
} else if (audio.paused && nowPlaying === track) {
//play track
audio.play();
track.children[0].classList.remove('fa-play');
track.children[0].classList.add('fa-pause');
} else {
//load and play track
instructions.style.display = "none";
trackNumber = parseInt(track.getAttribute('data-value'), 10);
playTrack(trackNumber);
nowPlaying = track;
iconFlick(track);
}
trackDuration = duration[trackNumber];
segment = width / trackDuration;
if (clickFirst === 0) {
clickFirst = 10;
setupNodes(audio)
}
trackGlobal = track;
});
const setupNodes = (audio) => {
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
const source = audioCtx.createMediaElementSource(audio);
analyser = audioCtx.createAnalyser();
source.connect(analyser);
analyser.fftSize = 256;
bufferLength = analyser.frequencyBinCount;
dataArray = new Uint8Array(bufferLength);
audioBegin = 1;
analyser.connect(audioCtx.destination);
};
如果你发现了什么,请告诉我,这让我很困惑。
如果您不使用 <audio>
标签,您可能会有更好的运气和更多的控制权。如果您想要这些控件,则需要制作自己的播放按钮和滑块。并单独使用Web Audio API下载并解码播放曲目。
var url = "whatever.mp3";
var source = audioCtx.createBufferSource();
var buffers = {};
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
request.onload = function () {
audioCtx.decodeAudioData(request.response, function (buffer) {
source.buffer = buffer;
source.connect(audioCtx.destination);
source.start(audioCtx.currentTime);
// save this for later, so you can replay it without downloading
buffers[url] = buffer;
}, function () {
console.warn("error loading sound url: " + url);
});
}
request.send();