mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-09 03:46:16 -08:00
183 lines
4.3 KiB
JavaScript
183 lines
4.3 KiB
JavaScript
/*!
|
|
* artplayer-plugin-audio-track.js v2.0.0
|
|
* Github: https://github.com/zhw2590582/ArtPlayer
|
|
* (c) 2017-2026 Harvey Zhao
|
|
* Released under the MIT License.
|
|
*/
|
|
function createAudioTrack(option) {
|
|
let { url, offset = 0, sync = 0.3 } = option;
|
|
const audio = new Audio();
|
|
let closed = false;
|
|
function play() {
|
|
if (closed || !url)
|
|
return;
|
|
audio.play().catch((error) => {
|
|
if (!closed)
|
|
console.warn(error);
|
|
});
|
|
}
|
|
function pause() {
|
|
if (!closed)
|
|
audio.pause();
|
|
}
|
|
function destroy() {
|
|
if (closed)
|
|
return;
|
|
closed = true;
|
|
const failures = [];
|
|
for (const release of [() => audio.pause(), () => audio.removeAttribute("src"), () => audio.load()]) {
|
|
try {
|
|
release();
|
|
} catch (error) {
|
|
failures.push(error);
|
|
}
|
|
}
|
|
if (failures.length)
|
|
throw failures[0];
|
|
}
|
|
try {
|
|
audio.preload = "auto";
|
|
if (url)
|
|
audio.src = url;
|
|
} catch (error) {
|
|
try {
|
|
destroy();
|
|
} catch {
|
|
}
|
|
throw error;
|
|
}
|
|
return {
|
|
audio,
|
|
play,
|
|
pause,
|
|
destroy,
|
|
sync(time) {
|
|
if (closed || !url)
|
|
return;
|
|
const target = time + offset;
|
|
if (Math.abs(audio.currentTime - target) > sync)
|
|
audio.currentTime = target;
|
|
},
|
|
update(newOption, playing) {
|
|
if (closed)
|
|
return;
|
|
if (newOption.url && newOption.url !== url) {
|
|
url = newOption.url;
|
|
audio.src = url;
|
|
if (playing)
|
|
play();
|
|
}
|
|
if (newOption.offset !== void 0)
|
|
offset = newOption.offset;
|
|
if (newOption.sync !== void 0)
|
|
sync = newOption.sync;
|
|
}
|
|
};
|
|
}
|
|
function artplayerPluginAudioTrack(option) {
|
|
return (art) => {
|
|
const track = createAudioTrack(option);
|
|
const { audio } = track;
|
|
const subscriptions = [];
|
|
let active = true;
|
|
function syncAudio() {
|
|
if (art.video)
|
|
track.sync(art.currentTime);
|
|
}
|
|
function canResumeAudio() {
|
|
const video = art.video;
|
|
if (!video)
|
|
return false;
|
|
if ("playing" in video && typeof video.playing === "boolean")
|
|
return video.playing;
|
|
return art.playing || video.paused === false && !video.ended && video.readyState > 2;
|
|
}
|
|
function listen(event, callback) {
|
|
const listener = () => {
|
|
if (active)
|
|
callback();
|
|
};
|
|
subscriptions.push([event, listener]);
|
|
art.on(event, listener);
|
|
}
|
|
function destroy() {
|
|
if (!active)
|
|
return;
|
|
active = false;
|
|
const failures = [];
|
|
for (const [event, listener] of subscriptions.splice(0)) {
|
|
try {
|
|
art.off(event, listener);
|
|
} catch (error) {
|
|
failures.push(error);
|
|
}
|
|
}
|
|
try {
|
|
track.destroy();
|
|
} catch (error) {
|
|
failures.push(error);
|
|
}
|
|
if (failures.length)
|
|
throw failures[0];
|
|
}
|
|
try {
|
|
listen("play", () => {
|
|
syncAudio();
|
|
track.play();
|
|
});
|
|
for (const event of ["pause", "video:pause", "video:ended", "video:waiting", "video:emptied", "video:seeking"])
|
|
listen(event, track.pause);
|
|
listen("seek", syncAudio);
|
|
listen("video:seeked", () => {
|
|
syncAudio();
|
|
if (canResumeAudio())
|
|
track.play();
|
|
});
|
|
listen("video:timeupdate", () => {
|
|
if (art.playing)
|
|
syncAudio();
|
|
});
|
|
listen("video:ratechange", () => {
|
|
audio.playbackRate = art.video.playbackRate;
|
|
});
|
|
listen("video:volumechange", () => {
|
|
audio.volume = art.volume;
|
|
audio.muted = art.muted;
|
|
});
|
|
listen("video:playing", () => {
|
|
if (canResumeAudio()) {
|
|
syncAudio();
|
|
track.play();
|
|
}
|
|
});
|
|
listen("video:canplay", () => {
|
|
if (audio.paused && canResumeAudio()) {
|
|
syncAudio();
|
|
track.play();
|
|
}
|
|
});
|
|
listen("destroy", destroy);
|
|
audio.volume = art.volume;
|
|
audio.muted = art.muted;
|
|
audio.playbackRate = art.video?.playbackRate || 1;
|
|
} catch (error) {
|
|
try {
|
|
destroy();
|
|
} catch {
|
|
}
|
|
throw error;
|
|
}
|
|
return {
|
|
name: "artplayerPluginAudioTrack",
|
|
audio,
|
|
update(newOption) {
|
|
if (active)
|
|
track.update(newOption, art.playing);
|
|
}
|
|
};
|
|
};
|
|
}
|
|
export {
|
|
artplayerPluginAudioTrack as default
|
|
};
|