Update package.json

Remove options section from README for clarity

Add 'waiting' event emission during seeking in mediabunnyEngine

This change emits a 'waiting' event when the seeking process begins,
improving the event handling and allowing for better synchronization
during media playback.

fix(audioEngine): adjust audio context suspension timing for improved playback responsiveness

refactor(mediabunnyVideoShim): remove redundant width and height getters; enhance poster setter and add setAttribute method

feat: initialize artplayer-proxy-mediabunny with essential files and structure

feat: implement audio and video engines for mediabunny integration

- Added audioEngine.js to handle audio playback using MediaBunny.
- Created mediabunnyEngine.js to manage both audio and video playback.
- Implemented videoEngine.js for rendering video on a canvas.
- Introduced canvasProxy.js to create a canvas element and manage its methods.
- Developed mediabunnyVideoShim.js to bridge ArtPlayer and MediaBunny functionalities.
- Added videoEvents.js for custom event handling related to video playback.
- Included a utility function clamp.js for value clamping.

feat: add playback rate control to audio and video engines

- Introduced playback rate management in the audio engine, allowing dynamic adjustment of playback speed.
- Updated the mediabunny engine to expose the new setPlaybackRate method.
- Enhanced the mediabunny video shim to support playback rate adjustments, including getter and setter for playbackRate.
- Added event emission for rate changes to ensure proper handling in the application.

Enhance audio engine and video shim functionality

- Added a check to ensure the audio context is initialized before playing audio in the audio engine.
- Introduced a new 'playing' getter in the video shim to accurately reflect the playback state, indicating when the video is neither paused nor ended.

Refactor audio context initialization to handle errors and remove async/await

- Changed `ensureAudioContext` from async to synchronous to simplify error handling.
- Added a try-catch block to handle potential errors when creating the AudioContext with a specified sample rate.
- Updated calls to `ensureAudioContext` to remove unnecessary await statements.

Enhance Mediabunny Engine and Video Shim with State Management and Error Handling

- Added readyState, networkState, and error properties to the Mediabunny Engine for better state management.
- Implemented error handling during media loading, emitting appropriate events on error.
- Updated the Video Engine to emit a 'timeupdate' event for better synchronization.
- Extended the Mediabunny Video Shim to expose new properties (readyState, networkState, error) and methods for improved functionality.
- Added seekable property to the Video Shim to provide seekable range based on media duration.
- Implemented additional properties and methods in the Video Shim for autoplay, loop, controls, currentSrc, poster, preload, defaultMuted, and defaultPlaybackRate.
- Enhanced requestVideoFrameCallback and cancelVideoFrameCallback methods for better frame handling.

refactor: streamline audio and video engine implementations

- Updated audioEngine.js to improve readability and maintainability by using consistent formatting and simplifying function structures.
- Refactored mediabunnyEngine.js to enhance clarity and ensure consistent coding style.
- Enhanced videoEngine.js with improved async handling and clearer function definitions.
- Modified canvasProxy.js to maintain consistent formatting and improve readability.
- Updated mediabunnyVideoShim.js to streamline event handling and improve clarity.
- Refactored videoEvents.js for better readability and consistency in event listener management.
- Simplified clamp.js for improved readability.

feat: enhance audio and video loading with metadata callbacks

- Updated audioEngine to accept an optional onMetadata callback in the load function, which is triggered upon loading completion.
- Modified mediabunnyEngine to handle video and audio loading concurrently, emitting loadedmetadata and durationchange events only when both are ready.
- Enhanced videoEngine to include an onMetadata callback in the load function, ensuring metadata events are emitted appropriately.
- Implemented a throttling mechanism for the timeupdate event in videoEngine to reduce event emissions and improve performance.

feat: add seeking state and played property to mediabunny engine and video shim

- Introduced a `_seeking` state in the mediabunny engine to track seek operations.
- Emitted 'seeking' and 'seeked' events during seek operations.
- Added a `seeking` getter to expose the seeking state.
- Implemented a `played` property in the video shim to provide playback range information.
- Added `width` and `height` getters to the video shim for better video dimension access.
- Enhanced cross-origin handling in the video shim.

feat(audioEngine): enhance audio playback management with starvation detection

- Added an event emitter to notify when the audio context is waiting.
- Implemented a starvation check that suspends the audio context if playback is delayed.
- Introduced a mechanism to track the latest scheduled end time of audio buffers.
- Updated the handling of audio buffer playback to ensure proper state transitions.

refactor: remove unnecessary comments and streamline code in audio, video, and mediabunny engines

feat: add resize functionality to canvas proxy and update type definitions

- Implemented a resize function in canvasProxy.js to adjust canvas size based on player dimensions and video metadata.
- Updated TypeScript definitions for artplayer-proxy-mediabunny to include option and result types.
- Modified build-ts script to include all plugin type definitions.
- Added TypeScript definitions for artplayer-proxy-canvas and artplayer-proxy-mediabunny.

refactor: remove unused properties from Artplayer instance and make option parameter optional in artplayerProxyCanvas type definition

Enhance Mediabunny and Video Engine functionality

- Added event listener for 'ended' event in mediabunnyEngine to handle playback state.
- Modified seek function to check if playback should resume after seeking.
- Reset canvas dimensions to zero in videoEngine when video track is not available or cannot be decoded.
- Ensured canvas is cleared when video track is invalid to prevent rendering issues.

Emit 'waiting' event during loadstart in mediabunnyEngine

Refactor event emission in mediabunnyEngine and add sleep utility function

- Changed the event emission for 'loadstart' to be asynchronous using setTimeout.
- Introduced a new utility function 'sleep' to facilitate delayed execution in promises.

feat: enhance mediabunny proxy with new options and source handling

- Added options for event delay, load timeout, timeupdate interval, AV sync tolerance, poster, and source in README.
- Implemented source normalization in audio and video engines to support URL, Blob, and ReadableStream.
- Updated mediabunny engine to handle new options and improve load handling with timeout and error management.
- Enhanced video engine to draw a poster when no video source is available and manage playback rate.
- Modified shim to accept source option and integrate with the new engine options.
- Updated TypeScript definitions to reflect new options and source types.

feat: add dropLateFrames option to video and mediabunny engines

- Introduced dropLateFrames option in mediabunnyEngine and videoEngine to control frame dropping behavior.
- Updated videoEngine logic to handle frame rendering based on the dropLateFrames setting.
- Added type definition for dropLateFrames in TypeScript declaration file.

fix: delay loadstart event emission to ensure proper event handling

The 'loadstart' event emission is now wrapped in a setTimeout to ensure it is triggered after the current call stack is cleared. This change aims to improve the timing of event emissions and prevent potential issues with event handling in the mediabunny engine.

feat: add preflight range check and drop late frames option

- Updated README.md to include new options: dropLateFrames and preflightRange.
- Enhanced mediabunnyEngine to support new options with default values.
- Implemented preflight function in videoEngine to check server support for Range requests.
- Adjusted videoEngine to utilize preflight check before loading media.
- Updated TypeScript definitions to include preflightRange option.

Remove aspectRatio option from Artplayer configuration

Update README and mediabunny example URL for consistency

Refactor code structure for improved readability and maintainability

Update dependencies and fix play/seek state management in mediabunnyEngine

Refactor code structure for improved readability and maintainability

fix(types): update export syntax and formatting in TypeScript declaration files
This commit is contained in:
Harvey Zhao committed 2025-12-13 14:06:30 +08:00
1 parent 2f42f85f90
commit 99ad0d7b93
117 files changed
+29059 -2229

No files matched your search

