vidply 1.0.26 → 1.0.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dev/{vidply.HLSRenderer-X46P47LY.js → vidply.HLSRenderer-ENLZE4QS.js} +13 -8
- package/dist/dev/vidply.HLSRenderer-ENLZE4QS.js.map +7 -0
- package/dist/dev/{vidply.HTML5Renderer-LXQ3I45Q.js → vidply.HTML5Renderer-6SBDI6S2.js} +2 -2
- package/dist/dev/vidply.SoundCloudRenderer-CD7VJKNS.js +280 -0
- package/dist/dev/vidply.SoundCloudRenderer-CD7VJKNS.js.map +7 -0
- package/dist/dev/{vidply.VimeoRenderer-DCETT5IZ.js → vidply.VimeoRenderer-VPH4RNES.js} +17 -4
- package/dist/dev/vidply.VimeoRenderer-VPH4RNES.js.map +7 -0
- package/dist/dev/{vidply.YouTubeRenderer-QLMMD757.js → vidply.YouTubeRenderer-6MGKEFTZ.js} +14 -6
- package/dist/dev/vidply.YouTubeRenderer-6MGKEFTZ.js.map +7 -0
- package/dist/dev/{vidply.chunk-UEIJOJH6.js → vidply.chunk-BCOFCT6U.js} +4 -1
- package/dist/dev/vidply.chunk-BCOFCT6U.js.map +7 -0
- package/dist/dev/vidply.esm.js +288 -12
- package/dist/dev/vidply.esm.js.map +2 -2
- package/dist/legacy/vidply.js +609 -23
- package/dist/legacy/vidply.js.map +3 -3
- package/dist/legacy/vidply.min.js +1 -1
- package/dist/legacy/vidply.min.meta.json +26 -13
- package/dist/prod/vidply.HLSRenderer-CBXZ4RF2.min.js +6 -0
- package/dist/prod/{vidply.HTML5Renderer-XJCSUETP.min.js → vidply.HTML5Renderer-MY7XDV7R.min.js} +1 -1
- package/dist/prod/vidply.SoundCloudRenderer-MOR2CUFH.min.js +6 -0
- package/dist/prod/vidply.VimeoRenderer-3HBMM2WR.min.js +6 -0
- package/dist/prod/vidply.YouTubeRenderer-MFC2GMAC.min.js +6 -0
- package/dist/prod/vidply.chunk-OXXPY2XB.min.js +6 -0
- package/dist/prod/vidply.esm.min.js +6 -6
- package/dist/vidply.css +51 -0
- package/dist/vidply.esm.min.meta.json +56 -28
- package/dist/vidply.min.css +1 -1
- package/package.json +1 -1
- package/src/core/Player.js +117 -8
- package/src/features/PlaylistManager.js +312 -4
- package/src/renderers/HLSRenderer.js +17 -9
- package/src/renderers/HTML5Renderer.js +5 -0
- package/src/renderers/SoundCloudRenderer.js +355 -0
- package/src/renderers/VimeoRenderer.js +20 -4
- package/src/renderers/YouTubeRenderer.js +12 -6
- package/src/styles/vidply.css +51 -0
- package/dist/dev/vidply.HLSRenderer-X46P47LY.js.map +0 -7
- package/dist/dev/vidply.VimeoRenderer-DCETT5IZ.js.map +0 -7
- package/dist/dev/vidply.YouTubeRenderer-QLMMD757.js.map +0 -7
- package/dist/dev/vidply.chunk-UEIJOJH6.js.map +0 -7
- package/dist/prod/vidply.HLSRenderer-LDXSMWTI.min.js +0 -6
- package/dist/prod/vidply.VimeoRenderer-P3PU27S7.min.js +0 -6
- package/dist/prod/vidply.YouTubeRenderer-DGKKWB5M.min.js +0 -6
- package/dist/prod/vidply.chunk-BQBGEJF7.min.js +0 -6
- /package/dist/dev/{vidply.HTML5Renderer-LXQ3I45Q.js.map → vidply.HTML5Renderer-6SBDI6S2.js.map} +0 -0
|
@@ -30,7 +30,7 @@ var HLSRenderer = class {
|
|
|
30
30
|
return video.canPlayType("application/vnd.apple.mpegurl") !== "";
|
|
31
31
|
}
|
|
32
32
|
async initNative() {
|
|
33
|
-
const HTML5Renderer = (await import("./vidply.HTML5Renderer-
|
|
33
|
+
const HTML5Renderer = (await import("./vidply.HTML5Renderer-6SBDI6S2.js")).HTML5Renderer;
|
|
34
34
|
const renderer = new HTML5Renderer(this.player);
|
|
35
35
|
await renderer.init();
|
|
36
36
|
Object.getOwnPropertyNames(Object.getPrototypeOf(renderer)).forEach((method) => {
|
|
@@ -72,12 +72,14 @@ var HLSRenderer = class {
|
|
|
72
72
|
fragLoadingMaxRetryTimeout: 64e3
|
|
73
73
|
});
|
|
74
74
|
this.hls.attachMedia(this.media);
|
|
75
|
-
let src;
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
75
|
+
let src = this.player.currentSource;
|
|
76
|
+
if (!src) {
|
|
77
|
+
const sourceElement = this.player.element.querySelector("source");
|
|
78
|
+
if (sourceElement) {
|
|
79
|
+
src = sourceElement.getAttribute("src");
|
|
80
|
+
} else {
|
|
81
|
+
src = this.player.element.getAttribute("src") || this.player.element.src;
|
|
82
|
+
}
|
|
81
83
|
}
|
|
82
84
|
this.player.log(`Loading HLS source: ${src}`, "log");
|
|
83
85
|
if (!src) {
|
|
@@ -100,6 +102,9 @@ var HLSRenderer = class {
|
|
|
100
102
|
this.hls.on(window.Hls.Events.MANIFEST_PARSED, (event, data) => {
|
|
101
103
|
this.player.log("HLS manifest loaded, found " + data.levels.length + " quality levels");
|
|
102
104
|
this.player.emit("hlsmanifestparsed", data);
|
|
105
|
+
if (this.player.container) {
|
|
106
|
+
this.player.container.classList.remove("vidply-external-controls");
|
|
107
|
+
}
|
|
103
108
|
});
|
|
104
109
|
this.hls.on(window.Hls.Events.LEVEL_SWITCHED, (event, data) => {
|
|
105
110
|
this.player.log("HLS level switched to " + data.level);
|
|
@@ -258,4 +263,4 @@ var HLSRenderer = class {
|
|
|
258
263
|
export {
|
|
259
264
|
HLSRenderer
|
|
260
265
|
};
|
|
261
|
-
//# sourceMappingURL=vidply.HLSRenderer-
|
|
266
|
+
//# sourceMappingURL=vidply.HLSRenderer-ENLZE4QS.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/renderers/HLSRenderer.js"],
|
|
4
|
+
"sourcesContent": ["/**\r\n * HLS Streaming Renderer\r\n * Uses hls.js for browsers that don't natively support HLS\r\n */\r\n\r\nexport class HLSRenderer {\r\n constructor(player) {\r\n this.player = player;\r\n this.media = player.element;\r\n this.hls = null;\r\n }\r\n\r\n async init() {\r\n // Check if browser natively supports HLS (Safari)\r\n if (this.canPlayNatively()) {\r\n this.player.log('Using native HLS support');\r\n await this.initNative();\r\n } else {\r\n this.player.log('Using hls.js for HLS support');\r\n await this.initHlsJs();\r\n }\r\n }\r\n\r\n canPlayNatively() {\r\n // Only use native HLS on Safari/iOS where it actually works properly\r\n // Chrome reports it can play HLS but doesn't have proper quality switching\r\n const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\r\n const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;\r\n \r\n if (!isSafari && !isIOS) {\r\n // Force hls.js on non-Safari browsers for proper quality switching\r\n return false;\r\n }\r\n \r\n const video = document.createElement('video');\r\n return video.canPlayType('application/vnd.apple.mpegurl') !== '';\r\n }\r\n\r\n async initNative() {\r\n // Use HTML5 renderer for native HLS support\r\n const HTML5Renderer = (await import('./HTML5Renderer.js')).HTML5Renderer;\r\n const renderer = new HTML5Renderer(this.player);\r\n await renderer.init();\r\n \r\n // Copy methods\r\n Object.getOwnPropertyNames(Object.getPrototypeOf(renderer)).forEach(method => {\r\n if (method !== 'constructor' && typeof renderer[method] === 'function') {\r\n this[method] = renderer[method].bind(renderer);\r\n }\r\n });\r\n }\r\n\r\n async initHlsJs() {\r\n // Hide native controls\r\n this.media.controls = false;\r\n this.media.removeAttribute('controls');\r\n \r\n // Load hls.js if not already loaded\r\n if (!window.Hls) {\r\n await this.loadHlsJs();\r\n }\r\n\r\n if (!window.Hls.isSupported()) {\r\n throw new Error('HLS is not supported in this browser');\r\n }\r\n\r\n // Create hls.js instance with better error recovery\r\n this.hls = new window.Hls({\r\n debug: this.player.options.debug,\r\n enableWorker: true,\r\n lowLatencyMode: false,\r\n backBufferLength: 90,\r\n maxBufferLength: 30,\r\n maxMaxBufferLength: 600,\r\n maxBufferSize: 60 * 1000 * 1000,\r\n maxBufferHole: 0.5,\r\n // Network retry settings\r\n manifestLoadingTimeOut: 10000,\r\n manifestLoadingMaxRetry: 4,\r\n manifestLoadingRetryDelay: 1000,\r\n manifestLoadingMaxRetryTimeout: 64000,\r\n levelLoadingTimeOut: 10000,\r\n levelLoadingMaxRetry: 4,\r\n levelLoadingRetryDelay: 1000,\r\n levelLoadingMaxRetryTimeout: 64000,\r\n fragLoadingTimeOut: 20000,\r\n fragLoadingMaxRetry: 6,\r\n fragLoadingRetryDelay: 1000,\r\n fragLoadingMaxRetryTimeout: 64000\r\n });\r\n\r\n // Attach media element\r\n this.hls.attachMedia(this.media);\r\n\r\n // Load source - use currentSource for external renderers, or get from attribute\r\n let src = this.player.currentSource;\r\n \r\n if (!src) {\r\n const sourceElement = this.player.element.querySelector('source');\r\n if (sourceElement) {\r\n // Use getAttribute to get the original URL, not the blob-converted one\r\n src = sourceElement.getAttribute('src');\r\n } else {\r\n // Fallback to element's src attribute\r\n src = this.player.element.getAttribute('src') || this.player.element.src;\r\n }\r\n }\r\n \r\n this.player.log(`Loading HLS source: ${src}`, 'log');\r\n \r\n if (!src) {\r\n throw new Error('No HLS source found');\r\n }\r\n \r\n this.hls.loadSource(src);\r\n\r\n // Attach events\r\n this.attachHlsEvents();\r\n this.attachMediaEvents();\r\n }\r\n\r\n async loadHlsJs() {\r\n return new Promise((resolve, reject) => {\r\n const script = document.createElement('script');\r\n script.src = 'https://cdn.jsdelivr.net/npm/hls.js@latest';\r\n script.onload = () => resolve();\r\n script.onerror = () => reject(new Error('Failed to load hls.js'));\r\n document.head.appendChild(script);\r\n });\r\n }\r\n\r\n attachHlsEvents() {\r\n this.hls.on(window.Hls.Events.MANIFEST_PARSED, (event, data) => {\r\n this.player.log('HLS manifest loaded, found ' + data.levels.length + ' quality levels');\r\n this.player.emit('hlsmanifestparsed', data);\r\n \r\n // Show VidPly controls (remove external controls class if present)\r\n if (this.player.container) {\r\n this.player.container.classList.remove('vidply-external-controls');\r\n }\r\n });\r\n\r\n this.hls.on(window.Hls.Events.LEVEL_SWITCHED, (event, data) => {\r\n this.player.log('HLS level switched to ' + data.level);\r\n this.player.emit('hlslevelswitched', data);\r\n });\r\n\r\n this.hls.on(window.Hls.Events.ERROR, (event, data) => {\r\n this.handleHlsError(data);\r\n });\r\n\r\n this.hls.on(window.Hls.Events.FRAG_BUFFERED, () => {\r\n this.player.state.buffering = false;\r\n });\r\n }\r\n\r\n attachMediaEvents() {\r\n // Use same events as HTML5 renderer\r\n this.media.addEventListener('loadedmetadata', () => {\r\n this.player.state.duration = this.media.duration;\r\n this.player.emit('loadedmetadata');\r\n });\r\n\r\n this.media.addEventListener('play', () => {\r\n this.player.state.playing = true;\r\n this.player.state.paused = false;\r\n this.player.state.ended = false;\r\n this.player.emit('play');\r\n \r\n if (this.player.options.onPlay) {\r\n this.player.options.onPlay.call(this.player);\r\n }\r\n });\r\n\r\n this.media.addEventListener('pause', () => {\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.emit('pause');\r\n \r\n if (this.player.options.onPause) {\r\n this.player.options.onPause.call(this.player);\r\n }\r\n });\r\n\r\n this.media.addEventListener('ended', () => {\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.state.ended = true;\r\n this.player.emit('ended');\r\n \r\n if (this.player.options.onEnded) {\r\n this.player.options.onEnded.call(this.player);\r\n }\r\n \r\n if (this.player.options.loop) {\r\n this.player.seek(0);\r\n this.player.play();\r\n }\r\n });\r\n\r\n this.media.addEventListener('timeupdate', () => {\r\n this.player.state.currentTime = this.media.currentTime;\r\n this.player.emit('timeupdate', this.media.currentTime);\r\n \r\n if (this.player.options.onTimeUpdate) {\r\n this.player.options.onTimeUpdate.call(this.player, this.media.currentTime);\r\n }\r\n });\r\n\r\n this.media.addEventListener('volumechange', () => {\r\n this.player.state.volume = this.media.volume;\r\n this.player.state.muted = this.media.muted;\r\n this.player.emit('volumechange', this.media.volume);\r\n });\r\n\r\n this.media.addEventListener('waiting', () => {\r\n this.player.state.buffering = true;\r\n this.player.emit('waiting');\r\n });\r\n\r\n this.media.addEventListener('canplay', () => {\r\n this.player.state.buffering = false;\r\n this.player.emit('canplay');\r\n });\r\n\r\n this.media.addEventListener('error', () => {\r\n this.player.handleError(this.media.error);\r\n });\r\n }\r\n\r\n handleHlsError(data) {\r\n // Log detailed error info\r\n this.player.log(`HLS Error - Type: ${data.type}, Details: ${data.details}, Fatal: ${data.fatal}`, 'warn');\r\n if (data.response) {\r\n this.player.log(`Response code: ${data.response.code}, URL: ${data.response.url}`, 'warn');\r\n }\r\n \r\n if (data.fatal) {\r\n switch (data.type) {\r\n case window.Hls.ErrorTypes.NETWORK_ERROR:\r\n this.player.log('Fatal network error, trying to recover...', 'error');\r\n this.player.log(`Network error details: ${data.details}`, 'error');\r\n setTimeout(() => {\r\n this.hls.startLoad();\r\n }, 1000);\r\n break;\r\n \r\n case window.Hls.ErrorTypes.MEDIA_ERROR:\r\n this.player.log('Fatal media error, trying to recover...', 'error');\r\n this.hls.recoverMediaError();\r\n break;\r\n \r\n default:\r\n this.player.log('Fatal error, cannot recover', 'error');\r\n this.player.handleError(new Error(`HLS Error: ${data.type} - ${data.details}`));\r\n this.hls.destroy();\r\n break;\r\n }\r\n } else {\r\n this.player.log('Non-fatal HLS error: ' + data.details, 'warn');\r\n }\r\n }\r\n\r\n play() {\r\n // Save scroll position to prevent browser from scrolling to video\r\n const scrollX = window.scrollX;\r\n const scrollY = window.scrollY;\r\n \r\n const promise = this.media.play();\r\n \r\n // Restore scroll position immediately to prevent auto-scroll\r\n window.scrollTo(scrollX, scrollY);\r\n \r\n if (promise !== undefined) {\r\n promise.catch(error => {\r\n this.player.log('Play failed:', error, 'warn');\r\n });\r\n }\r\n }\r\n\r\n pause() {\r\n this.media.pause();\r\n }\r\n\r\n seek(time) {\r\n this.media.currentTime = time;\r\n }\r\n\r\n setVolume(volume) {\r\n this.media.volume = volume;\r\n }\r\n\r\n setMuted(muted) {\r\n this.media.muted = muted;\r\n }\r\n\r\n setPlaybackSpeed(speed) {\r\n this.media.playbackRate = speed;\r\n }\r\n\r\n switchQuality(levelIndex) {\r\n if (this.hls) {\r\n this.hls.currentLevel = levelIndex;\r\n }\r\n }\r\n\r\n getQualities() {\r\n if (this.hls && this.hls.levels) {\r\n return this.hls.levels.map((level, index) => ({\r\n index,\r\n height: level.height,\r\n width: level.width,\r\n bitrate: level.bitrate,\r\n name: `${level.height}p`\r\n }));\r\n }\r\n return [];\r\n }\r\n\r\n getCurrentQuality() {\r\n if (this.hls) {\r\n return this.hls.currentLevel;\r\n }\r\n return -1;\r\n }\r\n\r\n destroy() {\r\n if (this.hls) {\r\n this.hls.destroy();\r\n this.hls = null;\r\n }\r\n }\r\n}\r\n\r\n"],
|
|
5
|
+
"mappings": ";;;;;;;AAKO,IAAM,cAAN,MAAkB;AAAA,EACvB,YAAY,QAAQ;AAClB,SAAK,SAAS;AACd,SAAK,QAAQ,OAAO;AACpB,SAAK,MAAM;AAAA,EACb;AAAA,EAEA,MAAM,OAAO;AAEX,QAAI,KAAK,gBAAgB,GAAG;AAC1B,WAAK,OAAO,IAAI,0BAA0B;AAC1C,YAAM,KAAK,WAAW;AAAA,IACxB,OAAO;AACL,WAAK,OAAO,IAAI,8BAA8B;AAC9C,YAAM,KAAK,UAAU;AAAA,IACvB;AAAA,EACF;AAAA,EAEA,kBAAkB;AAGhB,UAAM,WAAW,iCAAiC,KAAK,UAAU,SAAS;AAC1E,UAAM,QAAQ,mBAAmB,KAAK,UAAU,SAAS,KAAK,CAAC,OAAO;AAEtE,QAAI,CAAC,YAAY,CAAC,OAAO;AAEvB,aAAO;AAAA,IACT;AAEA,UAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,WAAO,MAAM,YAAY,+BAA+B,MAAM;AAAA,EAChE;AAAA,EAEA,MAAM,aAAa;AAEjB,UAAM,iBAAiB,MAAM,OAAO,oCAAoB,GAAG;AAC3D,UAAM,WAAW,IAAI,cAAc,KAAK,MAAM;AAC9C,UAAM,SAAS,KAAK;AAGpB,WAAO,oBAAoB,OAAO,eAAe,QAAQ,CAAC,EAAE,QAAQ,YAAU;AAC5E,UAAI,WAAW,iBAAiB,OAAO,SAAS,MAAM,MAAM,YAAY;AACtE,aAAK,MAAM,IAAI,SAAS,MAAM,EAAE,KAAK,QAAQ;AAAA,MAC/C;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,YAAY;AAEhB,SAAK,MAAM,WAAW;AACtB,SAAK,MAAM,gBAAgB,UAAU;AAGrC,QAAI,CAAC,OAAO,KAAK;AACf,YAAM,KAAK,UAAU;AAAA,IACvB;AAEA,QAAI,CAAC,OAAO,IAAI,YAAY,GAAG;AAC7B,YAAM,IAAI,MAAM,sCAAsC;AAAA,IACxD;AAGA,SAAK,MAAM,IAAI,OAAO,IAAI;AAAA,MACxB,OAAO,KAAK,OAAO,QAAQ;AAAA,MAC3B,cAAc;AAAA,MACd,gBAAgB;AAAA,MAChB,kBAAkB;AAAA,MAClB,iBAAiB;AAAA,MACjB,oBAAoB;AAAA,MACpB,eAAe,KAAK,MAAO;AAAA,MAC3B,eAAe;AAAA;AAAA,MAEf,wBAAwB;AAAA,MACxB,yBAAyB;AAAA,MACzB,2BAA2B;AAAA,MAC3B,gCAAgC;AAAA,MAChC,qBAAqB;AAAA,MACrB,sBAAsB;AAAA,MACtB,wBAAwB;AAAA,MACxB,6BAA6B;AAAA,MAC7B,oBAAoB;AAAA,MACpB,qBAAqB;AAAA,MACrB,uBAAuB;AAAA,MACvB,4BAA4B;AAAA,IAC9B,CAAC;AAGD,SAAK,IAAI,YAAY,KAAK,KAAK;AAG/B,QAAI,MAAM,KAAK,OAAO;AAEtB,QAAI,CAAC,KAAK;AACR,YAAM,gBAAgB,KAAK,OAAO,QAAQ,cAAc,QAAQ;AAChE,UAAI,eAAe;AAEjB,cAAM,cAAc,aAAa,KAAK;AAAA,MACxC,OAAO;AAEL,cAAM,KAAK,OAAO,QAAQ,aAAa,KAAK,KAAK,KAAK,OAAO,QAAQ;AAAA,MACvE;AAAA,IACF;AAEA,SAAK,OAAO,IAAI,uBAAuB,GAAG,IAAI,KAAK;AAEnD,QAAI,CAAC,KAAK;AACR,YAAM,IAAI,MAAM,qBAAqB;AAAA,IACvC;AAEA,SAAK,IAAI,WAAW,GAAG;AAGvB,SAAK,gBAAgB;AACrB,SAAK,kBAAkB;AAAA,EACzB;AAAA,EAEA,MAAM,YAAY;AAChB,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,YAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,aAAO,MAAM;AACb,aAAO,SAAS,MAAM,QAAQ;AAC9B,aAAO,UAAU,MAAM,OAAO,IAAI,MAAM,uBAAuB,CAAC;AAChE,eAAS,KAAK,YAAY,MAAM;AAAA,IAClC,CAAC;AAAA,EACH;AAAA,EAEA,kBAAkB;AAChB,SAAK,IAAI,GAAG,OAAO,IAAI,OAAO,iBAAiB,CAAC,OAAO,SAAS;AAC9D,WAAK,OAAO,IAAI,gCAAgC,KAAK,OAAO,SAAS,iBAAiB;AACtF,WAAK,OAAO,KAAK,qBAAqB,IAAI;AAG1C,UAAI,KAAK,OAAO,WAAW;AACzB,aAAK,OAAO,UAAU,UAAU,OAAO,0BAA0B;AAAA,MACnE;AAAA,IACF,CAAC;AAED,SAAK,IAAI,GAAG,OAAO,IAAI,OAAO,gBAAgB,CAAC,OAAO,SAAS;AAC7D,WAAK,OAAO,IAAI,2BAA2B,KAAK,KAAK;AACrD,WAAK,OAAO,KAAK,oBAAoB,IAAI;AAAA,IAC3C,CAAC;AAED,SAAK,IAAI,GAAG,OAAO,IAAI,OAAO,OAAO,CAAC,OAAO,SAAS;AACpD,WAAK,eAAe,IAAI;AAAA,IAC1B,CAAC;AAED,SAAK,IAAI,GAAG,OAAO,IAAI,OAAO,eAAe,MAAM;AACjD,WAAK,OAAO,MAAM,YAAY;AAAA,IAChC,CAAC;AAAA,EACH;AAAA,EAEA,oBAAoB;AAElB,SAAK,MAAM,iBAAiB,kBAAkB,MAAM;AAClD,WAAK,OAAO,MAAM,WAAW,KAAK,MAAM;AACxC,WAAK,OAAO,KAAK,gBAAgB;AAAA,IACnC,CAAC;AAED,SAAK,MAAM,iBAAiB,QAAQ,MAAM;AACxC,WAAK,OAAO,MAAM,UAAU;AAC5B,WAAK,OAAO,MAAM,SAAS;AAC3B,WAAK,OAAO,MAAM,QAAQ;AAC1B,WAAK,OAAO,KAAK,MAAM;AAEvB,UAAI,KAAK,OAAO,QAAQ,QAAQ;AAC9B,aAAK,OAAO,QAAQ,OAAO,KAAK,KAAK,MAAM;AAAA,MAC7C;AAAA,IACF,CAAC;AAED,SAAK,MAAM,iBAAiB,SAAS,MAAM;AACzC,WAAK,OAAO,MAAM,UAAU;AAC5B,WAAK,OAAO,MAAM,SAAS;AAC3B,WAAK,OAAO,KAAK,OAAO;AAExB,UAAI,KAAK,OAAO,QAAQ,SAAS;AAC/B,aAAK,OAAO,QAAQ,QAAQ,KAAK,KAAK,MAAM;AAAA,MAC9C;AAAA,IACF,CAAC;AAED,SAAK,MAAM,iBAAiB,SAAS,MAAM;AACzC,WAAK,OAAO,MAAM,UAAU;AAC5B,WAAK,OAAO,MAAM,SAAS;AAC3B,WAAK,OAAO,MAAM,QAAQ;AAC1B,WAAK,OAAO,KAAK,OAAO;AAExB,UAAI,KAAK,OAAO,QAAQ,SAAS;AAC/B,aAAK,OAAO,QAAQ,QAAQ,KAAK,KAAK,MAAM;AAAA,MAC9C;AAEA,UAAI,KAAK,OAAO,QAAQ,MAAM;AAC5B,aAAK,OAAO,KAAK,CAAC;AAClB,aAAK,OAAO,KAAK;AAAA,MACnB;AAAA,IACF,CAAC;AAED,SAAK,MAAM,iBAAiB,cAAc,MAAM;AAC9C,WAAK,OAAO,MAAM,cAAc,KAAK,MAAM;AAC3C,WAAK,OAAO,KAAK,cAAc,KAAK,MAAM,WAAW;AAErD,UAAI,KAAK,OAAO,QAAQ,cAAc;AACpC,aAAK,OAAO,QAAQ,aAAa,KAAK,KAAK,QAAQ,KAAK,MAAM,WAAW;AAAA,MAC3E;AAAA,IACF,CAAC;AAED,SAAK,MAAM,iBAAiB,gBAAgB,MAAM;AAChD,WAAK,OAAO,MAAM,SAAS,KAAK,MAAM;AACtC,WAAK,OAAO,MAAM,QAAQ,KAAK,MAAM;AACrC,WAAK,OAAO,KAAK,gBAAgB,KAAK,MAAM,MAAM;AAAA,IACpD,CAAC;AAED,SAAK,MAAM,iBAAiB,WAAW,MAAM;AAC3C,WAAK,OAAO,MAAM,YAAY;AAC9B,WAAK,OAAO,KAAK,SAAS;AAAA,IAC5B,CAAC;AAED,SAAK,MAAM,iBAAiB,WAAW,MAAM;AAC3C,WAAK,OAAO,MAAM,YAAY;AAC9B,WAAK,OAAO,KAAK,SAAS;AAAA,IAC5B,CAAC;AAED,SAAK,MAAM,iBAAiB,SAAS,MAAM;AACzC,WAAK,OAAO,YAAY,KAAK,MAAM,KAAK;AAAA,IAC1C,CAAC;AAAA,EACH;AAAA,EAEA,eAAe,MAAM;AAEnB,SAAK,OAAO,IAAI,qBAAqB,KAAK,IAAI,cAAc,KAAK,OAAO,YAAY,KAAK,KAAK,IAAI,MAAM;AACxG,QAAI,KAAK,UAAU;AACjB,WAAK,OAAO,IAAI,kBAAkB,KAAK,SAAS,IAAI,UAAU,KAAK,SAAS,GAAG,IAAI,MAAM;AAAA,IAC3F;AAEA,QAAI,KAAK,OAAO;AACd,cAAQ,KAAK,MAAM;AAAA,QACjB,KAAK,OAAO,IAAI,WAAW;AACzB,eAAK,OAAO,IAAI,6CAA6C,OAAO;AACpE,eAAK,OAAO,IAAI,0BAA0B,KAAK,OAAO,IAAI,OAAO;AACjE,qBAAW,MAAM;AACf,iBAAK,IAAI,UAAU;AAAA,UACrB,GAAG,GAAI;AACP;AAAA,QAEF,KAAK,OAAO,IAAI,WAAW;AACzB,eAAK,OAAO,IAAI,2CAA2C,OAAO;AAClE,eAAK,IAAI,kBAAkB;AAC3B;AAAA,QAEF;AACE,eAAK,OAAO,IAAI,+BAA+B,OAAO;AACtD,eAAK,OAAO,YAAY,IAAI,MAAM,cAAc,KAAK,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;AAC9E,eAAK,IAAI,QAAQ;AACjB;AAAA,MACJ;AAAA,IACF,OAAO;AACL,WAAK,OAAO,IAAI,0BAA0B,KAAK,SAAS,MAAM;AAAA,IAChE;AAAA,EACF;AAAA,EAEA,OAAO;AAEL,UAAM,UAAU,OAAO;AACvB,UAAM,UAAU,OAAO;AAEvB,UAAM,UAAU,KAAK,MAAM,KAAK;AAGhC,WAAO,SAAS,SAAS,OAAO;AAEhC,QAAI,YAAY,QAAW;AACzB,cAAQ,MAAM,WAAS;AACrB,aAAK,OAAO,IAAI,gBAAgB,OAAO,MAAM;AAAA,MAC/C,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,QAAQ;AACN,SAAK,MAAM,MAAM;AAAA,EACnB;AAAA,EAEA,KAAK,MAAM;AACT,SAAK,MAAM,cAAc;AAAA,EAC3B;AAAA,EAEA,UAAU,QAAQ;AAChB,SAAK,MAAM,SAAS;AAAA,EACtB;AAAA,EAEA,SAAS,OAAO;AACd,SAAK,MAAM,QAAQ;AAAA,EACrB;AAAA,EAEA,iBAAiB,OAAO;AACtB,SAAK,MAAM,eAAe;AAAA,EAC5B;AAAA,EAEA,cAAc,YAAY;AACxB,QAAI,KAAK,KAAK;AACZ,WAAK,IAAI,eAAe;AAAA,IAC1B;AAAA,EACF;AAAA,EAEA,eAAe;AACb,QAAI,KAAK,OAAO,KAAK,IAAI,QAAQ;AAC/B,aAAO,KAAK,IAAI,OAAO,IAAI,CAAC,OAAO,WAAW;AAAA,QAC5C;AAAA,QACA,QAAQ,MAAM;AAAA,QACd,OAAO,MAAM;AAAA,QACb,SAAS,MAAM;AAAA,QACf,MAAM,GAAG,MAAM,MAAM;AAAA,MACvB,EAAE;AAAA,IACJ;AACA,WAAO,CAAC;AAAA,EACV;AAAA,EAEA,oBAAoB;AAClB,QAAI,KAAK,KAAK;AACZ,aAAO,KAAK,IAAI;AAAA,IAClB;AACA,WAAO;AAAA,EACT;AAAA,EAEA,UAAU;AACR,QAAI,KAAK,KAAK;AACZ,WAAK,IAAI,QAAQ;AACjB,WAAK,MAAM;AAAA,IACb;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import {
|
|
7
7
|
HTML5Renderer
|
|
8
|
-
} from "./vidply.chunk-
|
|
8
|
+
} from "./vidply.chunk-BCOFCT6U.js";
|
|
9
9
|
export {
|
|
10
10
|
HTML5Renderer
|
|
11
11
|
};
|
|
12
|
-
//# sourceMappingURL=vidply.HTML5Renderer-
|
|
12
|
+
//# sourceMappingURL=vidply.HTML5Renderer-6SBDI6S2.js.map
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Universal, Accessible Video Player
|
|
3
|
+
* (c) 2025 Matthias Peltzer
|
|
4
|
+
* Released under GPL-2.0-or-later License
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// src/renderers/SoundCloudRenderer.js
|
|
8
|
+
var SoundCloudRenderer = class {
|
|
9
|
+
constructor(player) {
|
|
10
|
+
this.player = player;
|
|
11
|
+
this.widget = null;
|
|
12
|
+
this.trackUrl = null;
|
|
13
|
+
this.isReady = false;
|
|
14
|
+
this.iframe = null;
|
|
15
|
+
this.iframeId = null;
|
|
16
|
+
}
|
|
17
|
+
async init() {
|
|
18
|
+
this.trackUrl = this.player.currentSource || this.player.element.src || this.player.element.querySelector("source")?.src;
|
|
19
|
+
if (!this.trackUrl || !this.isValidSoundCloudUrl(this.trackUrl)) {
|
|
20
|
+
throw new Error("Invalid SoundCloud URL");
|
|
21
|
+
}
|
|
22
|
+
await this.loadSoundCloudAPI();
|
|
23
|
+
this.createIframe();
|
|
24
|
+
await this.initializeWidget();
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Validate SoundCloud URL
|
|
28
|
+
* @param {string} url
|
|
29
|
+
* @returns {boolean}
|
|
30
|
+
*/
|
|
31
|
+
isValidSoundCloudUrl(url) {
|
|
32
|
+
return url.includes("soundcloud.com") || url.includes("api.soundcloud.com");
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Check if URL is a playlist/set
|
|
36
|
+
*/
|
|
37
|
+
isPlaylist() {
|
|
38
|
+
return this.trackUrl && this.trackUrl.includes("/sets/");
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Extract track/playlist info from URL for embed
|
|
42
|
+
* SoundCloud URLs can be:
|
|
43
|
+
* - https://soundcloud.com/artist/track
|
|
44
|
+
* - https://soundcloud.com/artist/sets/playlist
|
|
45
|
+
* - https://api.soundcloud.com/tracks/123456
|
|
46
|
+
*/
|
|
47
|
+
getEmbedUrl() {
|
|
48
|
+
const encodedUrl = encodeURIComponent(this.trackUrl);
|
|
49
|
+
const params = new URLSearchParams({
|
|
50
|
+
url: this.trackUrl,
|
|
51
|
+
auto_play: this.player.options.autoplay ? "true" : "false",
|
|
52
|
+
hide_related: "true",
|
|
53
|
+
show_comments: "false",
|
|
54
|
+
show_user: "true",
|
|
55
|
+
show_reposts: "false",
|
|
56
|
+
show_teaser: "false",
|
|
57
|
+
visual: "false",
|
|
58
|
+
// Use classic player for better control
|
|
59
|
+
color: "%23007bff"
|
|
60
|
+
});
|
|
61
|
+
return `https://w.soundcloud.com/player/?${params.toString()}`;
|
|
62
|
+
}
|
|
63
|
+
async loadSoundCloudAPI() {
|
|
64
|
+
if (window.SC && window.SC.Widget) {
|
|
65
|
+
return Promise.resolve();
|
|
66
|
+
}
|
|
67
|
+
return new Promise((resolve, reject) => {
|
|
68
|
+
const script = document.createElement("script");
|
|
69
|
+
script.src = "https://w.soundcloud.com/player/api.js";
|
|
70
|
+
script.onload = () => {
|
|
71
|
+
setTimeout(() => {
|
|
72
|
+
if (window.SC && window.SC.Widget) {
|
|
73
|
+
resolve();
|
|
74
|
+
} else {
|
|
75
|
+
reject(new Error("SoundCloud Widget API not available"));
|
|
76
|
+
}
|
|
77
|
+
}, 100);
|
|
78
|
+
};
|
|
79
|
+
script.onerror = () => reject(new Error("Failed to load SoundCloud Widget API"));
|
|
80
|
+
document.head.appendChild(script);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
createIframe() {
|
|
84
|
+
this.player.element.style.display = "none";
|
|
85
|
+
this.player.element.removeAttribute("poster");
|
|
86
|
+
if (this.player.videoWrapper) {
|
|
87
|
+
this.player.videoWrapper.classList.remove("vidply-forced-poster");
|
|
88
|
+
this.player.videoWrapper.style.removeProperty("--vidply-poster-image");
|
|
89
|
+
}
|
|
90
|
+
this.iframeId = `soundcloud-player-${Math.random().toString(36).substr(2, 9)}`;
|
|
91
|
+
this.iframe = document.createElement("iframe");
|
|
92
|
+
this.iframe.id = this.iframeId;
|
|
93
|
+
this.iframe.scrolling = "no";
|
|
94
|
+
this.iframe.frameBorder = "no";
|
|
95
|
+
this.iframe.allow = "autoplay";
|
|
96
|
+
this.iframe.src = this.getEmbedUrl();
|
|
97
|
+
this.iframe.style.width = "100%";
|
|
98
|
+
this.iframe.style.display = "block";
|
|
99
|
+
if (this.isPlaylist()) {
|
|
100
|
+
this.iframe.style.aspectRatio = "16 / 9";
|
|
101
|
+
this.iframe.classList.add("vidply-soundcloud-iframe", "vidply-soundcloud-playlist");
|
|
102
|
+
} else {
|
|
103
|
+
this.iframe.style.aspectRatio = "16 / 3";
|
|
104
|
+
this.iframe.classList.add("vidply-soundcloud-iframe");
|
|
105
|
+
}
|
|
106
|
+
this.iframe.style.maxHeight = "100%";
|
|
107
|
+
this.player.element.parentNode.insertBefore(this.iframe, this.player.element);
|
|
108
|
+
}
|
|
109
|
+
async initializeWidget() {
|
|
110
|
+
return new Promise((resolve, reject) => {
|
|
111
|
+
this.iframe.addEventListener("load", () => {
|
|
112
|
+
try {
|
|
113
|
+
this.widget = window.SC.Widget(this.iframe);
|
|
114
|
+
this.widget.bind(window.SC.Widget.Events.READY, () => {
|
|
115
|
+
this.isReady = true;
|
|
116
|
+
this.attachEvents();
|
|
117
|
+
if (this.player.container) {
|
|
118
|
+
this.player.container.classList.add("vidply-external-controls");
|
|
119
|
+
}
|
|
120
|
+
this.widget.getCurrentSound((sound) => {
|
|
121
|
+
if (sound) {
|
|
122
|
+
this.player.state.duration = sound.duration / 1e3;
|
|
123
|
+
this.player.emit("loadedmetadata");
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
resolve();
|
|
127
|
+
});
|
|
128
|
+
this.widget.bind(window.SC.Widget.Events.ERROR, (error) => {
|
|
129
|
+
this.player.handleError(new Error(`SoundCloud error: ${error.message || "Unknown error"}`));
|
|
130
|
+
});
|
|
131
|
+
} catch (error) {
|
|
132
|
+
reject(error);
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
setTimeout(() => {
|
|
136
|
+
if (!this.isReady) {
|
|
137
|
+
reject(new Error("SoundCloud widget initialization timeout"));
|
|
138
|
+
}
|
|
139
|
+
}, 1e4);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
attachEvents() {
|
|
143
|
+
if (!this.widget) return;
|
|
144
|
+
const Events = window.SC.Widget.Events;
|
|
145
|
+
this.widget.bind(Events.PLAY, () => {
|
|
146
|
+
this.player.state.playing = true;
|
|
147
|
+
this.player.state.paused = false;
|
|
148
|
+
this.player.state.ended = false;
|
|
149
|
+
this.player.emit("play");
|
|
150
|
+
if (this.player.options.onPlay) {
|
|
151
|
+
this.player.options.onPlay.call(this.player);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
this.widget.bind(Events.PAUSE, () => {
|
|
155
|
+
this.player.state.playing = false;
|
|
156
|
+
this.player.state.paused = true;
|
|
157
|
+
this.player.emit("pause");
|
|
158
|
+
if (this.player.options.onPause) {
|
|
159
|
+
this.player.options.onPause.call(this.player);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
this.widget.bind(Events.FINISH, () => {
|
|
163
|
+
this.player.state.playing = false;
|
|
164
|
+
this.player.state.paused = true;
|
|
165
|
+
this.player.state.ended = true;
|
|
166
|
+
this.player.emit("ended");
|
|
167
|
+
if (this.player.options.onEnded) {
|
|
168
|
+
this.player.options.onEnded.call(this.player);
|
|
169
|
+
}
|
|
170
|
+
if (this.player.options.loop) {
|
|
171
|
+
this.seek(0);
|
|
172
|
+
this.play();
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
this.widget.bind(Events.PLAY_PROGRESS, (data) => {
|
|
176
|
+
const currentTime = data.currentPosition / 1e3;
|
|
177
|
+
this.player.state.currentTime = currentTime;
|
|
178
|
+
this.player.emit("timeupdate", currentTime);
|
|
179
|
+
if (this.player.options.onTimeUpdate) {
|
|
180
|
+
this.player.options.onTimeUpdate.call(this.player, currentTime);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
this.widget.bind(Events.SEEK, (data) => {
|
|
184
|
+
this.player.state.currentTime = data.currentPosition / 1e3;
|
|
185
|
+
this.player.emit("seeked");
|
|
186
|
+
});
|
|
187
|
+
this.widget.bind(Events.LOAD_PROGRESS, (data) => {
|
|
188
|
+
if (this.player.state.duration) {
|
|
189
|
+
const buffered = data.loadedProgress * this.player.state.duration;
|
|
190
|
+
this.player.emit("progress", buffered);
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
play() {
|
|
195
|
+
if (this.isReady && this.widget) {
|
|
196
|
+
const scrollX = window.scrollX;
|
|
197
|
+
const scrollY = window.scrollY;
|
|
198
|
+
this.widget.play();
|
|
199
|
+
window.scrollTo(scrollX, scrollY);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
pause() {
|
|
203
|
+
if (this.isReady && this.widget) {
|
|
204
|
+
this.widget.pause();
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
seek(time) {
|
|
208
|
+
if (this.isReady && this.widget) {
|
|
209
|
+
this.widget.seekTo(time * 1e3);
|
|
210
|
+
this.player.state.currentTime = time;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
setVolume(volume) {
|
|
214
|
+
if (this.isReady && this.widget) {
|
|
215
|
+
this.widget.setVolume(volume * 100);
|
|
216
|
+
this.player.state.volume = volume;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
setMuted(muted) {
|
|
220
|
+
if (this.isReady && this.widget) {
|
|
221
|
+
if (muted) {
|
|
222
|
+
this.widget.getVolume((vol) => {
|
|
223
|
+
this._previousVolume = vol;
|
|
224
|
+
this.widget.setVolume(0);
|
|
225
|
+
});
|
|
226
|
+
} else {
|
|
227
|
+
this.widget.setVolume(this._previousVolume || 100);
|
|
228
|
+
}
|
|
229
|
+
this.player.state.muted = muted;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
setPlaybackSpeed(speed) {
|
|
233
|
+
this.player.log("SoundCloud does not support playback speed control", "warn");
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Get current track info
|
|
237
|
+
* @returns {Promise<Object>}
|
|
238
|
+
*/
|
|
239
|
+
getCurrentSound() {
|
|
240
|
+
return new Promise((resolve) => {
|
|
241
|
+
if (this.isReady && this.widget) {
|
|
242
|
+
this.widget.getCurrentSound((sound) => {
|
|
243
|
+
resolve(sound);
|
|
244
|
+
});
|
|
245
|
+
} else {
|
|
246
|
+
resolve(null);
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
destroy() {
|
|
251
|
+
if (this.widget) {
|
|
252
|
+
const Events = window.SC.Widget.Events;
|
|
253
|
+
try {
|
|
254
|
+
this.widget.unbind(Events.READY);
|
|
255
|
+
this.widget.unbind(Events.PLAY);
|
|
256
|
+
this.widget.unbind(Events.PAUSE);
|
|
257
|
+
this.widget.unbind(Events.FINISH);
|
|
258
|
+
this.widget.unbind(Events.PLAY_PROGRESS);
|
|
259
|
+
this.widget.unbind(Events.SEEK);
|
|
260
|
+
this.widget.unbind(Events.LOAD_PROGRESS);
|
|
261
|
+
this.widget.unbind(Events.ERROR);
|
|
262
|
+
} catch (e) {
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
if (this.iframe && this.iframe.parentNode) {
|
|
266
|
+
this.iframe.parentNode.removeChild(this.iframe);
|
|
267
|
+
}
|
|
268
|
+
if (this.player.element) {
|
|
269
|
+
this.player.element.style.display = "";
|
|
270
|
+
}
|
|
271
|
+
this.widget = null;
|
|
272
|
+
this.isReady = false;
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
var SoundCloudRenderer_default = SoundCloudRenderer;
|
|
276
|
+
export {
|
|
277
|
+
SoundCloudRenderer,
|
|
278
|
+
SoundCloudRenderer_default as default
|
|
279
|
+
};
|
|
280
|
+
//# sourceMappingURL=vidply.SoundCloudRenderer-CD7VJKNS.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/renderers/SoundCloudRenderer.js"],
|
|
4
|
+
"sourcesContent": ["/**\r\n * SoundCloud Renderer\r\n * Uses SoundCloud Widget API for embedded track playback\r\n */\r\n\r\nexport class SoundCloudRenderer {\r\n constructor(player) {\r\n this.player = player;\r\n this.widget = null;\r\n this.trackUrl = null;\r\n this.isReady = false;\r\n this.iframe = null;\r\n this.iframeId = null;\r\n }\r\n\r\n async init() {\r\n // Extract track URL - use currentSource which works for external renderers\r\n this.trackUrl = this.player.currentSource || this.player.element.src || this.player.element.querySelector('source')?.src;\r\n \r\n if (!this.trackUrl || !this.isValidSoundCloudUrl(this.trackUrl)) {\r\n throw new Error('Invalid SoundCloud URL');\r\n }\r\n\r\n // Load SoundCloud Widget API\r\n await this.loadSoundCloudAPI();\r\n\r\n // Create iframe\r\n this.createIframe();\r\n\r\n // Initialize widget\r\n await this.initializeWidget();\r\n }\r\n\r\n /**\r\n * Validate SoundCloud URL\r\n * @param {string} url \r\n * @returns {boolean}\r\n */\r\n isValidSoundCloudUrl(url) {\r\n return url.includes('soundcloud.com') || url.includes('api.soundcloud.com');\r\n }\r\n\r\n /**\r\n * Check if URL is a playlist/set\r\n */\r\n isPlaylist() {\r\n return this.trackUrl && this.trackUrl.includes('/sets/');\r\n }\r\n\r\n /**\r\n * Extract track/playlist info from URL for embed\r\n * SoundCloud URLs can be:\r\n * - https://soundcloud.com/artist/track\r\n * - https://soundcloud.com/artist/sets/playlist\r\n * - https://api.soundcloud.com/tracks/123456\r\n */\r\n getEmbedUrl() {\r\n // SoundCloud widget needs the track URL encoded\r\n const encodedUrl = encodeURIComponent(this.trackUrl);\r\n \r\n // Build widget URL with parameters\r\n const params = new URLSearchParams({\r\n url: this.trackUrl,\r\n auto_play: this.player.options.autoplay ? 'true' : 'false',\r\n hide_related: 'true',\r\n show_comments: 'false',\r\n show_user: 'true',\r\n show_reposts: 'false',\r\n show_teaser: 'false',\r\n visual: 'false', // Use classic player for better control\r\n color: '%23007bff'\r\n });\r\n \r\n return `https://w.soundcloud.com/player/?${params.toString()}`;\r\n }\r\n\r\n async loadSoundCloudAPI() {\r\n // Check if API is already loaded\r\n if (window.SC && window.SC.Widget) {\r\n return Promise.resolve();\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n const script = document.createElement('script');\r\n script.src = 'https://w.soundcloud.com/player/api.js';\r\n script.onload = () => {\r\n // Wait a bit for SC.Widget to be fully available\r\n setTimeout(() => {\r\n if (window.SC && window.SC.Widget) {\r\n resolve();\r\n } else {\r\n reject(new Error('SoundCloud Widget API not available'));\r\n }\r\n }, 100);\r\n };\r\n script.onerror = () => reject(new Error('Failed to load SoundCloud Widget API'));\r\n document.head.appendChild(script);\r\n });\r\n }\r\n\r\n createIframe() {\r\n // Hide original element and remove poster (SoundCloud has its own visual widget)\r\n this.player.element.style.display = 'none';\r\n this.player.element.removeAttribute('poster');\r\n \r\n // Remove poster overlay from video wrapper if present\r\n if (this.player.videoWrapper) {\r\n this.player.videoWrapper.classList.remove('vidply-forced-poster');\r\n this.player.videoWrapper.style.removeProperty('--vidply-poster-image');\r\n }\r\n\r\n // Generate unique ID for iframe\r\n this.iframeId = `soundcloud-player-${Math.random().toString(36).substr(2, 9)}`;\r\n\r\n // Create iframe for SoundCloud widget\r\n this.iframe = document.createElement('iframe');\r\n this.iframe.id = this.iframeId;\r\n this.iframe.scrolling = 'no';\r\n this.iframe.frameBorder = 'no';\r\n this.iframe.allow = 'autoplay';\r\n this.iframe.src = this.getEmbedUrl();\r\n this.iframe.style.width = '100%';\r\n this.iframe.style.display = 'block';\r\n \r\n // Use different aspect ratio for playlists vs single tracks\r\n // Playlists need more height to show the track list\r\n if (this.isPlaylist()) {\r\n this.iframe.style.aspectRatio = '16 / 9'; // More height for playlist\r\n this.iframe.classList.add('vidply-soundcloud-iframe', 'vidply-soundcloud-playlist');\r\n } else {\r\n this.iframe.style.aspectRatio = '16 / 3'; // Banner-like for single track\r\n this.iframe.classList.add('vidply-soundcloud-iframe');\r\n }\r\n this.iframe.style.maxHeight = '100%';\r\n \r\n this.player.element.parentNode.insertBefore(this.iframe, this.player.element);\r\n }\r\n\r\n async initializeWidget() {\r\n return new Promise((resolve, reject) => {\r\n // Wait for iframe to load\r\n this.iframe.addEventListener('load', () => {\r\n try {\r\n this.widget = window.SC.Widget(this.iframe);\r\n \r\n this.widget.bind(window.SC.Widget.Events.READY, () => {\r\n this.isReady = true;\r\n this.attachEvents();\r\n \r\n // Hide VidPly controls - SoundCloud has its own\r\n if (this.player.container) {\r\n this.player.container.classList.add('vidply-external-controls');\r\n }\r\n \r\n // Get initial sound info\r\n this.widget.getCurrentSound((sound) => {\r\n if (sound) {\r\n this.player.state.duration = sound.duration / 1000; // Convert ms to seconds\r\n this.player.emit('loadedmetadata');\r\n }\r\n });\r\n \r\n resolve();\r\n });\r\n \r\n this.widget.bind(window.SC.Widget.Events.ERROR, (error) => {\r\n this.player.handleError(new Error(`SoundCloud error: ${error.message || 'Unknown error'}`));\r\n });\r\n } catch (error) {\r\n reject(error);\r\n }\r\n });\r\n \r\n // Timeout after 10 seconds\r\n setTimeout(() => {\r\n if (!this.isReady) {\r\n reject(new Error('SoundCloud widget initialization timeout'));\r\n }\r\n }, 10000);\r\n });\r\n }\r\n\r\n attachEvents() {\r\n if (!this.widget) return;\r\n \r\n const Events = window.SC.Widget.Events;\r\n\r\n this.widget.bind(Events.PLAY, () => {\r\n this.player.state.playing = true;\r\n this.player.state.paused = false;\r\n this.player.state.ended = false;\r\n this.player.emit('play');\r\n \r\n if (this.player.options.onPlay) {\r\n this.player.options.onPlay.call(this.player);\r\n }\r\n });\r\n\r\n this.widget.bind(Events.PAUSE, () => {\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.emit('pause');\r\n \r\n if (this.player.options.onPause) {\r\n this.player.options.onPause.call(this.player);\r\n }\r\n });\r\n\r\n this.widget.bind(Events.FINISH, () => {\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.state.ended = true;\r\n this.player.emit('ended');\r\n \r\n if (this.player.options.onEnded) {\r\n this.player.options.onEnded.call(this.player);\r\n }\r\n \r\n if (this.player.options.loop) {\r\n this.seek(0);\r\n this.play();\r\n }\r\n });\r\n\r\n this.widget.bind(Events.PLAY_PROGRESS, (data) => {\r\n // data.currentPosition is in milliseconds\r\n const currentTime = data.currentPosition / 1000;\r\n this.player.state.currentTime = currentTime;\r\n this.player.emit('timeupdate', currentTime);\r\n \r\n if (this.player.options.onTimeUpdate) {\r\n this.player.options.onTimeUpdate.call(this.player, currentTime);\r\n }\r\n });\r\n\r\n this.widget.bind(Events.SEEK, (data) => {\r\n this.player.state.currentTime = data.currentPosition / 1000;\r\n this.player.emit('seeked');\r\n });\r\n\r\n this.widget.bind(Events.LOAD_PROGRESS, (data) => {\r\n // data.loadedProgress is 0-1\r\n if (this.player.state.duration) {\r\n const buffered = data.loadedProgress * this.player.state.duration;\r\n this.player.emit('progress', buffered);\r\n }\r\n });\r\n }\r\n\r\n play() {\r\n if (this.isReady && this.widget) {\r\n // Save scroll position to prevent browser from scrolling\r\n const scrollX = window.scrollX;\r\n const scrollY = window.scrollY;\r\n \r\n this.widget.play();\r\n \r\n // Restore scroll position\r\n window.scrollTo(scrollX, scrollY);\r\n }\r\n }\r\n\r\n pause() {\r\n if (this.isReady && this.widget) {\r\n this.widget.pause();\r\n }\r\n }\r\n\r\n seek(time) {\r\n if (this.isReady && this.widget) {\r\n // SoundCloud seekTo uses milliseconds\r\n this.widget.seekTo(time * 1000);\r\n this.player.state.currentTime = time;\r\n }\r\n }\r\n\r\n setVolume(volume) {\r\n if (this.isReady && this.widget) {\r\n // SoundCloud setVolume expects 0-100\r\n this.widget.setVolume(volume * 100);\r\n this.player.state.volume = volume;\r\n }\r\n }\r\n\r\n setMuted(muted) {\r\n if (this.isReady && this.widget) {\r\n // SoundCloud doesn't have a native mute, use volume instead\r\n if (muted) {\r\n // Store current volume before muting\r\n this.widget.getVolume((vol) => {\r\n this._previousVolume = vol;\r\n this.widget.setVolume(0);\r\n });\r\n } else {\r\n this.widget.setVolume(this._previousVolume || 100);\r\n }\r\n this.player.state.muted = muted;\r\n }\r\n }\r\n\r\n setPlaybackSpeed(speed) {\r\n // SoundCloud Widget API doesn't support playback speed\r\n this.player.log('SoundCloud does not support playback speed control', 'warn');\r\n }\r\n\r\n /**\r\n * Get current track info\r\n * @returns {Promise<Object>}\r\n */\r\n getCurrentSound() {\r\n return new Promise((resolve) => {\r\n if (this.isReady && this.widget) {\r\n this.widget.getCurrentSound((sound) => {\r\n resolve(sound);\r\n });\r\n } else {\r\n resolve(null);\r\n }\r\n });\r\n }\r\n\r\n destroy() {\r\n // Unbind all events\r\n if (this.widget) {\r\n const Events = window.SC.Widget.Events;\r\n try {\r\n this.widget.unbind(Events.READY);\r\n this.widget.unbind(Events.PLAY);\r\n this.widget.unbind(Events.PAUSE);\r\n this.widget.unbind(Events.FINISH);\r\n this.widget.unbind(Events.PLAY_PROGRESS);\r\n this.widget.unbind(Events.SEEK);\r\n this.widget.unbind(Events.LOAD_PROGRESS);\r\n this.widget.unbind(Events.ERROR);\r\n } catch (e) {\r\n // Ignore unbind errors\r\n }\r\n }\r\n\r\n if (this.iframe && this.iframe.parentNode) {\r\n this.iframe.parentNode.removeChild(this.iframe);\r\n }\r\n\r\n // Show original element\r\n if (this.player.element) {\r\n this.player.element.style.display = '';\r\n }\r\n\r\n this.widget = null;\r\n this.isReady = false;\r\n }\r\n}\r\n\r\nexport default SoundCloudRenderer;\r\n\r\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -14,7 +14,8 @@ var VimeoRenderer = class {
|
|
|
14
14
|
this.iframe = null;
|
|
15
15
|
}
|
|
16
16
|
async init() {
|
|
17
|
-
|
|
17
|
+
const src = this.player.currentSource || this.player.element.src;
|
|
18
|
+
this.videoId = this.extractVideoId(src);
|
|
18
19
|
if (!this.videoId) {
|
|
19
20
|
throw new Error("Invalid Vimeo URL");
|
|
20
21
|
}
|
|
@@ -53,7 +54,8 @@ var VimeoRenderer = class {
|
|
|
53
54
|
this.iframe = document.createElement("div");
|
|
54
55
|
this.iframe.id = `vimeo-player-${Math.random().toString(36).substr(2, 9)}`;
|
|
55
56
|
this.iframe.style.width = "100%";
|
|
56
|
-
this.iframe.style.
|
|
57
|
+
this.iframe.style.aspectRatio = "16 / 9";
|
|
58
|
+
this.iframe.style.maxHeight = "100%";
|
|
57
59
|
this.player.element.parentNode.insertBefore(this.iframe, this.player.element);
|
|
58
60
|
}
|
|
59
61
|
async initializePlayer() {
|
|
@@ -61,7 +63,8 @@ var VimeoRenderer = class {
|
|
|
61
63
|
id: this.videoId,
|
|
62
64
|
width: "100%",
|
|
63
65
|
height: "100%",
|
|
64
|
-
controls:
|
|
66
|
+
controls: true,
|
|
67
|
+
// Use Vimeo native controls
|
|
65
68
|
autoplay: this.player.options.autoplay,
|
|
66
69
|
muted: this.player.options.muted,
|
|
67
70
|
loop: this.player.options.loop,
|
|
@@ -73,6 +76,16 @@ var VimeoRenderer = class {
|
|
|
73
76
|
this.vimeo = new window.Vimeo.Player(this.iframe.id, options);
|
|
74
77
|
await this.vimeo.ready();
|
|
75
78
|
this.isReady = true;
|
|
79
|
+
const vimeoIframe = this.iframe.querySelector("iframe");
|
|
80
|
+
if (vimeoIframe) {
|
|
81
|
+
vimeoIframe.style.width = "100%";
|
|
82
|
+
vimeoIframe.style.height = "100%";
|
|
83
|
+
vimeoIframe.setAttribute("width", "100%");
|
|
84
|
+
vimeoIframe.setAttribute("height", "100%");
|
|
85
|
+
}
|
|
86
|
+
if (this.player.container) {
|
|
87
|
+
this.player.container.classList.add("vidply-external-controls");
|
|
88
|
+
}
|
|
76
89
|
this.attachEvents();
|
|
77
90
|
try {
|
|
78
91
|
const duration = await this.vimeo.getDuration();
|
|
@@ -210,4 +223,4 @@ var VimeoRenderer = class {
|
|
|
210
223
|
export {
|
|
211
224
|
VimeoRenderer
|
|
212
225
|
};
|
|
213
|
-
//# sourceMappingURL=vidply.VimeoRenderer-
|
|
226
|
+
//# sourceMappingURL=vidply.VimeoRenderer-VPH4RNES.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/renderers/VimeoRenderer.js"],
|
|
4
|
+
"sourcesContent": ["/**\r\n * Vimeo Renderer\r\n */\r\n\r\nexport class VimeoRenderer {\r\n constructor(player) {\r\n this.player = player;\r\n this.vimeo = null;\r\n this.videoId = null;\r\n this.isReady = false;\r\n this.iframe = null;\r\n }\r\n\r\n async init() {\r\n // Extract video ID from URL - use currentSource which works for external renderers\r\n const src = this.player.currentSource || this.player.element.src;\r\n this.videoId = this.extractVideoId(src);\r\n \r\n if (!this.videoId) {\r\n throw new Error('Invalid Vimeo URL');\r\n }\r\n\r\n // Load Vimeo Player API\r\n await this.loadVimeoAPI();\r\n\r\n // Create iframe\r\n this.createIframe();\r\n\r\n // Initialize player\r\n await this.initializePlayer();\r\n }\r\n\r\n extractVideoId(url) {\r\n const patterns = [\r\n /vimeo\\.com\\/(\\d+)/,\r\n /vimeo\\.com\\/video\\/(\\d+)/,\r\n /player\\.vimeo\\.com\\/video\\/(\\d+)/\r\n ];\r\n\r\n for (const pattern of patterns) {\r\n const match = url.match(pattern);\r\n if (match && match[1]) {\r\n return match[1];\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n async loadVimeoAPI() {\r\n // Check if API is already loaded\r\n if (window.Vimeo && window.Vimeo.Player) {\r\n return Promise.resolve();\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n const script = document.createElement('script');\r\n script.src = 'https://player.vimeo.com/api/player.js';\r\n script.onload = () => resolve();\r\n script.onerror = () => reject(new Error('Failed to load Vimeo API'));\r\n document.head.appendChild(script);\r\n });\r\n }\r\n\r\n createIframe() {\r\n // Hide original element\r\n this.player.element.style.display = 'none';\r\n\r\n // Create container for iframe\r\n this.iframe = document.createElement('div');\r\n this.iframe.id = `vimeo-player-${Math.random().toString(36).substr(2, 9)}`;\r\n this.iframe.style.width = '100%';\r\n this.iframe.style.aspectRatio = '16 / 9';\r\n this.iframe.style.maxHeight = '100%';\r\n \r\n this.player.element.parentNode.insertBefore(this.iframe, this.player.element);\r\n }\r\n\r\n async initializePlayer() {\r\n const options = {\r\n id: this.videoId,\r\n width: '100%',\r\n height: '100%',\r\n controls: true, // Use Vimeo native controls\r\n autoplay: this.player.options.autoplay,\r\n muted: this.player.options.muted,\r\n loop: this.player.options.loop,\r\n keyboard: false\r\n };\r\n\r\n if (this.player.options.startTime > 0) {\r\n options.startTime = this.player.options.startTime;\r\n }\r\n\r\n this.vimeo = new window.Vimeo.Player(this.iframe.id, options);\r\n\r\n // Wait for player to be ready\r\n await this.vimeo.ready();\r\n this.isReady = true;\r\n \r\n // Ensure the iframe has 100% width and height\r\n const vimeoIframe = this.iframe.querySelector('iframe');\r\n if (vimeoIframe) {\r\n vimeoIframe.style.width = '100%';\r\n vimeoIframe.style.height = '100%';\r\n vimeoIframe.setAttribute('width', '100%');\r\n vimeoIframe.setAttribute('height', '100%');\r\n }\r\n \r\n // Hide VidPly controls - Vimeo has its own\r\n if (this.player.container) {\r\n this.player.container.classList.add('vidply-external-controls');\r\n }\r\n\r\n this.attachEvents();\r\n\r\n // Get initial duration\r\n try {\r\n const duration = await this.vimeo.getDuration();\r\n this.player.state.duration = duration;\r\n this.player.emit('loadedmetadata');\r\n } catch (error) {\r\n this.player.log('Error getting duration:', error, 'warn');\r\n }\r\n }\r\n\r\n attachEvents() {\r\n this.vimeo.on('play', () => {\r\n this.player.state.playing = true;\r\n this.player.state.paused = false;\r\n this.player.state.ended = false;\r\n this.player.emit('play');\r\n \r\n if (this.player.options.onPlay) {\r\n this.player.options.onPlay.call(this.player);\r\n }\r\n });\r\n\r\n this.vimeo.on('pause', () => {\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.emit('pause');\r\n \r\n if (this.player.options.onPause) {\r\n this.player.options.onPause.call(this.player);\r\n }\r\n });\r\n\r\n this.vimeo.on('ended', () => {\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.state.ended = true;\r\n this.player.emit('ended');\r\n \r\n if (this.player.options.onEnded) {\r\n this.player.options.onEnded.call(this.player);\r\n }\r\n });\r\n\r\n this.vimeo.on('timeupdate', (data) => {\r\n this.player.state.currentTime = data.seconds;\r\n this.player.state.duration = data.duration;\r\n this.player.emit('timeupdate', data.seconds);\r\n \r\n if (this.player.options.onTimeUpdate) {\r\n this.player.options.onTimeUpdate.call(this.player, data.seconds);\r\n }\r\n });\r\n\r\n this.vimeo.on('volumechange', (data) => {\r\n this.player.state.volume = data.volume;\r\n this.player.emit('volumechange', data.volume);\r\n });\r\n\r\n this.vimeo.on('bufferstart', () => {\r\n this.player.state.buffering = true;\r\n this.player.emit('waiting');\r\n });\r\n\r\n this.vimeo.on('bufferend', () => {\r\n this.player.state.buffering = false;\r\n this.player.emit('canplay');\r\n });\r\n\r\n this.vimeo.on('seeking', () => {\r\n this.player.state.seeking = true;\r\n this.player.emit('seeking');\r\n });\r\n\r\n this.vimeo.on('seeked', () => {\r\n this.player.state.seeking = false;\r\n this.player.emit('seeked');\r\n });\r\n\r\n this.vimeo.on('playbackratechange', (data) => {\r\n this.player.state.playbackSpeed = data.playbackRate;\r\n this.player.emit('ratechange', data.playbackRate);\r\n });\r\n\r\n this.vimeo.on('error', (error) => {\r\n this.player.handleError(new Error(`Vimeo error: ${error.message}`));\r\n });\r\n }\r\n\r\n play() {\r\n if (this.isReady && this.vimeo) {\r\n // Save scroll position to prevent browser from scrolling to video\r\n const scrollX = window.scrollX;\r\n const scrollY = window.scrollY;\r\n \r\n this.vimeo.play().catch(error => {\r\n this.player.log('Play error:', error, 'warn');\r\n });\r\n \r\n // Restore scroll position immediately to prevent auto-scroll\r\n window.scrollTo(scrollX, scrollY);\r\n }\r\n }\r\n\r\n pause() {\r\n if (this.isReady && this.vimeo) {\r\n this.vimeo.pause().catch(error => {\r\n this.player.log('Pause error:', error, 'warn');\r\n });\r\n }\r\n }\r\n\r\n seek(time) {\r\n if (this.isReady && this.vimeo) {\r\n this.vimeo.setCurrentTime(time).catch(error => {\r\n this.player.log('Seek error:', error, 'warn');\r\n });\r\n }\r\n }\r\n\r\n setVolume(volume) {\r\n if (this.isReady && this.vimeo) {\r\n this.vimeo.setVolume(volume).catch(error => {\r\n this.player.log('Volume error:', error, 'warn');\r\n });\r\n this.player.state.volume = volume;\r\n }\r\n }\r\n\r\n setMuted(muted) {\r\n if (this.isReady && this.vimeo) {\r\n if (muted) {\r\n this.vimeo.setVolume(0);\r\n } else {\r\n this.vimeo.setVolume(this.player.state.volume);\r\n }\r\n this.player.state.muted = muted;\r\n }\r\n }\r\n\r\n setPlaybackSpeed(speed) {\r\n if (this.isReady && this.vimeo) {\r\n this.vimeo.setPlaybackRate(speed).catch(error => {\r\n this.player.log('Playback rate error:', error, 'warn');\r\n });\r\n this.player.state.playbackSpeed = speed;\r\n }\r\n }\r\n\r\n destroy() {\r\n if (this.vimeo && this.vimeo.destroy) {\r\n this.vimeo.destroy();\r\n }\r\n\r\n if (this.iframe && this.iframe.parentNode) {\r\n this.iframe.parentNode.removeChild(this.iframe);\r\n }\r\n\r\n // Show original element\r\n if (this.player.element) {\r\n this.player.element.style.display = '';\r\n }\r\n }\r\n}\r\n\r\n"],
|
|
5
|
+
"mappings": ";;;;;;;AAIO,IAAM,gBAAN,MAAoB;AAAA,EACzB,YAAY,QAAQ;AAClB,SAAK,SAAS;AACd,SAAK,QAAQ;AACb,SAAK,UAAU;AACf,SAAK,UAAU;AACf,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,MAAM,OAAO;AAEX,UAAM,MAAM,KAAK,OAAO,iBAAiB,KAAK,OAAO,QAAQ;AAC7D,SAAK,UAAU,KAAK,eAAe,GAAG;AAEtC,QAAI,CAAC,KAAK,SAAS;AACjB,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACrC;AAGA,UAAM,KAAK,aAAa;AAGxB,SAAK,aAAa;AAGlB,UAAM,KAAK,iBAAiB;AAAA,EAC9B;AAAA,EAEA,eAAe,KAAK;AAClB,UAAM,WAAW;AAAA,MACf;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,eAAW,WAAW,UAAU;AAC9B,YAAM,QAAQ,IAAI,MAAM,OAAO;AAC/B,UAAI,SAAS,MAAM,CAAC,GAAG;AACrB,eAAO,MAAM,CAAC;AAAA,MAChB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,eAAe;AAEnB,QAAI,OAAO,SAAS,OAAO,MAAM,QAAQ;AACvC,aAAO,QAAQ,QAAQ;AAAA,IACzB;AAEA,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,YAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,aAAO,MAAM;AACb,aAAO,SAAS,MAAM,QAAQ;AAC9B,aAAO,UAAU,MAAM,OAAO,IAAI,MAAM,0BAA0B,CAAC;AACnE,eAAS,KAAK,YAAY,MAAM;AAAA,IAClC,CAAC;AAAA,EACH;AAAA,EAEA,eAAe;AAEb,SAAK,OAAO,QAAQ,MAAM,UAAU;AAGpC,SAAK,SAAS,SAAS,cAAc,KAAK;AAC1C,SAAK,OAAO,KAAK,gBAAgB,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,GAAG,CAAC,CAAC;AACxE,SAAK,OAAO,MAAM,QAAQ;AAC1B,SAAK,OAAO,MAAM,cAAc;AAChC,SAAK,OAAO,MAAM,YAAY;AAE9B,SAAK,OAAO,QAAQ,WAAW,aAAa,KAAK,QAAQ,KAAK,OAAO,OAAO;AAAA,EAC9E;AAAA,EAEA,MAAM,mBAAmB;AACvB,UAAM,UAAU;AAAA,MACd,IAAI,KAAK;AAAA,MACT,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,UAAU;AAAA;AAAA,MACV,UAAU,KAAK,OAAO,QAAQ;AAAA,MAC9B,OAAO,KAAK,OAAO,QAAQ;AAAA,MAC3B,MAAM,KAAK,OAAO,QAAQ;AAAA,MAC1B,UAAU;AAAA,IACZ;AAEA,QAAI,KAAK,OAAO,QAAQ,YAAY,GAAG;AACrC,cAAQ,YAAY,KAAK,OAAO,QAAQ;AAAA,IAC1C;AAEA,SAAK,QAAQ,IAAI,OAAO,MAAM,OAAO,KAAK,OAAO,IAAI,OAAO;AAG5D,UAAM,KAAK,MAAM,MAAM;AACvB,SAAK,UAAU;AAGf,UAAM,cAAc,KAAK,OAAO,cAAc,QAAQ;AACtD,QAAI,aAAa;AACf,kBAAY,MAAM,QAAQ;AAC1B,kBAAY,MAAM,SAAS;AAC3B,kBAAY,aAAa,SAAS,MAAM;AACxC,kBAAY,aAAa,UAAU,MAAM;AAAA,IAC3C;AAGA,QAAI,KAAK,OAAO,WAAW;AACzB,WAAK,OAAO,UAAU,UAAU,IAAI,0BAA0B;AAAA,IAChE;AAEA,SAAK,aAAa;AAGlB,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,MAAM,YAAY;AAC9C,WAAK,OAAO,MAAM,WAAW;AAC7B,WAAK,OAAO,KAAK,gBAAgB;AAAA,IACnC,SAAS,OAAO;AACd,WAAK,OAAO,IAAI,2BAA2B,OAAO,MAAM;AAAA,IAC1D;AAAA,EACF;AAAA,EAEA,eAAe;AACb,SAAK,MAAM,GAAG,QAAQ,MAAM;AAC1B,WAAK,OAAO,MAAM,UAAU;AAC5B,WAAK,OAAO,MAAM,SAAS;AAC3B,WAAK,OAAO,MAAM,QAAQ;AAC1B,WAAK,OAAO,KAAK,MAAM;AAEvB,UAAI,KAAK,OAAO,QAAQ,QAAQ;AAC9B,aAAK,OAAO,QAAQ,OAAO,KAAK,KAAK,MAAM;AAAA,MAC7C;AAAA,IACF,CAAC;AAED,SAAK,MAAM,GAAG,SAAS,MAAM;AAC3B,WAAK,OAAO,MAAM,UAAU;AAC5B,WAAK,OAAO,MAAM,SAAS;AAC3B,WAAK,OAAO,KAAK,OAAO;AAExB,UAAI,KAAK,OAAO,QAAQ,SAAS;AAC/B,aAAK,OAAO,QAAQ,QAAQ,KAAK,KAAK,MAAM;AAAA,MAC9C;AAAA,IACF,CAAC;AAED,SAAK,MAAM,GAAG,SAAS,MAAM;AAC3B,WAAK,OAAO,MAAM,UAAU;AAC5B,WAAK,OAAO,MAAM,SAAS;AAC3B,WAAK,OAAO,MAAM,QAAQ;AAC1B,WAAK,OAAO,KAAK,OAAO;AAExB,UAAI,KAAK,OAAO,QAAQ,SAAS;AAC/B,aAAK,OAAO,QAAQ,QAAQ,KAAK,KAAK,MAAM;AAAA,MAC9C;AAAA,IACF,CAAC;AAED,SAAK,MAAM,GAAG,cAAc,CAAC,SAAS;AACpC,WAAK,OAAO,MAAM,cAAc,KAAK;AACrC,WAAK,OAAO,MAAM,WAAW,KAAK;AAClC,WAAK,OAAO,KAAK,cAAc,KAAK,OAAO;AAE3C,UAAI,KAAK,OAAO,QAAQ,cAAc;AACpC,aAAK,OAAO,QAAQ,aAAa,KAAK,KAAK,QAAQ,KAAK,OAAO;AAAA,MACjE;AAAA,IACF,CAAC;AAED,SAAK,MAAM,GAAG,gBAAgB,CAAC,SAAS;AACtC,WAAK,OAAO,MAAM,SAAS,KAAK;AAChC,WAAK,OAAO,KAAK,gBAAgB,KAAK,MAAM;AAAA,IAC9C,CAAC;AAED,SAAK,MAAM,GAAG,eAAe,MAAM;AACjC,WAAK,OAAO,MAAM,YAAY;AAC9B,WAAK,OAAO,KAAK,SAAS;AAAA,IAC5B,CAAC;AAED,SAAK,MAAM,GAAG,aAAa,MAAM;AAC/B,WAAK,OAAO,MAAM,YAAY;AAC9B,WAAK,OAAO,KAAK,SAAS;AAAA,IAC5B,CAAC;AAED,SAAK,MAAM,GAAG,WAAW,MAAM;AAC7B,WAAK,OAAO,MAAM,UAAU;AAC5B,WAAK,OAAO,KAAK,SAAS;AAAA,IAC5B,CAAC;AAED,SAAK,MAAM,GAAG,UAAU,MAAM;AAC5B,WAAK,OAAO,MAAM,UAAU;AAC5B,WAAK,OAAO,KAAK,QAAQ;AAAA,IAC3B,CAAC;AAED,SAAK,MAAM,GAAG,sBAAsB,CAAC,SAAS;AAC5C,WAAK,OAAO,MAAM,gBAAgB,KAAK;AACvC,WAAK,OAAO,KAAK,cAAc,KAAK,YAAY;AAAA,IAClD,CAAC;AAED,SAAK,MAAM,GAAG,SAAS,CAAC,UAAU;AAChC,WAAK,OAAO,YAAY,IAAI,MAAM,gBAAgB,MAAM,OAAO,EAAE,CAAC;AAAA,IACpE,CAAC;AAAA,EACH;AAAA,EAEA,OAAO;AACL,QAAI,KAAK,WAAW,KAAK,OAAO;AAE9B,YAAM,UAAU,OAAO;AACvB,YAAM,UAAU,OAAO;AAEvB,WAAK,MAAM,KAAK,EAAE,MAAM,WAAS;AAC/B,aAAK,OAAO,IAAI,eAAe,OAAO,MAAM;AAAA,MAC9C,CAAC;AAGD,aAAO,SAAS,SAAS,OAAO;AAAA,IAClC;AAAA,EACF;AAAA,EAEA,QAAQ;AACN,QAAI,KAAK,WAAW,KAAK,OAAO;AAC9B,WAAK,MAAM,MAAM,EAAE,MAAM,WAAS;AAChC,aAAK,OAAO,IAAI,gBAAgB,OAAO,MAAM;AAAA,MAC/C,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,KAAK,MAAM;AACT,QAAI,KAAK,WAAW,KAAK,OAAO;AAC9B,WAAK,MAAM,eAAe,IAAI,EAAE,MAAM,WAAS;AAC7C,aAAK,OAAO,IAAI,eAAe,OAAO,MAAM;AAAA,MAC9C,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,UAAU,QAAQ;AAChB,QAAI,KAAK,WAAW,KAAK,OAAO;AAC9B,WAAK,MAAM,UAAU,MAAM,EAAE,MAAM,WAAS;AAC1C,aAAK,OAAO,IAAI,iBAAiB,OAAO,MAAM;AAAA,MAChD,CAAC;AACD,WAAK,OAAO,MAAM,SAAS;AAAA,IAC7B;AAAA,EACF;AAAA,EAEA,SAAS,OAAO;AACd,QAAI,KAAK,WAAW,KAAK,OAAO;AAC9B,UAAI,OAAO;AACT,aAAK,MAAM,UAAU,CAAC;AAAA,MACxB,OAAO;AACL,aAAK,MAAM,UAAU,KAAK,OAAO,MAAM,MAAM;AAAA,MAC/C;AACA,WAAK,OAAO,MAAM,QAAQ;AAAA,IAC5B;AAAA,EACF;AAAA,EAEA,iBAAiB,OAAO;AACtB,QAAI,KAAK,WAAW,KAAK,OAAO;AAC9B,WAAK,MAAM,gBAAgB,KAAK,EAAE,MAAM,WAAS;AAC/C,aAAK,OAAO,IAAI,wBAAwB,OAAO,MAAM;AAAA,MACvD,CAAC;AACD,WAAK,OAAO,MAAM,gBAAgB;AAAA,IACpC;AAAA,EACF;AAAA,EAEA,UAAU;AACR,QAAI,KAAK,SAAS,KAAK,MAAM,SAAS;AACpC,WAAK,MAAM,QAAQ;AAAA,IACrB;AAEA,QAAI,KAAK,UAAU,KAAK,OAAO,YAAY;AACzC,WAAK,OAAO,WAAW,YAAY,KAAK,MAAM;AAAA,IAChD;AAGA,QAAI,KAAK,OAAO,SAAS;AACvB,WAAK,OAAO,QAAQ,MAAM,UAAU;AAAA,IACtC;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -14,7 +14,8 @@ var YouTubeRenderer = class {
|
|
|
14
14
|
this.iframe = null;
|
|
15
15
|
}
|
|
16
16
|
async init() {
|
|
17
|
-
|
|
17
|
+
const src = this.player.currentSource || this.player.element.src;
|
|
18
|
+
this.videoId = this.extractVideoId(src);
|
|
18
19
|
if (!this.videoId) {
|
|
19
20
|
throw new Error("Invalid YouTube URL");
|
|
20
21
|
}
|
|
@@ -63,7 +64,8 @@ var YouTubeRenderer = class {
|
|
|
63
64
|
this.iframe = document.createElement("div");
|
|
64
65
|
this.iframe.id = `youtube-player-${Math.random().toString(36).substr(2, 9)}`;
|
|
65
66
|
this.iframe.style.width = "100%";
|
|
66
|
-
this.iframe.style.
|
|
67
|
+
this.iframe.style.aspectRatio = "16 / 9";
|
|
68
|
+
this.iframe.style.maxHeight = "100%";
|
|
67
69
|
this.player.element.parentNode.insertBefore(this.iframe, this.player.element);
|
|
68
70
|
}
|
|
69
71
|
async initializePlayer() {
|
|
@@ -73,9 +75,12 @@ var YouTubeRenderer = class {
|
|
|
73
75
|
width: "100%",
|
|
74
76
|
height: "100%",
|
|
75
77
|
playerVars: {
|
|
76
|
-
controls:
|
|
77
|
-
|
|
78
|
-
|
|
78
|
+
controls: 1,
|
|
79
|
+
// Use YouTube native controls
|
|
80
|
+
disablekb: 0,
|
|
81
|
+
// Allow keyboard controls
|
|
82
|
+
fs: 1,
|
|
83
|
+
// Allow fullscreen
|
|
79
84
|
modestbranding: 1,
|
|
80
85
|
rel: 0,
|
|
81
86
|
showinfo: 0,
|
|
@@ -88,6 +93,9 @@ var YouTubeRenderer = class {
|
|
|
88
93
|
onReady: (event) => {
|
|
89
94
|
this.isReady = true;
|
|
90
95
|
this.attachEvents();
|
|
96
|
+
if (this.player.container) {
|
|
97
|
+
this.player.container.classList.add("vidply-external-controls");
|
|
98
|
+
}
|
|
91
99
|
resolve();
|
|
92
100
|
},
|
|
93
101
|
onStateChange: (event) => this.handleStateChange(event),
|
|
@@ -224,4 +232,4 @@ var YouTubeRenderer = class {
|
|
|
224
232
|
export {
|
|
225
233
|
YouTubeRenderer
|
|
226
234
|
};
|
|
227
|
-
//# sourceMappingURL=vidply.YouTubeRenderer-
|
|
235
|
+
//# sourceMappingURL=vidply.YouTubeRenderer-6MGKEFTZ.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/renderers/YouTubeRenderer.js"],
|
|
4
|
+
"sourcesContent": ["/**\r\n * YouTube Renderer\r\n */\r\n\r\nexport class YouTubeRenderer {\r\n constructor(player) {\r\n this.player = player;\r\n this.youtube = null;\r\n this.videoId = null;\r\n this.isReady = false;\r\n this.iframe = null;\r\n }\r\n\r\n async init() {\r\n // Extract video ID from URL - use currentSource which works for external renderers\r\n const src = this.player.currentSource || this.player.element.src;\r\n this.videoId = this.extractVideoId(src);\r\n \r\n if (!this.videoId) {\r\n throw new Error('Invalid YouTube URL');\r\n }\r\n\r\n // Load YouTube IFrame API\r\n await this.loadYouTubeAPI();\r\n\r\n // Create iframe\r\n this.createIframe();\r\n\r\n // Initialize player\r\n await this.initializePlayer();\r\n }\r\n\r\n extractVideoId(url) {\r\n const patterns = [\r\n /(?:youtube\\.com\\/watch\\?v=|youtu\\.be\\/)([^&\\s]+)/,\r\n /youtube\\.com\\/embed\\/([^&\\s]+)/\r\n ];\r\n\r\n for (const pattern of patterns) {\r\n const match = url.match(pattern);\r\n if (match && match[1]) {\r\n return match[1];\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n async loadYouTubeAPI() {\r\n // Check if API is already loaded\r\n if (window.YT && window.YT.Player) {\r\n return Promise.resolve();\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n // Check if script is already being loaded\r\n if (window.onYouTubeIframeAPIReady) {\r\n const originalCallback = window.onYouTubeIframeAPIReady;\r\n window.onYouTubeIframeAPIReady = () => {\r\n originalCallback();\r\n resolve();\r\n };\r\n return;\r\n }\r\n\r\n // Load the API script\r\n const tag = document.createElement('script');\r\n tag.src = 'https://www.youtube.com/iframe_api';\r\n \r\n window.onYouTubeIframeAPIReady = () => {\r\n resolve();\r\n };\r\n\r\n tag.onerror = () => reject(new Error('Failed to load YouTube API'));\r\n \r\n const firstScriptTag = document.getElementsByTagName('script')[0];\r\n firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\r\n });\r\n }\r\n\r\n createIframe() {\r\n // Hide original element\r\n this.player.element.style.display = 'none';\r\n\r\n // Create container for iframe\r\n this.iframe = document.createElement('div');\r\n this.iframe.id = `youtube-player-${Math.random().toString(36).substr(2, 9)}`;\r\n this.iframe.style.width = '100%';\r\n this.iframe.style.aspectRatio = '16 / 9';\r\n this.iframe.style.maxHeight = '100%';\r\n \r\n this.player.element.parentNode.insertBefore(this.iframe, this.player.element);\r\n }\r\n\r\n async initializePlayer() {\r\n return new Promise((resolve) => {\r\n this.youtube = new window.YT.Player(this.iframe.id, {\r\n videoId: this.videoId,\r\n width: '100%',\r\n height: '100%',\r\n playerVars: {\r\n controls: 1, // Use YouTube native controls\r\n disablekb: 0, // Allow keyboard controls\r\n fs: 1, // Allow fullscreen\r\n modestbranding: 1,\r\n rel: 0,\r\n showinfo: 0,\r\n iv_load_policy: 3,\r\n autoplay: this.player.options.autoplay ? 1 : 0,\r\n mute: this.player.options.muted ? 1 : 0,\r\n start: this.player.options.startTime || 0\r\n },\r\n events: {\r\n onReady: (event) => {\r\n this.isReady = true;\r\n this.attachEvents();\r\n // Hide VidPly controls - YouTube has its own\r\n if (this.player.container) {\r\n this.player.container.classList.add('vidply-external-controls');\r\n }\r\n resolve();\r\n },\r\n onStateChange: (event) => this.handleStateChange(event),\r\n onError: (event) => this.handleError(event)\r\n }\r\n });\r\n });\r\n }\r\n\r\n attachEvents() {\r\n // Set up polling for time updates (YouTube doesn't provide timeupdate events)\r\n this.timeUpdateInterval = setInterval(() => {\r\n if (this.isReady && this.youtube) {\r\n const currentTime = this.youtube.getCurrentTime();\r\n const duration = this.youtube.getDuration();\r\n \r\n this.player.state.currentTime = currentTime;\r\n this.player.state.duration = duration;\r\n \r\n this.player.emit('timeupdate', currentTime);\r\n }\r\n }, 250);\r\n\r\n // Initial metadata\r\n if (this.youtube.getDuration) {\r\n this.player.state.duration = this.youtube.getDuration();\r\n this.player.emit('loadedmetadata');\r\n }\r\n }\r\n\r\n handleStateChange(event) {\r\n const states = window.YT.PlayerState;\r\n\r\n switch (event.data) {\r\n case states.PLAYING:\r\n this.player.state.playing = true;\r\n this.player.state.paused = false;\r\n this.player.state.ended = false;\r\n this.player.state.buffering = false;\r\n this.player.emit('play');\r\n this.player.emit('playing');\r\n \r\n if (this.player.options.onPlay) {\r\n this.player.options.onPlay.call(this.player);\r\n }\r\n break;\r\n\r\n case states.PAUSED:\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.emit('pause');\r\n \r\n if (this.player.options.onPause) {\r\n this.player.options.onPause.call(this.player);\r\n }\r\n break;\r\n\r\n case states.ENDED:\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.state.ended = true;\r\n this.player.emit('ended');\r\n \r\n if (this.player.options.onEnded) {\r\n this.player.options.onEnded.call(this.player);\r\n }\r\n \r\n if (this.player.options.loop) {\r\n this.youtube.seekTo(0);\r\n this.youtube.playVideo();\r\n }\r\n break;\r\n\r\n case states.BUFFERING:\r\n this.player.state.buffering = true;\r\n this.player.emit('waiting');\r\n break;\r\n\r\n case states.CUED:\r\n this.player.emit('loadedmetadata');\r\n break;\r\n }\r\n }\r\n\r\n handleError(event) {\r\n const errors = {\r\n 2: 'Invalid video ID',\r\n 5: 'HTML5 player error',\r\n 100: 'Video not found',\r\n 101: 'Video not allowed to be played in embedded players',\r\n 150: 'Video not allowed to be played in embedded players'\r\n };\r\n\r\n const error = new Error(errors[event.data] || 'YouTube player error');\r\n this.player.handleError(error);\r\n }\r\n\r\n play() {\r\n if (this.isReady && this.youtube) {\r\n // Save scroll position to prevent browser from scrolling to video\r\n const scrollX = window.scrollX;\r\n const scrollY = window.scrollY;\r\n \r\n this.youtube.playVideo();\r\n \r\n // Restore scroll position immediately to prevent auto-scroll\r\n window.scrollTo(scrollX, scrollY);\r\n }\r\n }\r\n\r\n pause() {\r\n if (this.isReady && this.youtube) {\r\n this.youtube.pauseVideo();\r\n }\r\n }\r\n\r\n seek(time) {\r\n if (this.isReady && this.youtube) {\r\n this.youtube.seekTo(time, true);\r\n }\r\n }\r\n\r\n setVolume(volume) {\r\n if (this.isReady && this.youtube) {\r\n this.youtube.setVolume(volume * 100);\r\n this.player.state.volume = volume;\r\n }\r\n }\r\n\r\n setMuted(muted) {\r\n if (this.isReady && this.youtube) {\r\n if (muted) {\r\n this.youtube.mute();\r\n } else {\r\n this.youtube.unMute();\r\n }\r\n this.player.state.muted = muted;\r\n }\r\n }\r\n\r\n setPlaybackSpeed(speed) {\r\n if (this.isReady && this.youtube) {\r\n this.youtube.setPlaybackRate(speed);\r\n this.player.state.playbackSpeed = speed;\r\n }\r\n }\r\n\r\n destroy() {\r\n if (this.timeUpdateInterval) {\r\n clearInterval(this.timeUpdateInterval);\r\n }\r\n\r\n if (this.youtube && this.youtube.destroy) {\r\n this.youtube.destroy();\r\n }\r\n\r\n if (this.iframe && this.iframe.parentNode) {\r\n this.iframe.parentNode.removeChild(this.iframe);\r\n }\r\n\r\n // Show original element\r\n if (this.player.element) {\r\n this.player.element.style.display = '';\r\n }\r\n }\r\n}\r\n\r\n"],
|
|
5
|
+
"mappings": ";;;;;;;AAIO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YAAY,QAAQ;AAClB,SAAK,SAAS;AACd,SAAK,UAAU;AACf,SAAK,UAAU;AACf,SAAK,UAAU;AACf,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,MAAM,OAAO;AAEX,UAAM,MAAM,KAAK,OAAO,iBAAiB,KAAK,OAAO,QAAQ;AAC7D,SAAK,UAAU,KAAK,eAAe,GAAG;AAEtC,QAAI,CAAC,KAAK,SAAS;AACjB,YAAM,IAAI,MAAM,qBAAqB;AAAA,IACvC;AAGA,UAAM,KAAK,eAAe;AAG1B,SAAK,aAAa;AAGlB,UAAM,KAAK,iBAAiB;AAAA,EAC9B;AAAA,EAEA,eAAe,KAAK;AAClB,UAAM,WAAW;AAAA,MACf;AAAA,MACA;AAAA,IACF;AAEA,eAAW,WAAW,UAAU;AAC9B,YAAM,QAAQ,IAAI,MAAM,OAAO;AAC/B,UAAI,SAAS,MAAM,CAAC,GAAG;AACrB,eAAO,MAAM,CAAC;AAAA,MAChB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,iBAAiB;AAErB,QAAI,OAAO,MAAM,OAAO,GAAG,QAAQ;AACjC,aAAO,QAAQ,QAAQ;AAAA,IACzB;AAEA,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AAEtC,UAAI,OAAO,yBAAyB;AAClC,cAAM,mBAAmB,OAAO;AAChC,eAAO,0BAA0B,MAAM;AACrC,2BAAiB;AACjB,kBAAQ;AAAA,QACV;AACA;AAAA,MACF;AAGA,YAAM,MAAM,SAAS,cAAc,QAAQ;AAC3C,UAAI,MAAM;AAEV,aAAO,0BAA0B,MAAM;AACrC,gBAAQ;AAAA,MACV;AAEA,UAAI,UAAU,MAAM,OAAO,IAAI,MAAM,4BAA4B,CAAC;AAElE,YAAM,iBAAiB,SAAS,qBAAqB,QAAQ,EAAE,CAAC;AAChE,qBAAe,WAAW,aAAa,KAAK,cAAc;AAAA,IAC5D,CAAC;AAAA,EACH;AAAA,EAEA,eAAe;AAEb,SAAK,OAAO,QAAQ,MAAM,UAAU;AAGpC,SAAK,SAAS,SAAS,cAAc,KAAK;AAC1C,SAAK,OAAO,KAAK,kBAAkB,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,GAAG,CAAC,CAAC;AAC1E,SAAK,OAAO,MAAM,QAAQ;AAC1B,SAAK,OAAO,MAAM,cAAc;AAChC,SAAK,OAAO,MAAM,YAAY;AAE9B,SAAK,OAAO,QAAQ,WAAW,aAAa,KAAK,QAAQ,KAAK,OAAO,OAAO;AAAA,EAC9E;AAAA,EAEA,MAAM,mBAAmB;AACvB,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,WAAK,UAAU,IAAI,OAAO,GAAG,OAAO,KAAK,OAAO,IAAI;AAAA,QAClD,SAAS,KAAK;AAAA,QACd,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,YAAY;AAAA,UACV,UAAU;AAAA;AAAA,UACV,WAAW;AAAA;AAAA,UACX,IAAI;AAAA;AAAA,UACJ,gBAAgB;AAAA,UAChB,KAAK;AAAA,UACL,UAAU;AAAA,UACV,gBAAgB;AAAA,UAChB,UAAU,KAAK,OAAO,QAAQ,WAAW,IAAI;AAAA,UAC7C,MAAM,KAAK,OAAO,QAAQ,QAAQ,IAAI;AAAA,UACtC,OAAO,KAAK,OAAO,QAAQ,aAAa;AAAA,QAC1C;AAAA,QACA,QAAQ;AAAA,UACN,SAAS,CAAC,UAAU;AAClB,iBAAK,UAAU;AACf,iBAAK,aAAa;AAElB,gBAAI,KAAK,OAAO,WAAW;AACzB,mBAAK,OAAO,UAAU,UAAU,IAAI,0BAA0B;AAAA,YAChE;AACA,oBAAQ;AAAA,UACV;AAAA,UACA,eAAe,CAAC,UAAU,KAAK,kBAAkB,KAAK;AAAA,UACtD,SAAS,CAAC,UAAU,KAAK,YAAY,KAAK;AAAA,QAC5C;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EAEA,eAAe;AAEb,SAAK,qBAAqB,YAAY,MAAM;AAC1C,UAAI,KAAK,WAAW,KAAK,SAAS;AAChC,cAAM,cAAc,KAAK,QAAQ,eAAe;AAChD,cAAM,WAAW,KAAK,QAAQ,YAAY;AAE1C,aAAK,OAAO,MAAM,cAAc;AAChC,aAAK,OAAO,MAAM,WAAW;AAE7B,aAAK,OAAO,KAAK,cAAc,WAAW;AAAA,MAC5C;AAAA,IACF,GAAG,GAAG;AAGN,QAAI,KAAK,QAAQ,aAAa;AAC5B,WAAK,OAAO,MAAM,WAAW,KAAK,QAAQ,YAAY;AACtD,WAAK,OAAO,KAAK,gBAAgB;AAAA,IACnC;AAAA,EACF;AAAA,EAEA,kBAAkB,OAAO;AACvB,UAAM,SAAS,OAAO,GAAG;AAEzB,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK,OAAO;AACV,aAAK,OAAO,MAAM,UAAU;AAC5B,aAAK,OAAO,MAAM,SAAS;AAC3B,aAAK,OAAO,MAAM,QAAQ;AAC1B,aAAK,OAAO,MAAM,YAAY;AAC9B,aAAK,OAAO,KAAK,MAAM;AACvB,aAAK,OAAO,KAAK,SAAS;AAE1B,YAAI,KAAK,OAAO,QAAQ,QAAQ;AAC9B,eAAK,OAAO,QAAQ,OAAO,KAAK,KAAK,MAAM;AAAA,QAC7C;AACA;AAAA,MAEF,KAAK,OAAO;AACV,aAAK,OAAO,MAAM,UAAU;AAC5B,aAAK,OAAO,MAAM,SAAS;AAC3B,aAAK,OAAO,KAAK,OAAO;AAExB,YAAI,KAAK,OAAO,QAAQ,SAAS;AAC/B,eAAK,OAAO,QAAQ,QAAQ,KAAK,KAAK,MAAM;AAAA,QAC9C;AACA;AAAA,MAEF,KAAK,OAAO;AACV,aAAK,OAAO,MAAM,UAAU;AAC5B,aAAK,OAAO,MAAM,SAAS;AAC3B,aAAK,OAAO,MAAM,QAAQ;AAC1B,aAAK,OAAO,KAAK,OAAO;AAExB,YAAI,KAAK,OAAO,QAAQ,SAAS;AAC/B,eAAK,OAAO,QAAQ,QAAQ,KAAK,KAAK,MAAM;AAAA,QAC9C;AAEA,YAAI,KAAK,OAAO,QAAQ,MAAM;AAC5B,eAAK,QAAQ,OAAO,CAAC;AACrB,eAAK,QAAQ,UAAU;AAAA,QACzB;AACA;AAAA,MAEF,KAAK,OAAO;AACV,aAAK,OAAO,MAAM,YAAY;AAC9B,aAAK,OAAO,KAAK,SAAS;AAC1B;AAAA,MAEF,KAAK,OAAO;AACV,aAAK,OAAO,KAAK,gBAAgB;AACjC;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,YAAY,OAAO;AACjB,UAAM,SAAS;AAAA,MACb,GAAG;AAAA,MACH,GAAG;AAAA,MACH,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAEA,UAAM,QAAQ,IAAI,MAAM,OAAO,MAAM,IAAI,KAAK,sBAAsB;AACpE,SAAK,OAAO,YAAY,KAAK;AAAA,EAC/B;AAAA,EAEA,OAAO;AACL,QAAI,KAAK,WAAW,KAAK,SAAS;AAEhC,YAAM,UAAU,OAAO;AACvB,YAAM,UAAU,OAAO;AAEvB,WAAK,QAAQ,UAAU;AAGvB,aAAO,SAAS,SAAS,OAAO;AAAA,IAClC;AAAA,EACF;AAAA,EAEA,QAAQ;AACN,QAAI,KAAK,WAAW,KAAK,SAAS;AAChC,WAAK,QAAQ,WAAW;AAAA,IAC1B;AAAA,EACF;AAAA,EAEA,KAAK,MAAM;AACT,QAAI,KAAK,WAAW,KAAK,SAAS;AAChC,WAAK,QAAQ,OAAO,MAAM,IAAI;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,UAAU,QAAQ;AAChB,QAAI,KAAK,WAAW,KAAK,SAAS;AAChC,WAAK,QAAQ,UAAU,SAAS,GAAG;AACnC,WAAK,OAAO,MAAM,SAAS;AAAA,IAC7B;AAAA,EACF;AAAA,EAEA,SAAS,OAAO;AACd,QAAI,KAAK,WAAW,KAAK,SAAS;AAChC,UAAI,OAAO;AACT,aAAK,QAAQ,KAAK;AAAA,MACpB,OAAO;AACL,aAAK,QAAQ,OAAO;AAAA,MACtB;AACA,WAAK,OAAO,MAAM,QAAQ;AAAA,IAC5B;AAAA,EACF;AAAA,EAEA,iBAAiB,OAAO;AACtB,QAAI,KAAK,WAAW,KAAK,SAAS;AAChC,WAAK,QAAQ,gBAAgB,KAAK;AAClC,WAAK,OAAO,MAAM,gBAAgB;AAAA,IACpC;AAAA,EACF;AAAA,EAEA,UAAU;AACR,QAAI,KAAK,oBAAoB;AAC3B,oBAAc,KAAK,kBAAkB;AAAA,IACvC;AAEA,QAAI,KAAK,WAAW,KAAK,QAAQ,SAAS;AACxC,WAAK,QAAQ,QAAQ;AAAA,IACvB;AAEA,QAAI,KAAK,UAAU,KAAK,OAAO,YAAY;AACzC,WAAK,OAAO,WAAW,YAAY,KAAK,MAAM;AAAA,IAChD;AAGA,QAAI,KAAK,OAAO,SAAS;AACvB,WAAK,OAAO,QAAQ,MAAM,UAAU;AAAA,IACtC;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -16,6 +16,9 @@ var HTML5Renderer = class {
|
|
|
16
16
|
this.attachEvents();
|
|
17
17
|
this.media.preload = this.player.options.preload;
|
|
18
18
|
this.media.load();
|
|
19
|
+
if (this.player.container) {
|
|
20
|
+
this.player.container.classList.remove("vidply-external-controls");
|
|
21
|
+
}
|
|
19
22
|
}
|
|
20
23
|
attachEvents() {
|
|
21
24
|
this.media.addEventListener("loadedmetadata", () => {
|
|
@@ -240,4 +243,4 @@ var HTML5Renderer = class {
|
|
|
240
243
|
export {
|
|
241
244
|
HTML5Renderer
|
|
242
245
|
};
|
|
243
|
-
//# sourceMappingURL=vidply.chunk-
|
|
246
|
+
//# sourceMappingURL=vidply.chunk-BCOFCT6U.js.map
|