refactor(audio): [PKG-AUDIO-03] separate track ownership and native lifecycle

This commit is contained in:
Harvey Zhao committed 2026-09-12 02:22:13 +08:00
1 parent 803e87252e
commit 9c07ea830c
20 files changed
+12654 -250

No files matched your search

@@ -4,4 +4,4 @@
* (c) 2017-2026 Harvey Zhao
* Released under the MIT License.
*/
!function(e,o){"object"===typeof exports&&"undefined"!==typeof module?module.exports=o():"function"==typeof define&&define.amd?(t.artplayerPluginAudioTrack=o(),define(function(){return t.artplayerPluginAudioTrack})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerPluginAudioTrack=o()}(this,function(){"use strict";return function(e){return o=>{let{url:n,offset:a=0,sync:t=.3}=e;const u=new Audio;function i(){if(!o.video||!n)return;const e=o.currentTime+a;Math.abs(u.currentTime-e)>t&&(u.currentTime=e)}return u.preload="auto",n&&(u.src=n),o.on("play",()=>{n&&(i(),u.play().catch(e=>{console.warn(e)}))}),o.on("pause",()=>{u.pause()}),o.on("seek",()=>{i()}),o.on("video:timeupdate",()=>{o.playing&&i()}),o.on("video:ratechange",()=>{u.playbackRate=o.video.playbackRate}),o.on("video:volumechange",()=>{u.volume=o.volume,u.muted=o.muted}),o.on("video:waiting",()=>{u.pause()}),o.on("video:playing",()=>{n&&o.playing&&u.play().catch(e=>{console.warn(e)})}),o.on("destroy",()=>{u.pause(),u.src="",u.load()}),u.volume=o.volume,u.muted=o.muted,u.playbackRate=o.video?.playbackRate||1,{name:"artplayerPluginAudioTrack",audio:u,update:function(e){e.url&&e.url!==n&&(n=e.url,u.src=n,o.playing&&u.play().catch(e=>console.warn(e))),void 0!==e.offset&&(a=e.offset),void 0!==e.sync&&(t=e.sync)}}}}});
!function(e,t){"object"===typeof exports&&"undefined"!==typeof module?module.exports=t():"function"==typeof define&&define.amd?(e.artplayerPluginAudioTrack=t(),define(function(){return e.artplayerPluginAudioTrack})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerPluginAudioTrack=t()}(this,function(){"use strict";return function(e){return t=>{const o=function(e){let{url:t,offset:o=0,sync:n=.3}=e;const a=new Audio;let i=!1;function u(){!i&&t&&a.play().catch(e=>{i||console.warn(e)})}function c(){if(i)return;i=!0;const e=[];for(const o of[()=>a.pause(),()=>a.removeAttribute("src"),()=>a.load()])try{o()}catch(t){e.push(t)}if(e.length)throw e[0]}try{a.preload="auto",t&&(a.src=t)}catch(r){try{c()}catch{}throw r}return{audio:a,play:u,pause:function(){i||a.pause()},destroy:c,sync(e){if(i||!t)return;const u=e+o;Math.abs(a.currentTime-u)>n&&(a.currentTime=u)},update(e,c){i||(e.url&&e.url!==t&&(t=e.url,a.src=t,c&&u()),void 0!==e.offset&&(o=e.offset),void 0!==e.sync&&(n=e.sync))}}}(e),{audio:n}=o,a=[];let i=!0;function u(){t.video&&o.sync(t.currentTime)}function c(e,o){const n=()=>{i&&o()};a.push([e,n]),t.on(e,n)}function r(){if(!i)return;i=!1;const e=[];for(const[o,i]of a.splice(0))try{t.off(o,i)}catch(n){e.push(n)}try{o.destroy()}catch(n){e.push(n)}if(e.length)throw e[0]}try{c("play",()=>{u(),o.play()});for(const e of["pause","video:pause","video:ended","video:waiting","video:emptied","video:seeking"])c(e,o.pause);c("seek",u),c("video:seeked",()=>{u(),t.playing&&o.play()}),c("video:timeupdate",()=>{t.playing&&u()}),c("video:ratechange",()=>{n.playbackRate=t.video.playbackRate}),c("video:volumechange",()=>{n.volume=t.volume,n.muted=t.muted}),c("video:playing",()=>{t.playing&&(u(),o.play())}),c("destroy",r),n.volume=t.volume,n.muted=t.muted,n.playbackRate=t.video?.playbackRate||1}catch(d){try{r()}catch{}throw d}return{name:"artplayerPluginAudioTrack",audio:n,update(e){i&&o.update(e,t.playing)}}}}});
@@ -4,4 +4,4 @@
* (c) 2017-2026 Harvey Zhao
* Released under the MIT License.
*/
!function(e,o){"object"===typeof exports&&"undefined"!==typeof module?module.exports=o():"function"==typeof define&&define.amd?(t.artplayerPluginAudioTrack=o(),define(function(){return t.artplayerPluginAudioTrack})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerPluginAudioTrack=o()}(this,function(){"use strict";return function(e){return o=>{var n;let{url:a,offset:t=0,sync:u=.3}=e;const i=new Audio;function l(){if(!o.video||!a)return;const e=o.currentTime+t;Math.abs(i.currentTime-e)>u&&(i.currentTime=e)}return i.preload="auto",a&&(i.src=a),o.on("play",()=>{a&&(l(),i.play().catch(e=>{console.warn(e)}))}),o.on("pause",()=>{i.pause()}),o.on("seek",()=>{l()}),o.on("video:timeupdate",()=>{o.playing&&l()}),o.on("video:ratechange",()=>{i.playbackRate=o.video.playbackRate}),o.on("video:volumechange",()=>{i.volume=o.volume,i.muted=o.muted}),o.on("video:waiting",()=>{i.pause()}),o.on("video:playing",()=>{a&&o.playing&&i.play().catch(e=>{console.warn(e)})}),o.on("destroy",()=>{i.pause(),i.src="",i.load()}),i.volume=o.volume,i.muted=o.muted,i.playbackRate=(null==(n=o.video)?void 0:n.playbackRate)||1,{name:"artplayerPluginAudioTrack",audio:i,update:function(e){e.url&&e.url!==a&&(a=e.url,i.src=a,o.playing&&i.play().catch(e=>console.warn(e))),void 0!==e.offset&&(t=e.offset),void 0!==e.sync&&(u=e.sync)}}}}});
!function(e,t){"object"===typeof exports&&"undefined"!==typeof module?module.exports=t():"function"==typeof define&&define.amd?(e.artplayerPluginAudioTrack=t(),define(function(){return e.artplayerPluginAudioTrack})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerPluginAudioTrack=t()}(this,function(){"use strict";return function(e){return t=>{var o;const n=function(e){let{url:t,offset:o=0,sync:n=.3}=e;const a=new Audio;let i=!1;function u(){!i&&t&&a.play().catch(e=>{i||console.warn(e)})}function c(){if(i)return;i=!0;const e=[];for(const o of[()=>a.pause(),()=>a.removeAttribute("src"),()=>a.load()])try{o()}catch(t){e.push(t)}if(e.length)throw e[0]}try{a.preload="auto",t&&(a.src=t)}catch(r){try{c()}catch(d){}throw r}return{audio:a,play:u,pause:function(){i||a.pause()},destroy:c,sync(e){if(i||!t)return;const u=e+o;Math.abs(a.currentTime-u)>n&&(a.currentTime=u)},update(e,c){i||(e.url&&e.url!==t&&(t=e.url,a.src=t,c&&u()),void 0!==e.offset&&(o=e.offset),void 0!==e.sync&&(n=e.sync))}}}(e),{audio:a}=n,i=[];let u=!0;function c(){t.video&&n.sync(t.currentTime)}function r(e,o){const n=()=>{u&&o()};i.push([e,n]),t.on(e,n)}function d(){if(!u)return;u=!1;const e=[];for(const[n,a]of i.splice(0))try{t.off(n,a)}catch(o){e.push(o)}try{n.destroy()}catch(o){e.push(o)}if(e.length)throw e[0]}try{r("play",()=>{c(),n.play()});for(const e of["pause","video:pause","video:ended","video:waiting","video:emptied","video:seeking"])r(e,n.pause);r("seek",c),r("video:seeked",()=>{c(),t.playing&&n.play()}),r("video:timeupdate",()=>{t.playing&&c()}),r("video:ratechange",()=>{a.playbackRate=t.video.playbackRate}),r("video:volumechange",()=>{a.volume=t.volume,a.muted=t.muted}),r("video:playing",()=>{t.playing&&(c(),n.play())}),r("destroy",d),a.volume=t.volume,a.muted=t.muted,a.playbackRate=(null==(o=t.video)?void 0:o.playbackRate)||1}catch(s){try{d()}catch(l){}throw s}return{name:"artplayerPluginAudioTrack",audio:a,update(e){u&&n.update(e,t.playing)}}}}});
+141 -65
View File
@@ -4,86 +4,162 @@
* (c) 2017-2026 Harvey Zhao
* Released under the MIT License.
*/
function artplayerPluginAudioTrack(option) {
return (art) => {
let { url, offset = 0, sync = 0.3 } = option;
const audio = new Audio();
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) {
if (url)
audio.src = url;
} catch (error) {
try {
destroy();
} catch {
}
function syncAudio() {
if (!art.video || !url)
throw error;
}
return {
audio,
play,
pause,
destroy,
sync(time) {
if (closed || !url)
return;
const videoTime = art.currentTime;
const targetTime = videoTime + offset;
if (Math.abs(audio.currentTime - targetTime) > sync) {
audio.currentTime = targetTime;
}
}
art.on("play", () => {
if (!url)
const target = time + offset;
if (Math.abs(audio.currentTime - target) > sync)
audio.currentTime = target;
},
update(newOption, playing) {
if (closed)
return;
syncAudio();
audio.play().catch((err) => {
console.warn(err);
});
});
art.on("pause", () => {
audio.pause();
});
art.on("seek", () => {
syncAudio();
});
art.on("video:timeupdate", () => {
if (art.playing) {
syncAudio();
}
});
art.on("video:ratechange", () => {
audio.playbackRate = art.video.playbackRate;
});
art.on("video:volumechange", () => {
audio.volume = art.volume;
audio.muted = art.muted;
});
art.on("video:waiting", () => {
audio.pause();
});
art.on("video:playing", () => {
if (url && art.playing) {
audio.play().catch((err) => {
console.warn(err);
});
}
});
art.on("destroy", () => {
audio.pause();
audio.src = "";
audio.load();
});
function update(newOption) {
if (newOption.url && newOption.url !== url) {
url = newOption.url;
audio.src = url;
if (art.playing) {
audio.play().catch((err) => console.warn(err));
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 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);
}
}
if (newOption.offset !== void 0) {
offset = newOption.offset;
}
if (newOption.sync !== void 0) {
sync = newOption.sync;
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 (art.playing)
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 (art.playing) {
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;
}
audio.volume = art.volume;
audio.muted = art.muted;
audio.playbackRate = art.video?.playbackRate || 1;
return {
name: "artplayerPluginAudioTrack",
audio,
update
update(newOption) {
if (active)
track.update(newOption, art.playing);
}
};
};
}