@@ -115,7 +115,7 @@ export default class LibassAdapter {
if (!option.workerUrl) {
option.workerUrl
= 'https://cdnjs.cloudflare.com/ajax/libs/libass-wasm/4.1.0/js/subtitles-octopus-worker.js'
= 'https://cdnjs.cloudflare.com/ajax/libs/libass-wasm/4.1.0/js/subtitles-octopus-worker.js'
}
if (option.availableFonts) {
@@ -36,7 +36,7 @@ export default async function getVttArray(vttUrl = '') {
continue
const timeReg
= /((?:\d{2}:)?(?:\d{2}:)?\d{2}(?:.\d{3})?) ?--> ?((?:\d{2}:)?(?:\d{2}:)?\d{2}(?:.\d{3})?)/
= /((?:\d{2}:)?(?:\d{2}:)?\d{2}(?:.\d{3})?) ?--> ?((?:\d{2}:)?(?:\d{2}:)?\d{2}(?:.\d{3})?)/
const timeMatch = time.match(timeReg)
const textReg = /(.*)#(\w{4})=(.*)/
@@ -4,6 +4,6 @@ type Option = (ctx: CanvasRenderingContext2D, video: HTMLVideoElement) => void
type Result = HTMLCanvasElement
declare const artplayerProxyCanvas: (option: Option) => (art: Artplayer) => Result
declare const artplayerProxyCanvas: (option?: Option) => (art: Artplayer) => Result
export default artplayerProxyCanvas
@@ -0,0 +1,6 @@
node_modules
.DS_Store
.parcel-cache
yarn.lock
package-lock.json
src
@@ -0,0 +1,11 @@
# artplayer-proxy-mediabunny
mediabunny proxy for ArtPlayer
## Demo
[https://artplayer.org](https://artplayer.org/?libs=./uncompiled/artplayer-proxy-mediabunny/index.js&example=mediabunny)
## License
MIT © Harvey Zack
@@ -0,0 +1,8 @@
/*!
* artplayer-proxy-mediabunny.js v1.0.0
* Github: https://github.com/zhw2590582/ArtPlayer
* (c) 2017-2025 Harvey Zack
* Released under the MIT License.
*/
!function(e,r,a,i,s,n,o,l){var c="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},d="function"==typeof c[i]&&c[i],u=d.i||{},m=d.cache||{},h="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function p(r,a){if(!m[r]){if(!e[r]){if(s[r])return s[r];var n="function"==typeof c[i]&&c[i];if(!a&&n)return n(r,!0);if(d)return d(r,!0);if(h&&"string"==typeof r)return h(r);var o=Error("Cannot find module '"+r+"'");throw o.code="MODULE_NOT_FOUND",o}u.resolve=function(a){var i=e[r][1][a];return null!=i?i:a},u.cache={};var l=m[r]=new p.Module(r);e[r][0].call(l.exports,u,l,l.exports,c)}return m[r].exports;function u(e){var r=u.resolve(e);return!1===r?{}:p(r)}}p.isParcelRequire=!0,p.Module=function(e){this.id=e,this.bundle=p,this.require=h,this.exports={}},p.modules=e,p.cache=m,p.parent=d,p.distDir=void 0,p.publicUrl=void 0,p.devServer=void 0,p.i=u,p.register=function(r,a){e[r]=[function(e,r){r.exports=a},{}]},Object.defineProperty(p,"root",{get:function(){return c[i]}}),c[i]=p;for(var f=0;f<r.length;f++)p(r[f]);if(a){var g=p(a);"object"==typeof exports&&"undefined"!=typeof module?module.exports=g:"function"==typeof define&&define.amd&&define(function(){return g})}}({"1qMFK":[function(e,r,a,i){var s=e("@parcel/transformer-js/src/esmodule-helpers.js");s.defineInteropFlag(a),s.export(a,"default",()=>l);var n=e("./proxy/canvasProxy.js"),o=s.interopDefault(n);function l(e={}){return r=>(0,o.default)(r,e)}"undefined"!=typeof window&&(window.artplayerProxyMediabunny=l)},{"./proxy/canvasProxy.js":"ln3T4","@parcel/transformer-js/src/esmodule-helpers.js":"6ykb1"}],ln3T4:[function(e,r,a,i){var s=e("@parcel/transformer-js/src/esmodule-helpers.js");s.defineInteropFlag(a),s.export(a,"default",()=>l);var n=e("../shim/mediabunnyVideoShim.js"),o=s.interopDefault(n);function l(e,r){let{constructor:a}=e,{createElement:i}=a.utils,s=i("canvas"),n=s.getContext("2d"),l=(0,o.default)({art:e,canvas:s,ctx:n,option:r}),c={};for(let e in s)"function"==typeof s[e]&&(c[e]=s[e].bind(s));for(let e in l)e in s||Object.defineProperty(s,e,{get(){let r=l[e];return"function"==typeof r?r.bind(l):r},set(r){l[e]=r},configurable:!0,enumerable:!0});for(let e in c)s[e]=(...r)=>c[e](...r);function d(){e.template?.$player&&!e.option.autoSize&&Object.assign(s.style,{width:"100%",height:"100%",objectFit:"contain"})}return e.on("destroy",()=>{l.destroy()}),e.on("resize",d),e.on("video:loadedmetadata",d),s}},{"../shim/mediabunnyVideoShim.js":"aLQUP","@parcel/transformer-js/src/esmodule-helpers.js":"6ykb1"}],aLQUP:[function(e,r,a,i){var s=e("@parcel/transformer-js/src/esmodule-helpers.js");s.defineInteropFlag(a),s.export(a,"default",()=>u);var n=e("../engine/mediabunnyEngine.js"),o=s.interopDefault(n),l=e("../utils/clamp.js"),c=s.interopDefault(l),d=e("./videoEvents.js");function u({art:e,canvas:r,ctx:a,option:i}){let s=(0,d.createVideoEventTarget)(),n=(0,o.default)({canvas:r,ctx:a,events:s,option:i}),l=null,u=i.volume??.7,m=!!i.muted,h=1;n.setVolume(u,m);let{events:p}=e.constructor.config;p.forEach(r=>{s.addEventListener(r,r=>{e.emit(`video:${r.type}`,r)})});let f={addEventListener:s.addEventListener,removeEventListener:s.removeEventListener,get src(){return l},set src(v){l=v,v&&n.load(v)},get currentTime(){return n.currentTime},set currentTime(t){n.seek(Number(t)||0)},get duration(){return n.duration},get buffered(){let e=n.duration;if(!e||Number.isNaN(e))return{length:0,start:()=>0,end:()=>0};return{length:1,start:()=>0,end:()=>e}},get played(){let e=n.duration,r=n.currentTime;if(!e||Number.isNaN(e)||r<=0)return{length:0,start:()=>0,end:()=>0};return{length:1,start:()=>0,end:()=>r}},get paused(){return n.paused},get playing(){return!n.paused&&!n.ended},get ended(){return n.ended},get readyState(){return n.readyState},get networkState(){return n.networkState},get error(){return n.error},get seeking(){return n.seeking},get seekable(){let e=n.duration;if(!e||Number.isNaN(e))return{length:0,start:()=>0,end:()=>0};return{length:1,start:()=>0,end:()=>e}},get playbackRate(){return h},set playbackRate(v){let e=Number(v);if(Number.isNaN(e)||e<=0)return;h=e,n.setPlaybackRate(e),s.emit("ratechange")},get volume(){return u},set volume(v){u=(0,c.default)(v,0,1),m=!1,n.setVolume(u,m),s.emit("volumechange")},get muted(){return m},set muted(v){m=!!v,n.setVolume(u,m),s.emit("volumechange")},play:()=>n.play(),pause(){n.pause()},load(){l&&n.load(l)},destroy(){n.destroy()},get videoWidth(){return n.videoWidth},get videoHeight(){return n.videoHeight},get playsInline(){return!0},set playsInline(v){},get autoplay(){return i.autoplay||!1},set autoplay(v){},get loop(){return i.loop||!1},set loop(v){},get controls(){return!1},set controls(v){},get crossOrigin(){return i.crossOrigin||""},set crossOrigin(v){},get currentSrc(){return l},get poster(){return i.poster||""},set poster(v){i.poster=v},get preload(){return"auto"},set preload(v){},get defaultMuted(){returnLine truncated
@@ -0,0 +1,8 @@
/*!
* artplayer-proxy-mediabunny.js v1.0.0
* Github: https://github.com/zhw2590582/ArtPlayer
* (c) 2017-2025 Harvey Zack
* Released under the MIT License.
*/
!function(e,r,n,a,i,s,o,c){var u="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},l="function"==typeof u[a]&&u[a],d=l.i||{},f=l.cache||{},h="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function p(r,n){if(!f[r]){if(!e[r]){if(i[r])return i[r];var s="function"==typeof u[a]&&u[a];if(!n&&s)return s(r,!0);if(l)return l(r,!0);if(h&&"string"==typeof r)return h(r);var o=Error("Cannot find module '"+r+"'");throw o.code="MODULE_NOT_FOUND",o}d.resolve=function(n){var a=e[r][1][n];return null!=a?a:n},d.cache={};var c=f[r]=new p.Module(r);e[r][0].call(c.exports,d,c,c.exports,u)}return f[r].exports;function d(e){var r=d.resolve(e);return!1===r?{}:p(r)}}p.isParcelRequire=!0,p.Module=function(e){this.id=e,this.bundle=p,this.require=h,this.exports={}},p.modules=e,p.cache=f,p.parent=l,p.distDir=void 0,p.publicUrl=void 0,p.devServer=void 0,p.i=d,p.register=function(r,n){e[r]=[function(e,r){r.exports=n},{}]},Object.defineProperty(p,"root",{get:function(){return u[a]}}),u[a]=p;for(var m=0;m<r.length;m++)p(r[m]);if(n){var g=p(n);"object"==typeof exports&&"undefined"!=typeof module?module.exports=g:"function"==typeof define&&define.amd&&define(function(){return g})}}({OIaIB:[function(e,r,n,a){var i=e("@parcel/transformer-js/src/esmodule-helpers.js");i.defineInteropFlag(n),i.export(n,"default",function(){return c});var s=e("./proxy/canvasProxy.js"),o=i.interopDefault(s);function c(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return function(r){return(0,o.default)(r,e)}}"undefined"!=typeof window&&(window.artplayerProxyMediabunny=c)},{"./proxy/canvasProxy.js":"hTxiw","@parcel/transformer-js/src/esmodule-helpers.js":"qpMMf"}],hTxiw:[function(e,r,n,a){var i=e("@parcel/transformer-js/src/esmodule-helpers.js");i.defineInteropFlag(n),i.export(n,"default",function(){return u});var s=e("@swc/helpers/cjs/_to_consumable_array.cjs"),o=e("../shim/mediabunnyVideoShim.js"),c=i.interopDefault(o);function u(e,r){var n,a=function(e){e in o||Object.defineProperty(o,e,{get:function(){var r=l[e];return"function"==typeof r?r.bind(l):r},set:function(r){l[e]=r},configurable:!0,enumerable:!0})},i=function(e){o[e]=function(){for(var r=arguments.length,a=Array(r),i=0;i<r;i++)a[i]=arguments[i];return(n=d)[e].apply(n,(0,s._)(a))}},o=(0,e.constructor.utils.createElement)("canvas"),u=o.getContext("2d"),l=(0,c.default)({art:e,canvas:o,ctx:u,option:r}),d={};for(var f in o)"function"==typeof o[f]&&(d[f]=o[f].bind(o));for(var h in l)a(h);for(var p in d)i(p);function m(){var r;(null==(r=e.template)?void 0:r.$player)&&!e.option.autoSize&&Object.assign(o.style,{width:"100%",height:"100%",objectFit:"contain"})}return e.on("destroy",function(){l.destroy()}),e.on("resize",m),e.on("video:loadedmetadata",m),o}},{"@swc/helpers/cjs/_to_consumable_array.cjs":"i81N6","../shim/mediabunnyVideoShim.js":"4Z3fn","@parcel/transformer-js/src/esmodule-helpers.js":"qpMMf"}],i81N6:[function(e,r,n,a){"use strict";var i=e("d402183024004bc7"),s=e("3209e2b12672cd18"),o=e("fc58adb8f1bff142"),c=e("5e213dc122a10171");n._=function(e){return i._(e)||s._(e)||c._(e)||o._()}},{d402183024004bc7:"hfQG0","3209e2b12672cd18":"fQrlQ",fc58adb8f1bff142:"fWabh","5e213dc122a10171":"fh7mx"}],hfQG0:[function(e,r,n,a){"use strict";var i=e("5bd5b10bf87fc8e");n._=function(e){if(Array.isArray(e))return i._(e)}},{"5bd5b10bf87fc8e":"1WOAB"}],"1WOAB":[function(e,r,n,a){"use strict";n._=function(e,r){(null==r||r>e.length)&&(r=e.length);for(var n=0,a=Array(r);n<r;n++)a[n]=e[n];return a}},{}],fQrlQ:[function(e,r,n,a){"use strict";n._=function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}},{}],fWabh:[function(e,r,n,a){"use strict";n._=function(){throw TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}},{}],fh7mx:[function(e,r,n,a){"use strict";var i=e("3ee51b7dc02d0c44");n._=function(e,r){if(e){if("string"==typeof e)return i._(e,r);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(n);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return i._(e,r)}}},{"3ee51b7dc02d0c44":"1WOAB"}],"4Z3fn":[function(e,r,n,a){var i=e("@parcel/transformer-js/src/esmodule-helpers.js");i.defineInteropFlag(n),i.export(n,"default",function(){return d});var s=e("../engine/mediabunnyEngine.js"),o=i.interopDefault(s),c=e("../utils/clamp.js"),u=i.interopDefault(c),l=e("./videoEvents.js");function d(e){var r,n,a=e.art,i=e.canvas,s=e.ctx,c=e.option,d=(0,l.createVideoEventTarget)(),f=(0,o.default)({canvas:i,ctx:s,events:d,option:c}),h=null,p=null!=(n=c.volume)?n:.7,m=!!c.muted,g=1;f.setVolume(p,m),a.constructor.config.events.forEach(function(e){d.addEventListener(e,function(e){a.emit("video:".concat(e.type),e)})});var b={addEvLine truncated
@@ -0,0 +1,8 @@
/*!
* artplayer-proxy-mediabunny.js v1.0.0
* Github: https://github.com/zhw2590582/ArtPlayer
* (c) 2017-2025 Harvey Zack
* Released under the MIT License.
*/
!function(e,r,a,i,s,n,o,l){var c="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},d="function"==typeof c[i]&&c[i],u=d.i||{},m=d.cache||{},h="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function p(r,a){if(!m[r]){if(!e[r]){if(s[r])return s[r];var n="function"==typeof c[i]&&c[i];if(!a&&n)return n(r,!0);if(d)return d(r,!0);if(h&&"string"==typeof r)return h(r);var o=Error("Cannot find module '"+r+"'");throw o.code="MODULE_NOT_FOUND",o}u.resolve=function(a){var i=e[r][1][a];return null!=i?i:a},u.cache={};var l=m[r]=new p.Module(r);e[r][0].call(l.exports,u,l,l.exports,c)}return m[r].exports;function u(e){var r=u.resolve(e);return!1===r?{}:p(r)}}p.isParcelRequire=!0,p.Module=function(e){this.id=e,this.bundle=p,this.require=h,this.exports={}},p.modules=e,p.cache=m,p.parent=d,p.distDir=void 0,p.publicUrl=void 0,p.devServer=void 0,p.i=u,p.register=function(r,a){e[r]=[function(e,r){r.exports=a},{}]},Object.defineProperty(p,"root",{get:function(){return c[i]}}),c[i]=p;for(var f=0;f<r.length;f++)p(r[f]);if(a){var g=p(a);"object"==typeof exports&&"undefined"!=typeof module?module.exports=g:"function"==typeof define&&define.amd&&define(function(){return g})}}({"2x2Ir":[function(e,r,a,i){var s=e("@parcel/transformer-js/src/esmodule-helpers.js");s.defineInteropFlag(a),s.export(a,"default",()=>l);var n=e("./proxy/canvasProxy.js"),o=s.interopDefault(n);function l(e={}){return r=>(0,o.default)(r,e)}"undefined"!=typeof window&&(window.artplayerProxyMediabunny=l)},{"./proxy/canvasProxy.js":"dQEB4","@parcel/transformer-js/src/esmodule-helpers.js":"loqXi"}],dQEB4:[function(e,r,a,i){var s=e("@parcel/transformer-js/src/esmodule-helpers.js");s.defineInteropFlag(a),s.export(a,"default",()=>l);var n=e("../shim/mediabunnyVideoShim.js"),o=s.interopDefault(n);function l(e,r){let{constructor:a}=e,{createElement:i}=a.utils,s=i("canvas"),n=s.getContext("2d"),l=(0,o.default)({art:e,canvas:s,ctx:n,option:r}),c={};for(let e in s)"function"==typeof s[e]&&(c[e]=s[e].bind(s));for(let e in l)e in s||Object.defineProperty(s,e,{get(){let r=l[e];return"function"==typeof r?r.bind(l):r},set(r){l[e]=r},configurable:!0,enumerable:!0});for(let e in c)s[e]=(...r)=>c[e](...r);function d(){e.template?.$player&&!e.option.autoSize&&Object.assign(s.style,{width:"100%",height:"100%",objectFit:"contain"})}return e.on("destroy",()=>{l.destroy()}),e.on("resize",d),e.on("video:loadedmetadata",d),s}},{"../shim/mediabunnyVideoShim.js":"1TXLF","@parcel/transformer-js/src/esmodule-helpers.js":"loqXi"}],"1TXLF":[function(e,r,a,i){var s=e("@parcel/transformer-js/src/esmodule-helpers.js");s.defineInteropFlag(a),s.export(a,"default",()=>u);var n=e("../engine/mediabunnyEngine.js"),o=s.interopDefault(n),l=e("../utils/clamp.js"),c=s.interopDefault(l),d=e("./videoEvents.js");function u({art:e,canvas:r,ctx:a,option:i}){let s=(0,d.createVideoEventTarget)(),n=(0,o.default)({canvas:r,ctx:a,events:s,option:i}),l=null,u=i.volume??.7,m=!!i.muted,h=1;n.setVolume(u,m);let{events:p}=e.constructor.config;p.forEach(r=>{s.addEventListener(r,r=>{e.emit(`video:${r.type}`,r)})});let f={addEventListener:s.addEventListener,removeEventListener:s.removeEventListener,get src(){return l},set src(v){l=v,v&&n.load(v)},get currentTime(){return n.currentTime},set currentTime(t){n.seek(Number(t)||0)},get duration(){return n.duration},get buffered(){let e=n.duration;if(!e||Number.isNaN(e))return{length:0,start:()=>0,end:()=>0};return{length:1,start:()=>0,end:()=>e}},get played(){let e=n.duration,r=n.currentTime;if(!e||Number.isNaN(e)||r<=0)return{length:0,start:()=>0,end:()=>0};return{length:1,start:()=>0,end:()=>r}},get paused(){return n.paused},get playing(){return!n.paused&&!n.ended},get ended(){return n.ended},get readyState(){return n.readyState},get networkState(){return n.networkState},get error(){return n.error},get seeking(){return n.seeking},get seekable(){let e=n.duration;if(!e||Number.isNaN(e))return{length:0,start:()=>0,end:()=>0};return{length:1,start:()=>0,end:()=>e}},get playbackRate(){return h},set playbackRate(v){let e=Number(v);if(Number.isNaN(e)||e<=0)return;h=e,n.setPlaybackRate(e),s.emit("ratechange")},get volume(){return u},set volume(v){u=(0,c.default)(v,0,1),m=!1,n.setVolume(u,m),s.emit("volumechange")},get muted(){return m},set muted(v){m=!!v,n.setVolume(u,m),s.emit("volumechange")},play:()=>n.play(),pause(){n.pause()},load(){l&&n.load(l)},destroy(){n.destroy()},get videoWidth(){return n.videoWidth},get videoHeight(){return n.videoHeight},get playsInline(){return!0},set playsInline(v){},get autoplay(){return i.autoplay||!1},set autoplay(v){},get loop(){return i.loop||!1},set loop(v){},get controls(){return!1},set controls(v){},get crossOrigin(){return i.crossOrigin||""},set crossOrigin(v){},get currentSrc(){return l},get poster(){return i.poster||""},set poster(v){i.poster=v},get preload(){return"auto"},set preload(v){},get defaultMuted(){retuLine truncated
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,40 @@
{
"name": "artplayer-proxy-mediabunny",
"version": "1.0.0",
"description": "mediabunny proxy for ArtPlayer",
"author": "Harvey Zack <laozhaochaguan@gmail.com>",
"license": "MIT",
"homepage": "https://artplayer.org",
"repository": {
"type": "git",
"url": "git+https://github.com/zhw2590582/ArtPlayer.git"
},
"bugs": {
"url": "https://github.com/zhw2590582/ArtPlayer/issues"
},
"keywords": [
"html5",
"video",
"player"
],
"exports": {
".": {
"types": "./types/artplayer-proxy-mediabunny.d.ts",
"import": "./dist/artplayer-proxy-mediabunny.mjs",
"require": "./dist/artplayer-proxy-mediabunny.js"
},
"./legacy": {
"types": "./types/artplayer-proxy-mediabunny.d.ts",
"import": "./dist/artplayer-proxy-mediabunny.legacy.js",
"require": "./dist/artplayer-proxy-mediabunny.legacy.js"
}
},
"main": "./dist/artplayer-proxy-mediabunny.js",
"module": "./dist/artplayer-proxy-mediabunny.mjs",
"types": "./types/artplayer-proxy-mediabunny.d.ts",
"legacy": "./dist/artplayer-proxy-mediabunny.legacy.js",
"browserslist": "last 1 Chrome version",
"dependencies": {
"mediabunny": "^1.26.0"
}
}
@@ -0,0 +1,316 @@
import {
ALL_FORMATS,
AudioBufferSink,
BlobSource,
Input,
ReadableStreamSource,
UrlSource,
} from 'mediabunny'
export default function createAudioEngine(events) {
let input = null
let audioSink = null
let audioContext = null
let gainNode = null
let audioIterator = null
let audioContextStartTime = 0
let playbackTimeAtStart = 0
let latestScheduledEndTime = 0
let _duration = Number.NaN
let _paused = true
let _volume = 0.7
let _muted = false
let _playbackRate = 1
let asyncId = 0
const queuedNodes = new Set()
function getCurrentTime() {
if (_paused)
return playbackTimeAtStart
return (
(audioContext.currentTime - audioContextStartTime) * _playbackRate
+ playbackTimeAtStart
)
}
function updateGain() {
if (!gainNode)
return
const v = _muted ? 0 : _volume
gainNode.gain.value = v * v
}
function ensureAudioContext(sampleRate) {
if (audioContext)
return
const AudioContext
= window.AudioContext || window.webkitAudioContext
try {
audioContext = new AudioContext({ sampleRate })
}
catch {
audioContext = new AudioContext()
}
gainNode = audioContext.createGain()
gainNode.connect(audioContext.destination)
updateGain()
}
function stopQueuedNodes() {
for (const node of queuedNodes) {
node.stop()
}
queuedNodes.clear()
}
async function stopIterator() {
await audioIterator?.return()
audioIterator = null
}
function normalizeSource(src) {
if (typeof src === 'string')
return new UrlSource(src)
if (src instanceof Blob)
return new BlobSource(src)
if (typeof ReadableStream !== 'undefined' && src instanceof ReadableStream)
return new ReadableStreamSource(src)
return src
}
async function load(src, onMetadata) {
asyncId++
const id = asyncId
await stopIterator()
stopQueuedNodes()
_paused = true
playbackTimeAtStart = 0
audioContextStartTime = 0
const source = normalizeSource(src)
if (!source)
return
input = new Input({
source,
formats: ALL_FORMATS,
})
_duration = await input.computeDuration()
if (id !== asyncId)
return
const audioTrack = await input.getPrimaryAudioTrack()
if (!audioTrack) {
audioSink = null
ensureAudioContext()
if (onMetadata)
onMetadata()
return
}
if (audioTrack.codec === null || !(await audioTrack.canDecode())) {
audioSink = null
ensureAudioContext()
if (onMetadata)
onMetadata()
return
}
ensureAudioContext(audioTrack.sampleRate)
audioSink = new AudioBufferSink(audioTrack)
if (onMetadata)
onMetadata()
}
async function runIterator(localId) {
if (!audioSink)
return
await stopIterator()
audioIterator = audioSink.buffers(getCurrentTime())
while (true) {
if (localId !== asyncId)
return
if (_paused)
return
const nextPromise = audioIterator.next()
const checkStarvation = setInterval(() => {
if (localId !== asyncId || _paused) {
clearInterval(checkStarvation)
return
}
if (audioContext.state === 'running'
&& audioContext.currentTime >= latestScheduledEndTime - 0.2) {
audioContext.suspend()
events.emit('waiting')
}
}, 50)
let result
try {
result = await nextPromise
}
catch (e) {
console.error(e)
break
}
finally {
clearInterval(checkStarvation)
}
if (localId !== asyncId)
return
if (_paused)
return
if (audioContext.state === 'suspended') {
await audioContext.resume()
events.emit('canplay')
events.emit('playing')
}
if (result.done)
break
const { buffer, timestamp } = result.value
const node = audioContext.createBufferSource()
node.buffer = buffer
node.connect(gainNode)
node.playbackRate.value = _playbackRate
const startAt
= audioContextStartTime
+ (timestamp - playbackTimeAtStart) / _playbackRate
const duration = buffer.duration
const endAt = startAt + duration / _playbackRate
if (endAt > latestScheduledEndTime) {
latestScheduledEndTime = endAt
}
if (startAt >= audioContext.currentTime) {
node.start(startAt)
}
else {
node.start(
audioContext.currentTime,
(audioContext.currentTime - startAt) * _playbackRate,
)
}
queuedNodes.add(node)
node.onended = () => queuedNodes.delete(node)
}
}
async function play() {
if (!_paused)
return
if (!audioContext) {
ensureAudioContext()
}
if (audioContext.state === 'suspended') {
await audioContext.resume()
}
audioContextStartTime = audioContext.currentTime
latestScheduledEndTime = audioContextStartTime
_paused = false
asyncId++
runIterator(asyncId)
}
function pause() {
if (_paused)
return
playbackTimeAtStart = getCurrentTime()
_paused = true
stopIterator()
stopQueuedNodes()
}
async function seek(time) {
playbackTimeAtStart = Math.max(0, time)
audioContextStartTime = audioContext.currentTime
latestScheduledEndTime = audioContextStartTime
asyncId++
if (!_paused) {
runIterator(asyncId)
}
}
function destroy() {
asyncId++
pause()
audioContext?.close()
audioContext = null
input = null
audioSink = null
}
return {
load,
play,
pause,
seek,
destroy,
setVolume(v, muted) {
_volume = v
_muted = muted
updateGain()
},
setPlaybackRate(rate) {
if (rate === _playbackRate)
return
if (!_paused) {
playbackTimeAtStart = getCurrentTime()
audioContextStartTime = audioContext.currentTime
}
_playbackRate = rate
if (!_paused) {
asyncId++
runIterator(asyncId)
}
},
get currentTime() {
return getCurrentTime()
},
get duration() {
return _duration
},
get paused() {
return _paused
},
}
}
@@ -0,0 +1,220 @@
import createAudioEngine from './audioEngine.js'
import createVideoEngine from './videoEngine.js'
export default function createMediabunnyEngine({
canvas,
ctx,
events,
option = {},
}) {
const defaults = {
timeupdateInterval: 250,
avSyncTolerance: 0.12,
loadTimeout: 12000,
dropLateFrames: false,
poster: '',
}
const audio = createAudioEngine(events)
const video = createVideoEngine({
canvas,
ctx,
events,
timeupdateInterval: option.timeupdateInterval ?? defaults.timeupdateInterval,
avSyncTolerance: option.avSyncTolerance ?? defaults.avSyncTolerance,
dropLateFrames: option.dropLateFrames ?? defaults.dropLateFrames,
poster: option.poster ?? defaults.poster,
preflightRange: option.preflightRange ?? false,
})
let _paused = true
let _ended = false
let _readyState = 0
let _networkState = 0
let _error = null
let _seeking = false
let loadSeq = 0
events.addEventListener?.('ended', () => {
_ended = true
_paused = true
})
async function load(src) {
const id = ++loadSeq
pause()
_ended = false
_error = null
_networkState = 2
_readyState = 0
setTimeout(() => events.emit('waiting'), 0)
setTimeout(() => events.emit('loadstart'), 0)
const loadTimeout = Number.isFinite(option.loadTimeout)
? option.loadTimeout
: defaults.loadTimeout
let timer = null
const timeoutPromise
= loadTimeout > 0
? new Promise((_, reject) => {
timer = setTimeout(() => reject(new Error('Load timeout')), loadTimeout)
})
: null
const loadTask = (async () => {
try {
let videoMetadataLoaded = false
let audioMetadataLoaded = false
const checkMetadata = () => {
if (videoMetadataLoaded && audioMetadataLoaded) {
_readyState = 1
events.emit('loadedmetadata')
events.emit('durationchange')
}
}
const p1 = video.load(src, () => {
if (id !== loadSeq)
return
videoMetadataLoaded = true
checkMetadata()
})
const p2 = audio.load(src, () => {
if (id !== loadSeq)
return
audioMetadataLoaded = true
checkMetadata()
})
await Promise.all([p1, p2])
if (id !== loadSeq)
return
_readyState = 4
_networkState = 1
events.emit('loadeddata')
events.emit('canplay')
events.emit('canplaythrough')
}
catch (err) {
if (id !== loadSeq)
return
_error = { code: 4, message: err.message }
_networkState = 3
events.emit('error')
console.error(err)
}
finally {
if (timer)
clearTimeout(timer)
}
})()
if (timeoutPromise) {
try {
await Promise.race([loadTask, timeoutPromise])
}
catch (err) {
if (id !== loadSeq)
return
loadSeq++
_error = { code: 4, message: err.message }
_networkState = 3
events.emit('error')
}
}
else {
await loadTask
}
}
async function play() {
if (!_paused)
return
_ended = false
_paused = false
await audio.play()
video.start(audio)
events.emit('play')
events.emit('playing')
}
function pause() {
if (_paused)
return
_paused = true
audio.pause()
video.stop()
events.emit('pause')
}
async function seek(time) {
const shouldResume = !_paused
_ended = false
_seeking = true
events.emit('seeking')
events.emit('waiting')
pause()
await audio.seek(time)
await video.seek(time)
_seeking = false
events.emit('seeked')
if (shouldResume && !_ended) {
await play()
}
}
function destroy() {
pause()
audio.destroy()
video.destroy()
}
return {
load,
play,
pause,
seek,
destroy,
setVolume: audio.setVolume,
setPlaybackRate(rate) {
audio.setPlaybackRate(rate)
video.setPlaybackRate(rate)
},
get currentTime() {
return audio.currentTime
},
get duration() {
return audio.duration || video.duration
},
get paused() {
return _paused
},
get seeking() {
return _seeking
},
get ended() {
return _ended
},
get readyState() {
return _readyState
},
get networkState() {
return _networkState
},
get error() {
return _error
},
get videoWidth() {
return video.width
},
get videoHeight() {
return video.height
},
}
}
@@ -0,0 +1,308 @@
import {
ALL_FORMATS,
BlobSource,
CanvasSink,
Input,
ReadableStreamSource,
UrlSource,
} from 'mediabunny'
export default function createVideoEngine({
canvas,
ctx,
events,
timeupdateInterval = 250,
avSyncTolerance = 0.12,
dropLateFrames = false,
poster = '',
preflightRange = false,
}) {
let input = null
let videoSink = null
let videoIterator = null
let nextFrame = null
let rafId = 0
let asyncId = 0
let _width = 0
let _height = 0
let _duration = Number.NaN
let audioClock = null
let lastTimeUpdate = 0
let stalled = false
let playbackRate = 1
let posterDrawn = false
function normalizeSource(src) {
if (typeof src === 'string')
return new UrlSource(src)
if (src instanceof Blob)
return new BlobSource(src)
if (typeof ReadableStream !== 'undefined' && src instanceof ReadableStream)
return new ReadableStreamSource(src)
return src
}
async function preflight(url) {
if (!preflightRange || typeof url !== 'string')
return true
try {
const res = await fetch(url, { method: 'HEAD' })
const acceptRanges = res.headers.get('accept-ranges')
if (!acceptRanges || acceptRanges === 'none') {
events.emit('error', new Event('RangeNotSupported'))
return false
}
return true
}
catch (e) {
console.warn('preflight failed', e)
return true
}
}
function drawPoster() {
if (!poster || posterDrawn)
return
const img = new Image()
img.onload = () => {
ctx.clearRect(0, 0, canvas.width, canvas.height)
canvas.width = img.naturalWidth || canvas.width
canvas.height = img.naturalHeight || canvas.height
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
posterDrawn = true
}
img.src = poster
}
async function stopIterator() {
await videoIterator?.return()
videoIterator = null
}
function clear() {
ctx.clearRect(0, 0, canvas.width, canvas.height)
}
async function load(src, onMetadata) {
asyncId++
const id = asyncId
await stopIterator()
clear()
posterDrawn = false
if (!(await preflight(src)))
return
const source = normalizeSource(src)
if (!source) {
drawPoster()
return
}
input = new Input({
source,
formats: ALL_FORMATS,
})
_duration = await input.computeDuration()
if (id !== asyncId)
return
const videoTrack = await input.getPrimaryVideoTrack()
if (!videoTrack) {
videoSink = null
_width = 0
_height = 0
canvas.width = 0
canvas.height = 0
drawPoster()
if (onMetadata)
onMetadata()
return
}
if (videoTrack.codec === null || !(await videoTrack.canDecode())) {
videoSink = null
_width = 0
_height = 0
canvas.width = 0
canvas.height = 0
clear()
drawPoster()
if (onMetadata)
onMetadata()
return
}
const transparent = await videoTrack.canBeTransparent()
videoSink = new CanvasSink(videoTrack, {
poolSize: 2,
fit: 'contain',
alpha: transparent,
})
_width = videoTrack.displayWidth
_height = videoTrack.displayHeight
canvas.width = _width
canvas.height = _height
if (onMetadata)
onMetadata()
await resetIterator(0)
}
async function resetIterator(time) {
await stopIterator()
if (!videoSink)
return
videoIterator = videoSink.canvases(time)
const first = (await videoIterator.next()).value ?? null
const second = (await videoIterator.next()).value ?? null
nextFrame = second
if (first) {
ctx.drawImage(first.canvas, 0, 0)
events.emit('loadeddata')
}
else {
drawPoster()
}
}
async function updateNextFrame(localId) {
if (!videoIterator)
return
while (true) {
const frame = (await videoIterator.next()).value ?? null
if (!frame)
return
if (localId !== asyncId)
return
const t = audioClock.currentTime
if (dropLateFrames) {
const tolerance = Math.max(0.06, avSyncTolerance / Math.max(1, playbackRate))
if (frame.timestamp < t - tolerance) {
continue
}
if (frame.timestamp <= t + tolerance) {
ctx.clearRect(0, 0, canvas.width, canvas.height)
ctx.drawImage(frame.canvas, 0, 0)
}
else {
nextFrame = frame
return
}
}
else {
if (frame.timestamp <= t) {
ctx.clearRect(0, 0, canvas.width, canvas.height)
ctx.drawImage(frame.canvas, 0, 0)
}
else {
nextFrame = frame
return
}
}
}
}
function render() {
if (!audioClock)
return
const t = audioClock.currentTime
const now = Date.now()
if (now - lastTimeUpdate >= timeupdateInterval) {
events.emit('timeupdate')
lastTimeUpdate = now
}
if (Number.isFinite(_duration) && t >= _duration) {
stop()
events.emit('ended')
return
}
if (nextFrame && nextFrame.timestamp <= t) {
ctx.clearRect(0, 0, canvas.width, canvas.height)
ctx.drawImage(nextFrame.canvas, 0, 0)
nextFrame = null
updateNextFrame(asyncId)
if (stalled) {
events.emit('canplay')
events.emit('playing')
stalled = false
}
}
else if (!nextFrame) {
updateNextFrame(asyncId)
if (!nextFrame && Number.isFinite(_duration) && t < _duration && !stalled) {
stalled = true
events.emit('waiting')
}
}
rafId = requestAnimationFrame(render)
}
function start(audioEngine) {
audioClock = audioEngine
asyncId++
stalled = false
updateNextFrame(asyncId)
rafId = requestAnimationFrame(render)
}
function stop() {
cancelAnimationFrame(rafId)
}
async function seek(time) {
asyncId++
await resetIterator(time)
}
function setPlaybackRate(rate) {
playbackRate = Math.max(0.1, Number(rate) || 1)
}
function destroy() {
asyncId++
stop()
stopIterator()
posterDrawn = false
input = null
videoSink = null
}
return {
load,
start,
stop,
seek,
setPlaybackRate,
destroy,
get width() {
return _width
},
get height() {
return _height
},
get duration() {
return _duration
},
}
}
@@ -0,0 +1,11 @@
import createCanvasProxy from './proxy/canvasProxy.js'
export default function artplayerProxyMediabunny(option = {}) {
return (art) => {
return createCanvasProxy(art, option)
}
}
if (typeof window !== 'undefined') {
window.artplayerProxyMediabunny = artplayerProxyMediabunny
}
@@ -0,0 +1,64 @@
import createMediabunnyVideoShim from '../shim/mediabunnyVideoShim.js'
export default function createCanvasProxy(art, option) {
const { constructor } = art
const { createElement } = constructor.utils
const canvas = createElement('canvas')
const ctx = canvas.getContext('2d')
const shim = createMediabunnyVideoShim({
art,
canvas,
ctx,
option,
})
const originalCanvasMethods = {}
for (const prop in canvas) {
if (typeof canvas[prop] === 'function') {
originalCanvasMethods[prop] = canvas[prop].bind(canvas)
}
}
for (const prop in shim) {
if (!(prop in canvas)) {
Object.defineProperty(canvas, prop, {
get() {
const value = shim[prop]
return typeof value === 'function' ? value.bind(shim) : value
},
set(v) {
shim[prop] = v
},
configurable: true,
enumerable: true,
})
}
}
for (const prop in originalCanvasMethods) {
canvas[prop] = (...args) => originalCanvasMethods[prop](...args)
}
art.on('destroy', () => {
shim.destroy()
})
function resize() {
const player = art.template?.$player
if (!player || art.option.autoSize)
return
Object.assign(canvas.style, {
width: '100%',
height: '100%',
objectFit: 'contain',
})
}
art.on('resize', resize)
art.on('video:loadedmetadata', resize)
return canvas
}
@@ -0,0 +1,278 @@
import createMediabunnyEngine from '../engine/mediabunnyEngine.js'
import clamp from '../utils/clamp.js'
import { createVideoEventTarget } from './videoEvents.js'
export default function createMediabunnyVideoShim({ art, canvas, ctx, option }) {
const events = createVideoEventTarget()
const engine = createMediabunnyEngine({ canvas, ctx, events, option })
let _src = null
let _volume = option.volume ?? 0.7
let _muted = !!option.muted
let _playbackRate = 1
engine.setVolume(_volume, _muted)
const { events: artEvents } = art.constructor.config
artEvents.forEach((name) => {
events.addEventListener(name, (e) => {
art.emit(`video:${e.type}`, e)
})
})
const shim = {
addEventListener: events.addEventListener,
removeEventListener: events.removeEventListener,
get src() {
return _src
},
set src(v) {
_src = v
if (v)
engine.load(v)
},
get currentTime() {
return engine.currentTime
},
set currentTime(t) {
engine.seek(Number(t) || 0)
},
get duration() {
return engine.duration
},
get buffered() {
const duration = engine.duration
if (!duration || Number.isNaN(duration)) {
return {
length: 0,
start: () => 0,
end: () => 0,
}
}
return {
length: 1,
start: () => 0,
end: () => duration,
}
},
get played() {
const duration = engine.duration
const currentTime = engine.currentTime
if (!duration || Number.isNaN(duration) || currentTime <= 0) {
return {
length: 0,
start: () => 0,
end: () => 0,
}
}
return {
length: 1,
start: () => 0,
end: () => currentTime,
}
},
get paused() {
return engine.paused
},
get playing() {
return !engine.paused && !engine.ended
},
get ended() {
return engine.ended
},
get readyState() {
return engine.readyState
},
get networkState() {
return engine.networkState
},
get error() {
return engine.error
},
get seeking() {
return engine.seeking
},
get seekable() {
const duration = engine.duration
if (!duration || Number.isNaN(duration)) {
return {
length: 0,
start: () => 0,
end: () => 0,
}
}
return {
length: 1,
start: () => 0,
end: () => duration,
}
},
get playbackRate() {
return _playbackRate
},
set playbackRate(v) {
const rate = Number(v)
if (Number.isNaN(rate) || rate <= 0)
return
_playbackRate = rate
engine.setPlaybackRate(rate)
events.emit('ratechange')
},
get volume() {
return _volume
},
set volume(v) {
_volume = clamp(v, 0, 1)
_muted = false
engine.setVolume(_volume, _muted)
events.emit('volumechange')
},
get muted() {
return _muted
},
set muted(v) {
_muted = !!v
engine.setVolume(_volume, _muted)
events.emit('volumechange')
},
play() {
return engine.play()
},
pause() {
engine.pause()
},
load() {
if (_src)
engine.load(_src)
},
destroy() {
engine.destroy()
},
get videoWidth() {
return engine.videoWidth
},
get videoHeight() {
return engine.videoHeight
},
get playsInline() {
return true
},
set playsInline(v) {},
get autoplay() {
return option.autoplay || false
},
set autoplay(v) {},
get loop() {
return option.loop || false
},
set loop(v) {},
get controls() {
return false
},
set controls(v) {},
get crossOrigin() {
return option.crossOrigin || ''
},
set crossOrigin(v) {},
get currentSrc() {
return _src
},
get poster() {
return option.poster || ''
},
set poster(v) {
option.poster = v
},
get preload() {
return 'auto'
},
set preload(v) {},
get defaultMuted() {
return false
},
set defaultMuted(v) {},
get defaultPlaybackRate() {
return 1
},
set defaultPlaybackRate(v) {},
canPlayType(_type) {
return 'maybe'
},
getBoundingClientRect() {
return canvas.getBoundingClientRect()
},
requestVideoFrameCallback(callback) {
const id = requestAnimationFrame((time) => {
callback(time, {
presentationTime: engine.currentTime,
expectedDisplayTime: time + 16.6,
width: engine.videoWidth,
height: engine.videoHeight,
mediaTime: engine.currentTime,
presentedFrames: 0,
processingDuration: 0,
captureTime: time,
receiveTime: time,
rtpTimestamp: 0,
})
})
return id
},
cancelVideoFrameCallback(id) {
cancelAnimationFrame(id)
},
setAttribute(name, value) {
if (name === 'src')
this.src = value
else if (name === 'autoplay')
this.autoplay = value
else if (name === 'loop')
this.loop = value
else if (name === 'muted')
this.muted = true
else
canvas.setAttribute(name, value)
},
}
if (option.source) {
shim.src = option.source
}
else if (art.option?.url) {
shim.src = art.option.url
}
return shim
}
@@ -0,0 +1,28 @@
export function createVideoEventTarget() {
const listeners = new Map()
function addEventListener(type, fn) {
if (!listeners.has(type))
listeners.set(type, [])
listeners.get(type).push(fn)
}
function removeEventListener(type, fn) {
const list = listeners.get(type)
if (!list)
return
const i = list.indexOf(fn)
if (i >= 0)
list.splice(i, 1)
}
function emit(type, detail) {
const evt = new Event(type)
evt.detail = detail
const list = listeners.get(type)
if (list)
list.forEach(fn => fn(evt))
}
return { addEventListener, removeEventListener, emit }
}
@@ -0,0 +1,3 @@
export default function clamp(v, min, max) {
return Math.max(min, Math.min(max, Number(v) || 0))
}
@@ -0,0 +1,18 @@
import type Artplayer from 'artplayer'
interface Option {
eventDelay?: number
loadTimeout?: number
timeupdateInterval?: number
avSyncTolerance?: number
dropLateFrames?: boolean
poster?: string
source?: string | Blob | ReadableStream<Uint8Array>
preflightRange?: boolean
}
type Result = HTMLCanvasElement
declare const artplayerProxyMediabunny: (option?: Option) => (art: Artplayer) => Result
export default artplayerProxyMediabunny
+1 -1
View File
@@ -5,4 +5,4 @@
* (c) 2017-2025 Harvey Zack
* Released under the MIT License.
*/
!function(e,t,r,a,o,i,n,s){var l="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},c="function"==typeof l[a]&&l[a],p=c.i||{},u=c.cache||{},d="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function f(t,r){if(!u[t]){if(!e[t]){if(o[t])return o[t];var i="function"==typeof l[a]&&l[a];if(!r&&i)return i(t,!0);if(c)return c(t,!0);if(d&&"string"==typeof t)return d(t);var n=Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}p.resolve=function(r){var a=e[t][1][r];return null!=a?a:r},p.cache={};var s=u[t]=new f.Module(t);e[t][0].call(s.exports,p,s,s.exports,l)}return u[t].exports;function p(e){var t=p.resolve(e);return!1===t?{}:f(t)}}f.isParcelRequire=!0,f.Module=function(e){this.id=e,this.bundle=f,this.require=d,this.exports={}},f.modules=e,f.cache=u,f.parent=c,f.distDir=void 0,f.publicUrl=void 0,f.devServer=void 0,f.i=p,f.register=function(t,r){e[t]=[function(e,t){t.exports=r},{}]},Object.defineProperty(f,"root",{get:function(){return l[a]}}),l[a]=f;for(var h=0;h<t.length;h++)f(t[h]);if(r){var m=f(r);"object"==typeof exports&&"undefined"!=typeof module?module.exports=m:"function"==typeof define&&define.amd&&define(function(){return m})}}({"9IAQF":[function(e,t,r,a){var o=e("@parcel/transformer-js/src/esmodule-helpers.js");o.defineInteropFlag(r);var i=e("bundle-text:./style/index.less"),n=o.interopDefault(i),s=e("option-validator"),l=o.interopDefault(s),c=e("../package.json"),p=e("./config"),u=o.interopDefault(p),d=e("./contextmenu"),f=o.interopDefault(d),h=e("./control"),m=o.interopDefault(h),g=e("./events"),v=o.interopDefault(g),y=e("./hotkey"),b=o.interopDefault(y),x=e("./i18n"),w=o.interopDefault(x),k=e("./icons"),j=o.interopDefault(k),S=e("./info"),$=o.interopDefault(S),E=e("./layer"),I=o.interopDefault(E),M=e("./loading"),T=o.interopDefault(M),C=e("./mask"),F=o.interopDefault(C),D=e("./notice"),A=o.interopDefault(D),R=e("./player"),O=o.interopDefault(R),L=e("./plugins"),P=o.interopDefault(L),Y=e("./scheme"),z=o.interopDefault(Y),_=e("./setting"),H=o.interopDefault(_),V=e("./storage"),q=o.interopDefault(V),N=e("./subtitle"),B=o.interopDefault(N),W=e("./template"),U=o.interopDefault(W),Z=e("./utils"),K=e("./utils/emitter"),X=o.interopDefault(K);let G=0,J=[];class Q extends X.default{constructor(e,t){if(super(),!Z.isBrowser)throw Error("Artplayer can only be used in the browser environment");this.id=++G;let r=Z.mergeDeep(Q.option,e);if(r.container=e.container,this.option=(0,l.default)(r,z.default),this.isLock=!1,this.isReady=!1,this.isFocus=!1,this.isInput=!1,this.isRotate=!1,this.isDestroy=!1,this.template=new(0,U.default)(this),this.events=new(0,v.default)(this),this.storage=new(0,q.default)(this),this.icons=new(0,j.default)(this),this.i18n=new(0,w.default)(this),this.notice=new(0,A.default)(this),this.player=new(0,O.default)(this),this.layers=new(0,I.default)(this),this.controls=new(0,m.default)(this),this.contextmenu=new(0,f.default)(this),this.subtitle=new(0,B.default)(this),this.info=new(0,$.default)(this),this.loading=new(0,T.default)(this),this.hotkey=new(0,b.default)(this),this.mask=new(0,F.default)(this),this.setting=new(0,H.default)(this),this.plugins=new(0,P.default)(this),"function"==typeof t&&this.on("ready",()=>t.call(this,this)),Q.DEBUG){let e=e=>console.log(`[ART.${this.id}] -> ${e}`);e(`Version@${Q.version}`);for(let t=0;t<u.default.events.length;t++)this.on(`video:${u.default.events[t]}`,t=>e(`Event@${t.type}`))}J.push(this)}static get instances(){return J}static get version(){return c.version}static get config(){return u.default}static get utils(){return Z}static get scheme(){return z.default}static get Emitter(){return X.default}static get validator(){return l.default}static get kindOf(){return l.default.kindOf}static get html(){return U.default.html}static get option(){return{id:"",container:"#artplayer",url:"",poster:"",type:"",theme:"#f00",volume:.7,isLive:!1,muted:!1,autoplay:!1,autoSize:!1,autoMini:!1,loop:!1,flip:!1,playbackRate:!1,aspectRatio:!1,screenshot:!1,setting:!1,hotkey:!0,pip:!1,mutex:!0,backdrop:!0,fullscreen:!1,fullscreenWeb:!1,subtitleOffset:!1,miniProgressBar:!1,useSSR:!1,playsInline:!0,lock:!1,gesture:!0,fastForward:!1,autoPlayback:!1,autoOrientation:!1,airplay:!1,proxy:void 0,layers:[],contextmenu:[],controls:[],settings:[],quality:[],highlight:[],plugins:[],thumbnails:{url:"",number:60,column:10,width:0,height:0,scale:1},subtitle:{url:"",type:"",style:{},name:"",escape:!0,encoding:"utf-8",onVttLoad:e=>e},moreVideoAttr:{controls:!1,preload:Z.isSafari?"auto":"metadata"},i18n:{},icons:{},cssVar:{},customType:{},lang:navigator?.language.toLowerCase()}}get proxy(){return this.events.proxy}get query(){return this.template.query}get video(){return this.template.$video}reset(){this.video.removeAttribute("src"),this.video.load()}destroy(e=!0){Q.REMOVE_SRC_WHEN_DESTROY&&this.reset(),this.events.destroy(),this.template.destroy(e)Line truncated
!function(e,t,r,a,o,i,n,s){var l="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},c="function"==typeof l[a]&&l[a],p=c.i||{},d=c.cache||{},u="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function f(t,r){if(!d[t]){if(!e[t]){if(o[t])return o[t];var i="function"==typeof l[a]&&l[a];if(!r&&i)return i(t,!0);if(c)return c(t,!0);if(u&&"string"==typeof t)return u(t);var n=Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}p.resolve=function(r){var a=e[t][1][r];return null!=a?a:r},p.cache={};var s=d[t]=new f.Module(t);e[t][0].call(s.exports,p,s,s.exports,l)}return d[t].exports;function p(e){var t=p.resolve(e);return!1===t?{}:f(t)}}f.isParcelRequire=!0,f.Module=function(e){this.id=e,this.bundle=f,this.require=u,this.exports={}},f.modules=e,f.cache=d,f.parent=c,f.distDir=void 0,f.publicUrl=void 0,f.devServer=void 0,f.i=p,f.register=function(t,r){e[t]=[function(e,t){t.exports=r},{}]},Object.defineProperty(f,"root",{get:function(){return l[a]}}),l[a]=f;for(var h=0;h<t.length;h++)f(t[h]);if(r){var m=f(r);"object"==typeof exports&&"undefined"!=typeof module?module.exports=m:"function"==typeof define&&define.amd&&define(function(){return m})}}({"9IAQF":[function(e,t,r,a){var o=e("@parcel/transformer-js/src/esmodule-helpers.js");o.defineInteropFlag(r);var i=e("bundle-text:./style/index.less"),n=o.interopDefault(i),s=e("option-validator"),l=o.interopDefault(s),c=e("../package.json"),p=e("./config"),d=o.interopDefault(p),u=e("./contextmenu"),f=o.interopDefault(u),h=e("./control"),m=o.interopDefault(h),g=e("./events"),v=o.interopDefault(g),y=e("./hotkey"),b=o.interopDefault(y),x=e("./i18n"),w=o.interopDefault(x),k=e("./icons"),j=o.interopDefault(k),S=e("./info"),$=o.interopDefault(S),E=e("./layer"),I=o.interopDefault(E),M=e("./loading"),T=o.interopDefault(M),C=e("./mask"),F=o.interopDefault(C),D=e("./notice"),A=o.interopDefault(D),R=e("./player"),O=o.interopDefault(R),L=e("./plugins"),P=o.interopDefault(L),Y=e("./scheme"),z=o.interopDefault(Y),_=e("./setting"),H=o.interopDefault(_),V=e("./storage"),q=o.interopDefault(V),N=e("./subtitle"),B=o.interopDefault(N),W=e("./template"),U=o.interopDefault(W),Z=e("./utils"),K=e("./utils/emitter"),X=o.interopDefault(K);let G=0,J=[];class Q extends X.default{constructor(e,t){if(super(),!Z.isBrowser)throw Error("Artplayer can only be used in the browser environment");this.id=++G;let r=Z.mergeDeep(Q.option,e);if(r.container=e.container,this.option=(0,l.default)(r,z.default),this.isLock=!1,this.isReady=!1,this.isFocus=!1,this.isInput=!1,this.isRotate=!1,this.isDestroy=!1,this.template=new(0,U.default)(this),this.events=new(0,v.default)(this),this.storage=new(0,q.default)(this),this.icons=new(0,j.default)(this),this.i18n=new(0,w.default)(this),this.notice=new(0,A.default)(this),this.player=new(0,O.default)(this),this.layers=new(0,I.default)(this),this.controls=new(0,m.default)(this),this.contextmenu=new(0,f.default)(this),this.subtitle=new(0,B.default)(this),this.info=new(0,$.default)(this),this.loading=new(0,T.default)(this),this.hotkey=new(0,b.default)(this),this.mask=new(0,F.default)(this),this.setting=new(0,H.default)(this),this.plugins=new(0,P.default)(this),"function"==typeof t&&this.on("ready",()=>t.call(this,this)),Q.DEBUG){let e=e=>console.log(`[ART.${this.id}] -> ${e}`);e(`Version@${Q.version}`);for(let t=0;t<d.default.events.length;t++)this.on(`video:${d.default.events[t]}`,t=>e(`Event@${t.type}`))}J.push(this)}static get instances(){return J}static get version(){return c.version}static get config(){return d.default}static get utils(){return Z}static get scheme(){return z.default}static get Emitter(){return X.default}static get validator(){return l.default}static get kindOf(){return l.default.kindOf}static get html(){return U.default.html}static get option(){return{id:"",container:"#artplayer",url:"",poster:"",type:"",theme:"#f00",volume:.7,isLive:!1,muted:!1,autoplay:!1,autoSize:!1,autoMini:!1,loop:!1,flip:!1,playbackRate:!1,aspectRatio:!1,screenshot:!1,setting:!1,hotkey:!0,pip:!1,mutex:!0,backdrop:!0,fullscreen:!1,fullscreenWeb:!1,subtitleOffset:!1,miniProgressBar:!1,useSSR:!1,playsInline:!0,lock:!1,gesture:!0,fastForward:!1,autoPlayback:!1,autoOrientation:!1,airplay:!1,proxy:void 0,layers:[],contextmenu:[],controls:[],settings:[],quality:[],highlight:[],plugins:[],thumbnails:{url:"",number:60,column:10,width:0,height:0,scale:1},subtitle:{url:"",type:"",style:{},name:"",escape:!0,encoding:"utf-8",onVttLoad:e=>e},moreVideoAttr:{controls:!1,preload:Z.isSafari?"auto":"metadata"},i18n:{},icons:{},cssVar:{},customType:{},lang:navigator?.language.toLowerCase()}}get proxy(){return this.events.proxy}get query(){return this.template.query}get video(){return this.template.$video}reset(){this.video.removeAttribute("src"),this.video.load()}destroy(e=!0){Q.REMOVE_SRC_WHEN_DESTROY&&this.reset(),this.events.destroy(),this.template.destroy(e)Line truncated
+1 -1
View File
@@ -5,4 +5,4 @@
* (c) 2017-2025 Harvey Zack
* Released under the MIT License.
*/
!function(e,t,r,n,o,a,s,i){var c="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},l="function"==typeof c[n]&&c[n],u=l.i||{},p=l.cache||{},f="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function d(t,r){if(!p[t]){if(!e[t]){if(o[t])return o[t];var a="function"==typeof c[n]&&c[n];if(!r&&a)return a(t,!0);if(l)return l(t,!0);if(f&&"string"==typeof t)return f(t);var s=Error("Cannot find module '"+t+"'");throw s.code="MODULE_NOT_FOUND",s}u.resolve=function(r){var n=e[t][1][r];return null!=n?n:r},u.cache={};var i=p[t]=new d.Module(t);e[t][0].call(i.exports,u,i,i.exports,c)}return p[t].exports;function u(e){var t=u.resolve(e);return!1===t?{}:d(t)}}d.isParcelRequire=!0,d.Module=function(e){this.id=e,this.bundle=d,this.require=f,this.exports={}},d.modules=e,d.cache=p,d.parent=l,d.distDir=void 0,d.publicUrl=void 0,d.devServer=void 0,d.i=u,d.register=function(t,r){e[t]=[function(e,t){t.exports=r},{}]},Object.defineProperty(d,"root",{get:function(){return c[n]}}),c[n]=d;for(var h=0;h<t.length;h++)d(t[h]);if(r){var m=d(r);"object"==typeof exports&&"undefined"!=typeof module?module.exports=m:"function"==typeof define&&define.amd&&define(function(){return m})}}({ee4D8:[function(e,t,r,n){var o=e("@parcel/transformer-js/src/esmodule-helpers.js");o.defineInteropFlag(r),o.export(r,"default",function(){return en});var a=e("@swc/helpers/cjs/_call_super.cjs"),s=e("@swc/helpers/cjs/_class_call_check.cjs"),i=e("@swc/helpers/cjs/_create_class.cjs"),c=e("@swc/helpers/cjs/_inherits.cjs"),l=e("bundle-text:./style/index.less"),u=o.interopDefault(l),p=e("option-validator"),f=o.interopDefault(p),d=e("../package.json"),h=e("./config"),m=o.interopDefault(h),v=e("./contextmenu"),g=o.interopDefault(v),y=e("./control"),b=o.interopDefault(y),j=e("./events"),w=o.interopDefault(j),_=e("./hotkey"),x=o.interopDefault(_),k=e("./i18n"),M=o.interopDefault(k),S=e("./icons"),E=o.interopDefault(S),I=e("./info"),T=o.interopDefault(I),L=e("./layer"),C=o.interopDefault(L),O=e("./loading"),D=o.interopDefault(O),F=e("./mask"),A=o.interopDefault(F),R=e("./notice"),P=o.interopDefault(R),q=e("./player"),$=o.interopDefault(q),H=e("./plugins"),z=o.interopDefault(H),N=e("./scheme"),V=o.interopDefault(N),B=e("./setting"),U=o.interopDefault(B),W=e("./storage"),Q=o.interopDefault(W),Y=e("./subtitle"),G=o.interopDefault(Y),X=e("./template"),Z=o.interopDefault(X),K=e("./utils"),J=e("./utils/emitter"),ee=o.interopDefault(J),et=0,er=[],en=function(e){"use strict";function t(e,r){if((0,s._)(this,t),n=(0,a._)(this,t),!K.isBrowser)throw Error("Artplayer can only be used in the browser environment");n.id=++et;var n,o=K.mergeDeep(t.option,e);if(o.container=e.container,n.option=(0,f.default)(o,V.default),n.isLock=!1,n.isReady=!1,n.isFocus=!1,n.isInput=!1,n.isRotate=!1,n.isDestroy=!1,n.template=new(0,Z.default)(n),n.events=new(0,w.default)(n),n.storage=new(0,Q.default)(n),n.icons=new(0,E.default)(n),n.i18n=new(0,M.default)(n),n.notice=new(0,P.default)(n),n.player=new(0,$.default)(n),n.layers=new(0,C.default)(n),n.controls=new(0,b.default)(n),n.contextmenu=new(0,g.default)(n),n.subtitle=new(0,G.default)(n),n.info=new(0,T.default)(n),n.loading=new(0,D.default)(n),n.hotkey=new(0,x.default)(n),n.mask=new(0,A.default)(n),n.setting=new(0,U.default)(n),n.plugins=new(0,z.default)(n),"function"==typeof r&&n.on("ready",function(){return r.call(n,n)}),t.DEBUG){var i=function(e){return console.log("[ART.".concat(n.id,"] ->").concat(e))};i("Version@".concat(t.version));for(var c=0;c<m.default.events.length;c++)n.on("video:".concat(m.default.events[c]),function(e){return i("Event@".concat(e.type))})}return er.push(n),n}return(0,c._)(t,e),(0,i._)(t,[{key:"proxy",get:function(){return this.events.proxy}},{key:"query",get:function(){return this.template.query}},{key:"video",get:function(){return this.template.$video}},{key:"reset",value:function(){this.video.removeAttribute("src"),this.video.load()}},{key:"destroy",value:function(){var e=!(arguments.length>0)||void 0===arguments[0]||arguments[0];t.REMOVE_SRC_WHEN_DESTROY&&this.reset(),this.events.destroy(),this.template.destroy(e),er.splice(er.indexOf(this),1),this.isDestroy=!0,this.emit("destroy")}}],[{key:"instances",get:function(){return er}},{key:"version",get:function(){return d.version}},{key:"config",get:function(){return m.default}},{key:"utils",get:function(){return K}},{key:"scheme",get:function(){return V.default}},{key:"Emitter",get:function(){return ee.default}},{key:"validator",get:function(){return f.default}},{key:"kindOf",get:function(){return f.default.kindOf}},{key:"html",get:function(){return Z.default.html}},{key:"option",get:function(){var e;return{id:"",container:"#artplayer",url:"",poster:"",type:"",theme:"#f00",volume:.7,isLive:!1,muted:!1,autoplay:!1,autoSize:!1,autoMini:!1,loop:!1,flip:!1,playbackRate:!1,aspectRatio:!1,screenshot:!1,setting:!1,hotkey:!0,pip:!1,mutex:!0,backdrop:!0,fLine truncated
!function(e,t,r,n,o,a,s,i){var c="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},l="function"==typeof c[n]&&c[n],u=l.i||{},p=l.cache||{},f="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function d(t,r){if(!p[t]){if(!e[t]){if(o[t])return o[t];var a="function"==typeof c[n]&&c[n];if(!r&&a)return a(t,!0);if(l)return l(t,!0);if(f&&"string"==typeof t)return f(t);var s=Error("Cannot find module '"+t+"'");throw s.code="MODULE_NOT_FOUND",s}u.resolve=function(r){var n=e[t][1][r];return null!=n?n:r},u.cache={};var i=p[t]=new d.Module(t);e[t][0].call(i.exports,u,i,i.exports,c)}return p[t].exports;function u(e){var t=u.resolve(e);return!1===t?{}:d(t)}}d.isParcelRequire=!0,d.Module=function(e){this.id=e,this.bundle=d,this.require=f,this.exports={}},d.modules=e,d.cache=p,d.parent=l,d.distDir=void 0,d.publicUrl=void 0,d.devServer=void 0,d.i=u,d.register=function(t,r){e[t]=[function(e,t){t.exports=r},{}]},Object.defineProperty(d,"root",{get:function(){return c[n]}}),c[n]=d;for(var h=0;h<t.length;h++)d(t[h]);if(r){var m=d(r);"object"==typeof exports&&"undefined"!=typeof module?module.exports=m:"function"==typeof define&&define.amd&&define(function(){return m})}}({ee4D8:[function(e,t,r,n){var o=e("@parcel/transformer-js/src/esmodule-helpers.js");o.defineInteropFlag(r),o.export(r,"default",function(){return en});var a=e("@swc/helpers/cjs/_call_super.cjs"),s=e("@swc/helpers/cjs/_class_call_check.cjs"),i=e("@swc/helpers/cjs/_create_class.cjs"),c=e("@swc/helpers/cjs/_inherits.cjs"),l=e("bundle-text:./style/index.less"),u=o.interopDefault(l),p=e("option-validator"),f=o.interopDefault(p),d=e("../package.json"),h=e("./config"),m=o.interopDefault(h),v=e("./contextmenu"),g=o.interopDefault(v),y=e("./control"),b=o.interopDefault(y),j=e("./events"),w=o.interopDefault(j),_=e("./hotkey"),x=o.interopDefault(_),k=e("./i18n"),M=o.interopDefault(k),S=e("./icons"),E=o.interopDefault(S),I=e("./info"),T=o.interopDefault(I),L=e("./layer"),C=o.interopDefault(L),O=e("./loading"),F=o.interopDefault(O),D=e("./mask"),A=o.interopDefault(D),R=e("./notice"),P=o.interopDefault(R),q=e("./player"),$=o.interopDefault(q),H=e("./plugins"),z=o.interopDefault(H),N=e("./scheme"),V=o.interopDefault(N),B=e("./setting"),U=o.interopDefault(B),W=e("./storage"),Q=o.interopDefault(W),Y=e("./subtitle"),G=o.interopDefault(Y),X=e("./template"),Z=o.interopDefault(X),K=e("./utils"),J=e("./utils/emitter"),ee=o.interopDefault(J),et=0,er=[],en=function(e){"use strict";function t(e,r){if((0,s._)(this,t),n=(0,a._)(this,t),!K.isBrowser)throw Error("Artplayer can only be used in the browser environment");n.id=++et;var n,o=K.mergeDeep(t.option,e);if(o.container=e.container,n.option=(0,f.default)(o,V.default),n.isLock=!1,n.isReady=!1,n.isFocus=!1,n.isInput=!1,n.isRotate=!1,n.isDestroy=!1,n.template=new(0,Z.default)(n),n.events=new(0,w.default)(n),n.storage=new(0,Q.default)(n),n.icons=new(0,E.default)(n),n.i18n=new(0,M.default)(n),n.notice=new(0,P.default)(n),n.player=new(0,$.default)(n),n.layers=new(0,C.default)(n),n.controls=new(0,b.default)(n),n.contextmenu=new(0,g.default)(n),n.subtitle=new(0,G.default)(n),n.info=new(0,T.default)(n),n.loading=new(0,F.default)(n),n.hotkey=new(0,x.default)(n),n.mask=new(0,A.default)(n),n.setting=new(0,U.default)(n),n.plugins=new(0,z.default)(n),"function"==typeof r&&n.on("ready",function(){return r.call(n,n)}),t.DEBUG){var i=function(e){return console.log("[ART.".concat(n.id,"] ->").concat(e))};i("Version@".concat(t.version));for(var c=0;c<m.default.events.length;c++)n.on("video:".concat(m.default.events[c]),function(e){return i("Event@".concat(e.type))})}return er.push(n),n}return(0,c._)(t,e),(0,i._)(t,[{key:"proxy",get:function(){return this.events.proxy}},{key:"query",get:function(){return this.template.query}},{key:"video",get:function(){return this.template.$video}},{key:"reset",value:function(){this.video.removeAttribute("src"),this.video.load()}},{key:"destroy",value:function(){var e=!(arguments.length>0)||void 0===arguments[0]||arguments[0];t.REMOVE_SRC_WHEN_DESTROY&&this.reset(),this.events.destroy(),this.template.destroy(e),er.splice(er.indexOf(this),1),this.isDestroy=!0,this.emit("destroy")}}],[{key:"instances",get:function(){return er}},{key:"version",get:function(){return d.version}},{key:"config",get:function(){return m.default}},{key:"utils",get:function(){return K}},{key:"scheme",get:function(){return V.default}},{key:"Emitter",get:function(){return ee.default}},{key:"validator",get:function(){return f.default}},{key:"kindOf",get:function(){return f.default.kindOf}},{key:"html",get:function(){return Z.default.html}},{key:"option",get:function(){var e;return{id:"",container:"#artplayer",url:"",poster:"",type:"",theme:"#f00",volume:.7,isLive:!1,muted:!1,autoplay:!1,autoSize:!1,autoMini:!1,loop:!1,flip:!1,playbackRate:!1,aspectRatio:!1,screenshot:!1,setting:!1,hotkey:!0,pip:!1,mutex:!0,backdrop:!0,fLine truncated
+1 -1
View File
@@ -5,4 +5,4 @@
* (c) 2017-2025 Harvey Zack
* Released under the MIT License.
*/
!function(e,t,r,a,o,i,n,s){var l="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},c="function"==typeof l[a]&&l[a],p=c.i||{},d=c.cache||{},u="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function f(t,r){if(!d[t]){if(!e[t]){if(o[t])return o[t];var i="function"==typeof l[a]&&l[a];if(!r&&i)return i(t,!0);if(c)return c(t,!0);if(u&&"string"==typeof t)return u(t);var n=Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}p.resolve=function(r){var a=e[t][1][r];return null!=a?a:r},p.cache={};var s=d[t]=new f.Module(t);e[t][0].call(s.exports,p,s,s.exports,l)}return d[t].exports;function p(e){var t=p.resolve(e);return!1===t?{}:f(t)}}f.isParcelRequire=!0,f.Module=function(e){this.id=e,this.bundle=f,this.require=u,this.exports={}},f.modules=e,f.cache=d,f.parent=c,f.distDir=void 0,f.publicUrl=void 0,f.devServer=void 0,f.i=p,f.register=function(t,r){e[t]=[function(e,t){t.exports=r},{}]},Object.defineProperty(f,"root",{get:function(){return l[a]}}),l[a]=f;for(var h=0;h<t.length;h++)f(t[h]);if(r){var m=f(r);"object"==typeof exports&&"undefined"!=typeof module?module.exports=m:"function"==typeof define&&define.amd&&define(function(){return m})}}({esqvp:[function(e,t,r,a){var o=e("@parcel/transformer-js/src/esmodule-helpers.js");o.defineInteropFlag(r);var i=e("bundle-text:./style/index.less"),n=o.interopDefault(i),s=e("option-validator"),l=o.interopDefault(s),c=e("../package.json"),p=e("./config"),d=o.interopDefault(p),u=e("./contextmenu"),f=o.interopDefault(u),h=e("./control"),m=o.interopDefault(h),g=e("./events"),v=o.interopDefault(g),y=e("./hotkey"),b=o.interopDefault(y),x=e("./i18n"),w=o.interopDefault(x),j=e("./icons"),k=o.interopDefault(j),E=e("./info"),S=o.interopDefault(E),$=e("./layer"),M=o.interopDefault($),I=e("./loading"),T=o.interopDefault(I),C=e("./mask"),F=o.interopDefault(C),q=e("./notice"),D=o.interopDefault(q),A=e("./player"),R=o.interopDefault(A),B=e("./plugins"),L=o.interopDefault(B),O=e("./scheme"),P=o.interopDefault(O),z=e("./setting"),X=o.interopDefault(z),V=e("./storage"),_=o.interopDefault(V),H=e("./subtitle"),N=o.interopDefault(H),W=e("./template"),U=o.interopDefault(W),Y=e("./utils"),Z=e("./utils/emitter"),K=o.interopDefault(Z);let G=0,J=[];class Q extends K.default{constructor(e,t){if(super(),!Y.isBrowser)throw Error("Artplayer can only be used in the browser environment");this.id=++G;let r=Y.mergeDeep(Q.option,e);if(r.container=e.container,this.option=(0,l.default)(r,P.default),this.isLock=!1,this.isReady=!1,this.isFocus=!1,this.isInput=!1,this.isRotate=!1,this.isDestroy=!1,this.template=new(0,U.default)(this),this.events=new(0,v.default)(this),this.storage=new(0,_.default)(this),this.icons=new(0,k.default)(this),this.i18n=new(0,w.default)(this),this.notice=new(0,D.default)(this),this.player=new(0,R.default)(this),this.layers=new(0,M.default)(this),this.controls=new(0,m.default)(this),this.contextmenu=new(0,f.default)(this),this.subtitle=new(0,N.default)(this),this.info=new(0,S.default)(this),this.loading=new(0,T.default)(this),this.hotkey=new(0,b.default)(this),this.mask=new(0,F.default)(this),this.setting=new(0,X.default)(this),this.plugins=new(0,L.default)(this),"function"==typeof t&&this.on("ready",()=>t.call(this,this)),Q.DEBUG){let e=e=>console.log(`[ART.${this.id}] -> ${e}`);e(`Version@${Q.version}`);for(let t=0;t<d.default.events.length;t++)this.on(`video:${d.default.events[t]}`,t=>e(`Event@${t.type}`))}J.push(this)}static get instances(){return J}static get version(){return c.version}static get config(){return d.default}static get utils(){return Y}static get scheme(){return P.default}static get Emitter(){return K.default}static get validator(){return l.default}static get kindOf(){return l.default.kindOf}static get html(){return U.default.html}static get option(){return{id:"",container:"#artplayer",url:"",poster:"",type:"",theme:"#f00",volume:.7,isLive:!1,muted:!1,autoplay:!1,autoSize:!1,autoMini:!1,loop:!1,flip:!1,playbackRate:!1,aspectRatio:!1,screenshot:!1,setting:!1,hotkey:!0,pip:!1,mutex:!0,backdrop:!0,fullscreen:!1,fullscreenWeb:!1,subtitleOffset:!1,miniProgressBar:!1,useSSR:!1,playsInline:!0,lock:!1,gesture:!0,fastForward:!1,autoPlayback:!1,autoOrientation:!1,airplay:!1,proxy:void 0,layers:[],contextmenu:[],controls:[],settings:[],quality:[],highlight:[],plugins:[],thumbnails:{url:"",number:60,column:10,width:0,height:0,scale:1},subtitle:{url:"",type:"",style:{},name:"",escape:!0,encoding:"utf-8",onVttLoad:e=>e},moreVideoAttr:{controls:!1,preload:Y.isSafari?"auto":"metadata"},i18n:{},icons:{},cssVar:{},customType:{},lang:navigator?.language.toLowerCase()}}get proxy(){return this.events.proxy}get query(){return this.template.query}get video(){return this.template.$video}reset(){this.video.removeAttribute("src"),this.video.load()}destroy(e=!0){Q.REMOVE_SRC_WHEN_DESTROY&&this.reset(),this.events.destroy(),this.template.destroy(e),JLine truncated
!function(e,t,r,a,o,i,n,s){var l="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},c="function"==typeof l[a]&&l[a],p=c.i||{},d=c.cache||{},u="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function f(t,r){if(!d[t]){if(!e[t]){if(o[t])return o[t];var i="function"==typeof l[a]&&l[a];if(!r&&i)return i(t,!0);if(c)return c(t,!0);if(u&&"string"==typeof t)return u(t);var n=Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}p.resolve=function(r){var a=e[t][1][r];return null!=a?a:r},p.cache={};var s=d[t]=new f.Module(t);e[t][0].call(s.exports,p,s,s.exports,l)}return d[t].exports;function p(e){var t=p.resolve(e);return!1===t?{}:f(t)}}f.isParcelRequire=!0,f.Module=function(e){this.id=e,this.bundle=f,this.require=u,this.exports={}},f.modules=e,f.cache=d,f.parent=c,f.distDir=void 0,f.publicUrl=void 0,f.devServer=void 0,f.i=p,f.register=function(t,r){e[t]=[function(e,t){t.exports=r},{}]},Object.defineProperty(f,"root",{get:function(){return l[a]}}),l[a]=f;for(var h=0;h<t.length;h++)f(t[h]);if(r){var m=f(r);"object"==typeof exports&&"undefined"!=typeof module?module.exports=m:"function"==typeof define&&define.amd&&define(function(){return m})}}({esqvp:[function(e,t,r,a){var o=e("@parcel/transformer-js/src/esmodule-helpers.js");o.defineInteropFlag(r);var i=e("bundle-text:./style/index.less"),n=o.interopDefault(i),s=e("option-validator"),l=o.interopDefault(s),c=e("../package.json"),p=e("./config"),d=o.interopDefault(p),u=e("./contextmenu"),f=o.interopDefault(u),h=e("./control"),m=o.interopDefault(h),g=e("./events"),v=o.interopDefault(g),y=e("./hotkey"),b=o.interopDefault(y),x=e("./i18n"),w=o.interopDefault(x),j=e("./icons"),k=o.interopDefault(j),E=e("./info"),S=o.interopDefault(E),$=e("./layer"),M=o.interopDefault($),I=e("./loading"),T=o.interopDefault(I),C=e("./mask"),F=o.interopDefault(C),q=e("./notice"),D=o.interopDefault(q),A=e("./player"),R=o.interopDefault(A),B=e("./plugins"),L=o.interopDefault(B),O=e("./scheme"),P=o.interopDefault(O),z=e("./setting"),X=o.interopDefault(z),V=e("./storage"),_=o.interopDefault(V),H=e("./subtitle"),N=o.interopDefault(H),W=e("./template"),U=o.interopDefault(W),Y=e("./utils"),Z=e("./utils/emitter"),K=o.interopDefault(Z);let G=0,J=[];class Q extends K.default{constructor(e,t){if(super(),!Y.isBrowser)throw Error("Artplayer can only be used in the browser environment");this.id=++G;let r=Y.mergeDeep(Q.option,e);if(r.container=e.container,this.option=(0,l.default)(r,P.default),this.isLock=!1,this.isReady=!1,this.isFocus=!1,this.isInput=!1,this.isRotate=!1,this.isDestroy=!1,this.template=new(0,U.default)(this),this.events=new(0,v.default)(this),this.storage=new(0,_.default)(this),this.icons=new(0,k.default)(this),this.i18n=new(0,w.default)(this),this.notice=new(0,D.default)(this),this.player=new(0,R.default)(this),this.layers=new(0,M.default)(this),this.controls=new(0,m.default)(this),this.contextmenu=new(0,f.default)(this),this.subtitle=new(0,N.default)(this),this.info=new(0,S.default)(this),this.loading=new(0,T.default)(this),this.hotkey=new(0,b.default)(this),this.mask=new(0,F.default)(this),this.setting=new(0,X.default)(this),this.plugins=new(0,L.default)(this),"function"==typeof t&&this.on("ready",()=>t.call(this,this)),Q.DEBUG){let e=e=>console.log(`[ART.${this.id}] -> ${e}`);e(`Version@${Q.version}`);for(let t=0;t<d.default.events.length;t++)this.on(`video:${d.default.events[t]}`,t=>e(`Event@${t.type}`))}J.push(this)}static get instances(){return J}static get version(){return c.version}static get config(){return d.default}static get utils(){return Y}static get scheme(){return P.default}static get Emitter(){return K.default}static get validator(){return l.default}static get kindOf(){return l.default.kindOf}static get html(){return U.default.html}static get option(){return{id:"",container:"#artplayer",url:"",poster:"",type:"",theme:"#f00",volume:.7,isLive:!1,muted:!1,autoplay:!1,autoSize:!1,autoMini:!1,loop:!1,flip:!1,playbackRate:!1,aspectRatio:!1,screenshot:!1,setting:!1,hotkey:!0,pip:!1,mutex:!0,backdrop:!0,fullscreen:!1,fullscreenWeb:!1,subtitleOffset:!1,miniProgressBar:!1,useSSR:!1,playsInline:!0,lock:!1,gesture:!0,fastForward:!1,autoPlayback:!1,autoOrientation:!1,airplay:!1,proxy:void 0,layers:[],contextmenu:[],controls:[],settings:[],quality:[],highlight:[],plugins:[],thumbnails:{url:"",number:60,column:10,width:0,height:0,scale:1},subtitle:{url:"",type:"",style:{},name:"",escape:!0,encoding:"utf-8",onVttLoad:e=>e},moreVideoAttr:{controls:!1,preload:Y.isSafari?"auto":"metadata"},i18n:{},icons:{},cssVar:{},customType:{},lang:navigator?.language.toLowerCase()}}get proxy(){return this.events.proxy}get query(){return this.template.query}get video(){return this.template.$video}reset(){this.video.removeAttribute("src"),this.video.load()}destroy(e=!0){Q.REMOVE_SRC_WHEN_DESTROY&&this.reset(),this.events.destroy(),this.template.destroy(e),JLine truncated
+3 -3
View File
@@ -173,9 +173,9 @@ export default class Setting extends Component {
const settingLeft = controlLeft - playerLeft + controlWidth / 2 - settingWidth / 2
const settingHeight
= this.active === this.option
? this.active.length * SETTING_ITEM_HEIGHT
: (this.active.length + 1) * SETTING_ITEM_HEIGHT
= this.active === this.option
? this.active.length * SETTING_ITEM_HEIGHT
: (this.active.length + 1) * SETTING_ITEM_HEIGHT
setStyle($setting, 'height', `${settingHeight}px`)
setStyle($setting, 'width', `${settingWidth}px`)