vidply 1.0.25 → 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/README.md +5 -0
- package/dist/dev/{vidply.HLSRenderer-PNP5OPES.js → vidply.HLSRenderer-ENLZE4QS.js} +19 -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 +292 -13
- package/dist/dev/vidply.esm.js.map +2 -2
- package/dist/legacy/vidply.js +619 -24
- 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 +52 -1
- package/dist/vidply.esm.min.meta.json +56 -28
- package/dist/vidply.min.css +2 -2
- package/package.json +1 -1
- package/src/core/Player.js +124 -10
- 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-PNP5OPES.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-4PW35TCX.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
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/renderers/HTML5Renderer.js"],
|
|
4
|
+
"sourcesContent": ["/**\r\n * HTML5 Media Renderer\r\n */\r\n\r\nexport class HTML5Renderer {\r\n constructor(player) {\r\n this.player = player;\r\n this.media = player.element;\r\n }\r\n\r\n async init() {\r\n // Hide native controls\r\n this.media.controls = false;\r\n this.media.removeAttribute('controls');\r\n \r\n this.attachEvents();\r\n \r\n // Set preload\r\n this.media.preload = this.player.options.preload;\r\n \r\n // Load media\r\n this.media.load();\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 attachEvents() {\r\n // Playback events\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 // Pause other players if enabled\r\n if (this.player.options.pauseOthersOnPlay) {\r\n this.pauseOtherPlayers();\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 // Handle loop\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 if (this.player.options.onVolumeChange) {\r\n this.player.options.onVolumeChange.call(this.player, this.media.volume);\r\n }\r\n });\r\n\r\n this.media.addEventListener('seeking', () => {\r\n this.player.state.seeking = true;\r\n this.player.emit('seeking');\r\n });\r\n\r\n this.media.addEventListener('seeked', () => {\r\n this.player.state.seeking = false;\r\n this.player.emit('seeked');\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('progress', () => {\r\n if (this.media.buffered.length > 0) {\r\n const buffered = this.media.buffered.end(this.media.buffered.length - 1);\r\n this.player.emit('progress', buffered);\r\n }\r\n });\r\n\r\n this.media.addEventListener('error', (e) => {\r\n this.player.handleError(this.media.error);\r\n });\r\n\r\n this.media.addEventListener('ratechange', () => {\r\n this.player.state.playbackSpeed = this.media.playbackRate;\r\n this.player.emit('ratechange', this.media.playbackRate);\r\n });\r\n }\r\n\r\n pauseOtherPlayers() {\r\n // Pause other VidPly instances\r\n const allPlayers = document.querySelectorAll('.vidply-player');\r\n allPlayers.forEach(playerEl => {\r\n if (playerEl !== this.player.container) {\r\n const video = playerEl.querySelector('video, audio');\r\n if (video && !video.paused) {\r\n video.pause();\r\n }\r\n }\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 // If autoplay failed, try muted autoplay\r\n if (this.player.options.autoplay && !this.player.state.muted) {\r\n this.player.log('Retrying play with muted audio', 'info');\r\n this.media.muted = true;\r\n \r\n // Save scroll position again for retry\r\n const retryScrollX = window.scrollX;\r\n const retryScrollY = window.scrollY;\r\n this.media.play().then(() => {\r\n window.scrollTo(retryScrollX, retryScrollY);\r\n }).catch(err => {\r\n this.player.handleError(err);\r\n });\r\n }\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 /**\r\n * Get available quality levels from source elements\r\n * @returns {Array} Array of quality objects with index, height, width, and src\r\n */\r\n getQualities() {\r\n const sources = Array.from(this.media.querySelectorAll('source'));\r\n \r\n if (sources.length <= 1) {\r\n return [];\r\n }\r\n\r\n return sources.map((source, index) => {\r\n // Try to extract quality from data attributes or label\r\n const label = source.getAttribute('data-quality') || source.getAttribute('label') || '';\r\n const height = source.getAttribute('data-height') || this.extractHeightFromLabel(label);\r\n const width = source.getAttribute('data-width') || '';\r\n \r\n return {\r\n index,\r\n height: height ? parseInt(height) : 0,\r\n width: width ? parseInt(width) : 0,\r\n src: source.src,\r\n type: source.type,\r\n name: label || (height ? `${height}p` : `Quality ${index + 1}`)\r\n };\r\n }).filter(q => q.height > 0); // Only return qualities with valid height\r\n }\r\n\r\n /**\r\n * Extract height from quality label (e.g., \"1080p\" -> 1080)\r\n * @param {string} label \r\n * @returns {number}\r\n */\r\n extractHeightFromLabel(label) {\r\n const match = label.match(/(\\d+)p/i);\r\n return match ? parseInt(match[1]) : 0;\r\n }\r\n\r\n /**\r\n * Switch to a specific quality level\r\n * @param {number} qualityIndex - Index of the quality level (-1 for auto, not applicable for HTML5)\r\n */\r\n switchQuality(qualityIndex) {\r\n const qualities = this.getQualities();\r\n \r\n if (qualityIndex < 0 || qualityIndex >= qualities.length) {\r\n this.player.log('Invalid quality index', 'warn');\r\n return;\r\n }\r\n\r\n const quality = qualities[qualityIndex];\r\n const currentTime = this.media.currentTime;\r\n const wasPlaying = !this.media.paused;\r\n\r\n // Store the current source for comparison\r\n const currentSrc = this.media.currentSrc;\r\n \r\n // Don't switch if already at this quality\r\n if (currentSrc === quality.src) {\r\n this.player.log('Already at this quality level', 'info');\r\n return;\r\n }\r\n\r\n this.player.log(`Switching to quality: ${quality.name}`, 'info');\r\n\r\n // Update the src\r\n this.media.src = quality.src;\r\n \r\n // Wait for the new source to load, then restore playback state\r\n const onLoadedMetadata = () => {\r\n this.media.removeEventListener('loadedmetadata', onLoadedMetadata);\r\n \r\n // Restore playback position\r\n this.media.currentTime = currentTime;\r\n \r\n // Resume playback if it was playing\r\n if (wasPlaying) {\r\n this.media.play().catch(err => {\r\n this.player.log('Failed to resume playback after quality switch', 'warn');\r\n });\r\n }\r\n \r\n // Emit quality change event\r\n this.player.emit('qualitychange', { quality: quality.name, index: qualityIndex });\r\n };\r\n\r\n this.media.addEventListener('loadedmetadata', onLoadedMetadata);\r\n this.media.load();\r\n }\r\n\r\n /**\r\n * Get current quality index\r\n * @returns {number}\r\n */\r\n getCurrentQuality() {\r\n const qualities = this.getQualities();\r\n const currentSrc = this.media.currentSrc;\r\n \r\n for (let i = 0; i < qualities.length; i++) {\r\n if (qualities[i].src === currentSrc) {\r\n return i;\r\n }\r\n }\r\n \r\n return 0; // Default to first quality if not found\r\n }\r\n\r\n destroy() {\r\n // Remove event listeners\r\n this.media.removeEventListener('loadedmetadata', () => {});\r\n this.media.removeEventListener('play', () => {});\r\n this.media.removeEventListener('pause', () => {});\r\n // ... (other listeners would be removed in a real implementation)\r\n }\r\n}\r\n\r\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/dev/vidply.esm.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import {
|
|
7
7
|
HTML5Renderer
|
|
8
|
-
} from "./vidply.chunk-
|
|
8
|
+
} from "./vidply.chunk-BCOFCT6U.js";
|
|
9
9
|
import {
|
|
10
10
|
DOMUtils,
|
|
11
11
|
DraggableResizable,
|
|
@@ -3086,6 +3086,7 @@ var Player = class _Player extends EventEmitter {
|
|
|
3086
3086
|
this.element.appendChild(mediaElement);
|
|
3087
3087
|
this.element = mediaElement;
|
|
3088
3088
|
}
|
|
3089
|
+
this._originalElement = this.element;
|
|
3089
3090
|
this.options = {
|
|
3090
3091
|
// Display
|
|
3091
3092
|
width: null,
|
|
@@ -3359,7 +3360,7 @@ var Player = class _Player extends EventEmitter {
|
|
|
3359
3360
|
}
|
|
3360
3361
|
/**
|
|
3361
3362
|
* Detect language from HTML lang attribute
|
|
3362
|
-
* @returns {string|null} Language code if available in translations, null otherwise
|
|
3363
|
+
* @returns {string|null} Language code if available in translations or as built-in, null otherwise
|
|
3363
3364
|
*/
|
|
3364
3365
|
detectHtmlLanguage() {
|
|
3365
3366
|
const htmlLang = document.documentElement.lang || document.documentElement.getAttribute("lang");
|
|
@@ -3370,6 +3371,9 @@ var Player = class _Player extends EventEmitter {
|
|
|
3370
3371
|
if (i18n.translations[normalizedLang]) {
|
|
3371
3372
|
return normalizedLang;
|
|
3372
3373
|
}
|
|
3374
|
+
if (i18n.builtInLanguageLoaders && i18n.builtInLanguageLoaders[normalizedLang]) {
|
|
3375
|
+
return normalizedLang;
|
|
3376
|
+
}
|
|
3373
3377
|
this.log(`Language "${htmlLang}" not available, using English as fallback`);
|
|
3374
3378
|
return null;
|
|
3375
3379
|
}
|
|
@@ -3496,10 +3500,12 @@ var Player = class _Player extends EventEmitter {
|
|
|
3496
3500
|
this.playButtonOverlay.style.top = `${videoCenter}px`;
|
|
3497
3501
|
}
|
|
3498
3502
|
async initializeRenderer() {
|
|
3499
|
-
|
|
3503
|
+
let src = this._pendingSource || this.element.src || this.element.querySelector("source")?.src;
|
|
3500
3504
|
if (!src) {
|
|
3501
3505
|
throw new Error("No media source found");
|
|
3502
3506
|
}
|
|
3507
|
+
this.currentSource = src;
|
|
3508
|
+
this._pendingSource = null;
|
|
3503
3509
|
const sourceElements = this.sourceElements;
|
|
3504
3510
|
for (const sourceEl of sourceElements) {
|
|
3505
3511
|
const descSrc = sourceEl.getAttribute("data-desc-src");
|
|
@@ -3552,14 +3558,17 @@ var Player = class _Player extends EventEmitter {
|
|
|
3552
3558
|
}
|
|
3553
3559
|
let rendererClass = HTML5Renderer;
|
|
3554
3560
|
if (src.includes("youtube.com") || src.includes("youtu.be")) {
|
|
3555
|
-
const module = await import("./vidply.YouTubeRenderer-
|
|
3561
|
+
const module = await import("./vidply.YouTubeRenderer-6MGKEFTZ.js");
|
|
3556
3562
|
rendererClass = module.YouTubeRenderer || module.default;
|
|
3557
3563
|
} else if (src.includes("vimeo.com")) {
|
|
3558
|
-
const module = await import("./vidply.VimeoRenderer-
|
|
3564
|
+
const module = await import("./vidply.VimeoRenderer-VPH4RNES.js");
|
|
3559
3565
|
rendererClass = module.VimeoRenderer || module.default;
|
|
3560
3566
|
} else if (src.includes(".m3u8")) {
|
|
3561
|
-
const module = await import("./vidply.HLSRenderer-
|
|
3567
|
+
const module = await import("./vidply.HLSRenderer-ENLZE4QS.js");
|
|
3562
3568
|
rendererClass = module.HLSRenderer || module.default;
|
|
3569
|
+
} else if (src.includes("soundcloud.com") || src.includes("api.soundcloud.com")) {
|
|
3570
|
+
const module = await import("./vidply.SoundCloudRenderer-CD7VJKNS.js");
|
|
3571
|
+
rendererClass = module.SoundCloudRenderer || module.default;
|
|
3563
3572
|
}
|
|
3564
3573
|
this.log(`Using ${rendererClass?.name || "HTML5Renderer"} renderer`);
|
|
3565
3574
|
this.renderer = new rendererClass(this);
|
|
@@ -3671,6 +3680,11 @@ var Player = class _Player extends EventEmitter {
|
|
|
3671
3680
|
const resolvedPoster = this.resolvePosterPath(poster);
|
|
3672
3681
|
this.videoWrapper.style.setProperty("--vidply-poster-image", `url("${resolvedPoster}")`);
|
|
3673
3682
|
this.videoWrapper.classList.add("vidply-forced-poster");
|
|
3683
|
+
if (this._isAudioContent && this.container) {
|
|
3684
|
+
this.container.classList.add("vidply-audio-content");
|
|
3685
|
+
} else if (this.container) {
|
|
3686
|
+
this.container.classList.remove("vidply-audio-content");
|
|
3687
|
+
}
|
|
3674
3688
|
}
|
|
3675
3689
|
hidePosterOverlay() {
|
|
3676
3690
|
if (!this.videoWrapper) {
|
|
@@ -3713,6 +3727,15 @@ var Player = class _Player extends EventEmitter {
|
|
|
3713
3727
|
* @param {string} [config.audioDescriptionSrc] - Audio description video URL
|
|
3714
3728
|
* @param {string} [config.signLanguageSrc] - Sign language video URL
|
|
3715
3729
|
*/
|
|
3730
|
+
/**
|
|
3731
|
+
* Check if a source URL requires an external renderer (YouTube, Vimeo, SoundCloud, HLS)
|
|
3732
|
+
* @param {string} src - Source URL
|
|
3733
|
+
* @returns {boolean}
|
|
3734
|
+
*/
|
|
3735
|
+
isExternalRendererUrl(src) {
|
|
3736
|
+
if (!src) return false;
|
|
3737
|
+
return src.includes("youtube.com") || src.includes("youtu.be") || src.includes("vimeo.com") || src.includes("soundcloud.com") || src.includes("api.soundcloud.com") || src.includes(".m3u8");
|
|
3738
|
+
}
|
|
3716
3739
|
async load(config) {
|
|
3717
3740
|
try {
|
|
3718
3741
|
this.log("Loading new media:", config.src);
|
|
@@ -3724,12 +3747,44 @@ var Player = class _Player extends EventEmitter {
|
|
|
3724
3747
|
const existingTracks = this.trackElements;
|
|
3725
3748
|
existingTracks.forEach((track) => track.remove());
|
|
3726
3749
|
this.invalidateTrackCache();
|
|
3727
|
-
|
|
3728
|
-
if (
|
|
3729
|
-
this.
|
|
3750
|
+
const isExternalRenderer = this.isExternalRendererUrl(config.src);
|
|
3751
|
+
if (isExternalRenderer) {
|
|
3752
|
+
this._switchingRenderer = true;
|
|
3753
|
+
}
|
|
3754
|
+
if (!isExternalRenderer) {
|
|
3755
|
+
this.element.src = config.src;
|
|
3756
|
+
if (config.type) {
|
|
3757
|
+
this.element.type = config.type;
|
|
3758
|
+
}
|
|
3759
|
+
} else {
|
|
3760
|
+
this.element.removeAttribute("src");
|
|
3761
|
+
const sources = this.element.querySelectorAll("source");
|
|
3762
|
+
sources.forEach((s) => s.removeAttribute("src"));
|
|
3763
|
+
}
|
|
3764
|
+
this._pendingSource = config.src;
|
|
3765
|
+
this._isAudioContent = config.type && config.type.startsWith("audio/");
|
|
3766
|
+
if (this.container) {
|
|
3767
|
+
if (this._isAudioContent) {
|
|
3768
|
+
this.container.classList.add("vidply-audio-content");
|
|
3769
|
+
} else {
|
|
3770
|
+
this.container.classList.remove("vidply-audio-content");
|
|
3771
|
+
}
|
|
3730
3772
|
}
|
|
3731
3773
|
if (config.poster && this.element.tagName === "VIDEO") {
|
|
3732
|
-
|
|
3774
|
+
if (this._isAudioContent) {
|
|
3775
|
+
this.element.removeAttribute("poster");
|
|
3776
|
+
if (this.videoWrapper) {
|
|
3777
|
+
const resolvedPoster = this.resolvePosterPath(config.poster);
|
|
3778
|
+
this.videoWrapper.style.setProperty("--vidply-poster-image", `url("${resolvedPoster}")`);
|
|
3779
|
+
this.videoWrapper.classList.add("vidply-forced-poster");
|
|
3780
|
+
}
|
|
3781
|
+
} else {
|
|
3782
|
+
this.element.poster = this.resolvePosterPath(config.poster);
|
|
3783
|
+
if (this.videoWrapper) {
|
|
3784
|
+
this.videoWrapper.classList.remove("vidply-forced-poster");
|
|
3785
|
+
this.videoWrapper.style.removeProperty("--vidply-poster-image");
|
|
3786
|
+
}
|
|
3787
|
+
}
|
|
3733
3788
|
}
|
|
3734
3789
|
if (config.tracks && config.tracks.length > 0) {
|
|
3735
3790
|
config.tracks.forEach((trackConfig) => {
|
|
@@ -3772,6 +3827,13 @@ var Player = class _Player extends EventEmitter {
|
|
|
3772
3827
|
this.renderer.media = this.element;
|
|
3773
3828
|
this.element.load();
|
|
3774
3829
|
}
|
|
3830
|
+
if (isExternalRenderer) {
|
|
3831
|
+
setTimeout(() => {
|
|
3832
|
+
this._switchingRenderer = false;
|
|
3833
|
+
}, 500);
|
|
3834
|
+
} else {
|
|
3835
|
+
this._switchingRenderer = false;
|
|
3836
|
+
}
|
|
3775
3837
|
window.scrollTo(scrollX, scrollY);
|
|
3776
3838
|
if (this.captionManager) {
|
|
3777
3839
|
this.captionManager.destroy();
|
|
@@ -3830,11 +3892,13 @@ var Player = class _Player extends EventEmitter {
|
|
|
3830
3892
|
const isYouTube = src.includes("youtube.com") || src.includes("youtu.be");
|
|
3831
3893
|
const isVimeo = src.includes("vimeo.com");
|
|
3832
3894
|
const isHLS = src.includes(".m3u8");
|
|
3895
|
+
const isSoundCloud = src.includes("soundcloud.com") || src.includes("api.soundcloud.com");
|
|
3833
3896
|
const currentRendererName = this.renderer.constructor.name;
|
|
3834
3897
|
if (isYouTube && currentRendererName !== "YouTubeRenderer") return true;
|
|
3835
3898
|
if (isVimeo && currentRendererName !== "VimeoRenderer") return true;
|
|
3836
3899
|
if (isHLS && currentRendererName !== "HLSRenderer") return true;
|
|
3837
|
-
if (
|
|
3900
|
+
if (isSoundCloud && currentRendererName !== "SoundCloudRenderer") return true;
|
|
3901
|
+
if (!isYouTube && !isVimeo && !isHLS && !isSoundCloud && currentRendererName !== "HTML5Renderer") return true;
|
|
3838
3902
|
return false;
|
|
3839
3903
|
}
|
|
3840
3904
|
// Playback controls
|
|
@@ -6046,6 +6110,10 @@ var Player = class _Player extends EventEmitter {
|
|
|
6046
6110
|
}
|
|
6047
6111
|
// Error handling
|
|
6048
6112
|
handleError(error) {
|
|
6113
|
+
if (this._switchingRenderer) {
|
|
6114
|
+
this.log("Suppressing error during renderer switch:", error, "debug");
|
|
6115
|
+
return;
|
|
6116
|
+
}
|
|
6049
6117
|
this.log("Error:", error, "error");
|
|
6050
6118
|
this.emit("error", error);
|
|
6051
6119
|
if (this.options.onError) {
|
|
@@ -6584,6 +6652,8 @@ var PlaylistManager = class {
|
|
|
6584
6652
|
loop: options.loop || false,
|
|
6585
6653
|
showPanel: options.showPanel !== false,
|
|
6586
6654
|
// Default true
|
|
6655
|
+
recreatePlayers: options.recreatePlayers || false,
|
|
6656
|
+
// New: recreate player for each track type
|
|
6587
6657
|
...options
|
|
6588
6658
|
};
|
|
6589
6659
|
this.container = null;
|
|
@@ -6592,6 +6662,8 @@ var PlaylistManager = class {
|
|
|
6592
6662
|
this.navigationFeedback = null;
|
|
6593
6663
|
this.isPanelVisible = this.options.showPanel !== false;
|
|
6594
6664
|
this.isChangingTrack = false;
|
|
6665
|
+
this.hostElement = options.hostElement || null;
|
|
6666
|
+
this.PlayerClass = options.PlayerClass || null;
|
|
6595
6667
|
this.handleTrackEnd = this.handleTrackEnd.bind(this);
|
|
6596
6668
|
this.handleTrackError = this.handleTrackError.bind(this);
|
|
6597
6669
|
this.player.playlistManager = this;
|
|
@@ -6601,6 +6673,159 @@ var PlaylistManager = class {
|
|
|
6601
6673
|
this.loadPlaylist(this.initialTracks);
|
|
6602
6674
|
}
|
|
6603
6675
|
}
|
|
6676
|
+
/**
|
|
6677
|
+
* Determine the media type for a track
|
|
6678
|
+
* @param {Object} track - Track object
|
|
6679
|
+
* @returns {string} - 'audio', 'video', 'youtube', 'vimeo', 'soundcloud', 'hls'
|
|
6680
|
+
*/
|
|
6681
|
+
getTrackMediaType(track) {
|
|
6682
|
+
const src = track.src || "";
|
|
6683
|
+
if (src.includes("youtube.com") || src.includes("youtu.be")) {
|
|
6684
|
+
return "youtube";
|
|
6685
|
+
}
|
|
6686
|
+
if (src.includes("vimeo.com")) {
|
|
6687
|
+
return "vimeo";
|
|
6688
|
+
}
|
|
6689
|
+
if (src.includes("soundcloud.com") || src.includes("api.soundcloud.com")) {
|
|
6690
|
+
return "soundcloud";
|
|
6691
|
+
}
|
|
6692
|
+
if (src.includes(".m3u8")) {
|
|
6693
|
+
return "hls";
|
|
6694
|
+
}
|
|
6695
|
+
if (track.type && track.type.startsWith("audio/")) {
|
|
6696
|
+
return "audio";
|
|
6697
|
+
}
|
|
6698
|
+
return "video";
|
|
6699
|
+
}
|
|
6700
|
+
/**
|
|
6701
|
+
* Recreate the player with the appropriate element type for the track
|
|
6702
|
+
* @param {Object} track - Track to load
|
|
6703
|
+
* @param {boolean} autoPlay - Whether to auto-play after creation
|
|
6704
|
+
*/
|
|
6705
|
+
async recreatePlayerForTrack(track, autoPlay = false) {
|
|
6706
|
+
if (!this.hostElement || !this.PlayerClass) {
|
|
6707
|
+
console.warn("VidPly Playlist: Cannot recreate player - missing hostElement or PlayerClass");
|
|
6708
|
+
return false;
|
|
6709
|
+
}
|
|
6710
|
+
const mediaType = this.getTrackMediaType(track);
|
|
6711
|
+
const elementType = mediaType === "audio" ? "audio" : "video";
|
|
6712
|
+
const wasVisible = this.isPanelVisible;
|
|
6713
|
+
const savedTracks = [...this.tracks];
|
|
6714
|
+
const savedIndex = this.currentIndex;
|
|
6715
|
+
if (this.trackArtworkElement && this.trackArtworkElement.parentNode) {
|
|
6716
|
+
this.trackArtworkElement.parentNode.removeChild(this.trackArtworkElement);
|
|
6717
|
+
}
|
|
6718
|
+
if (this.trackInfoElement && this.trackInfoElement.parentNode) {
|
|
6719
|
+
this.trackInfoElement.parentNode.removeChild(this.trackInfoElement);
|
|
6720
|
+
}
|
|
6721
|
+
if (this.navigationFeedback && this.navigationFeedback.parentNode) {
|
|
6722
|
+
this.navigationFeedback.parentNode.removeChild(this.navigationFeedback);
|
|
6723
|
+
}
|
|
6724
|
+
if (this.playlistPanel && this.playlistPanel.parentNode) {
|
|
6725
|
+
this.playlistPanel.parentNode.removeChild(this.playlistPanel);
|
|
6726
|
+
}
|
|
6727
|
+
if (this.player) {
|
|
6728
|
+
this.player.off("ended", this.handleTrackEnd);
|
|
6729
|
+
this.player.off("error", this.handleTrackError);
|
|
6730
|
+
this.player.destroy();
|
|
6731
|
+
}
|
|
6732
|
+
this.hostElement.innerHTML = "";
|
|
6733
|
+
const mediaElement = document.createElement(elementType);
|
|
6734
|
+
mediaElement.setAttribute("preload", "metadata");
|
|
6735
|
+
if (elementType === "video" && track.poster && (mediaType === "video" || mediaType === "hls")) {
|
|
6736
|
+
mediaElement.setAttribute("poster", track.poster);
|
|
6737
|
+
}
|
|
6738
|
+
const isExternalRenderer = ["youtube", "vimeo", "soundcloud", "hls"].includes(mediaType);
|
|
6739
|
+
if (!isExternalRenderer) {
|
|
6740
|
+
const source = document.createElement("source");
|
|
6741
|
+
source.src = track.src;
|
|
6742
|
+
if (track.type) {
|
|
6743
|
+
source.type = track.type;
|
|
6744
|
+
}
|
|
6745
|
+
mediaElement.appendChild(source);
|
|
6746
|
+
if (track.tracks && track.tracks.length > 0) {
|
|
6747
|
+
track.tracks.forEach((trackConfig) => {
|
|
6748
|
+
const trackEl = document.createElement("track");
|
|
6749
|
+
trackEl.src = trackConfig.src;
|
|
6750
|
+
trackEl.kind = trackConfig.kind || "captions";
|
|
6751
|
+
trackEl.srclang = trackConfig.srclang || "en";
|
|
6752
|
+
trackEl.label = trackConfig.label || trackConfig.srclang;
|
|
6753
|
+
if (trackConfig.default) {
|
|
6754
|
+
trackEl.default = true;
|
|
6755
|
+
}
|
|
6756
|
+
mediaElement.appendChild(trackEl);
|
|
6757
|
+
});
|
|
6758
|
+
}
|
|
6759
|
+
}
|
|
6760
|
+
this.hostElement.appendChild(mediaElement);
|
|
6761
|
+
const playerOptions = {
|
|
6762
|
+
mediaType: elementType,
|
|
6763
|
+
poster: track.poster,
|
|
6764
|
+
audioDescriptionSrc: track.audioDescriptionSrc || null,
|
|
6765
|
+
audioDescriptionDuration: track.audioDescriptionDuration || null,
|
|
6766
|
+
signLanguageSrc: track.signLanguageSrc || null
|
|
6767
|
+
};
|
|
6768
|
+
this.player = new this.PlayerClass(mediaElement, playerOptions);
|
|
6769
|
+
this.player.playlistManager = this;
|
|
6770
|
+
await new Promise((resolve) => {
|
|
6771
|
+
this.player.on("ready", resolve);
|
|
6772
|
+
});
|
|
6773
|
+
this.player.on("ended", this.handleTrackEnd);
|
|
6774
|
+
this.player.on("error", this.handleTrackError);
|
|
6775
|
+
if (this.player.container) {
|
|
6776
|
+
if (this.trackArtworkElement) {
|
|
6777
|
+
const videoWrapper = this.player.container.querySelector(".vidply-video-wrapper");
|
|
6778
|
+
if (videoWrapper) {
|
|
6779
|
+
this.player.container.insertBefore(this.trackArtworkElement, videoWrapper);
|
|
6780
|
+
} else {
|
|
6781
|
+
this.player.container.appendChild(this.trackArtworkElement);
|
|
6782
|
+
}
|
|
6783
|
+
}
|
|
6784
|
+
if (this.trackInfoElement) {
|
|
6785
|
+
this.player.container.appendChild(this.trackInfoElement);
|
|
6786
|
+
}
|
|
6787
|
+
if (this.navigationFeedback) {
|
|
6788
|
+
this.player.container.appendChild(this.navigationFeedback);
|
|
6789
|
+
}
|
|
6790
|
+
if (this.playlistPanel) {
|
|
6791
|
+
this.player.container.appendChild(this.playlistPanel);
|
|
6792
|
+
}
|
|
6793
|
+
}
|
|
6794
|
+
this.container = this.player.container;
|
|
6795
|
+
this.updatePlayerControls();
|
|
6796
|
+
this.tracks = savedTracks;
|
|
6797
|
+
this.currentIndex = savedIndex;
|
|
6798
|
+
this.updatePlaylistUI();
|
|
6799
|
+
this.isPanelVisible = wasVisible;
|
|
6800
|
+
if (this.playlistPanel) {
|
|
6801
|
+
this.playlistPanel.style.display = wasVisible ? "" : "none";
|
|
6802
|
+
}
|
|
6803
|
+
if (isExternalRenderer) {
|
|
6804
|
+
this.player.load({
|
|
6805
|
+
src: track.src,
|
|
6806
|
+
type: track.type,
|
|
6807
|
+
poster: track.poster,
|
|
6808
|
+
tracks: track.tracks || [],
|
|
6809
|
+
audioDescriptionSrc: track.audioDescriptionSrc || null,
|
|
6810
|
+
signLanguageSrc: track.signLanguageSrc || null
|
|
6811
|
+
});
|
|
6812
|
+
} else {
|
|
6813
|
+
this.player.load({
|
|
6814
|
+
src: track.src,
|
|
6815
|
+
type: track.type,
|
|
6816
|
+
poster: track.poster,
|
|
6817
|
+
tracks: track.tracks || [],
|
|
6818
|
+
audioDescriptionSrc: track.audioDescriptionSrc || null,
|
|
6819
|
+
signLanguageSrc: track.signLanguageSrc || null
|
|
6820
|
+
});
|
|
6821
|
+
}
|
|
6822
|
+
if (autoPlay) {
|
|
6823
|
+
setTimeout(() => {
|
|
6824
|
+
this.player.play();
|
|
6825
|
+
}, 100);
|
|
6826
|
+
}
|
|
6827
|
+
return true;
|
|
6828
|
+
}
|
|
6604
6829
|
init() {
|
|
6605
6830
|
this.player.on("ended", this.handleTrackEnd);
|
|
6606
6831
|
this.player.on("error", this.handleTrackError);
|
|
@@ -6711,7 +6936,7 @@ var PlaylistManager = class {
|
|
|
6711
6936
|
* Load a track without playing
|
|
6712
6937
|
* @param {number} index - Track index
|
|
6713
6938
|
*/
|
|
6714
|
-
loadTrack(index) {
|
|
6939
|
+
async loadTrack(index) {
|
|
6715
6940
|
if (index < 0 || index >= this.tracks.length) {
|
|
6716
6941
|
console.warn("VidPly Playlist: Invalid track index", index);
|
|
6717
6942
|
return;
|
|
@@ -6719,6 +6944,25 @@ var PlaylistManager = class {
|
|
|
6719
6944
|
const track = this.tracks[index];
|
|
6720
6945
|
this.isChangingTrack = true;
|
|
6721
6946
|
this.currentIndex = index;
|
|
6947
|
+
if (this.options.recreatePlayers && this.hostElement && this.PlayerClass) {
|
|
6948
|
+
const currentMediaType = this.player ? this.player.element.tagName === "AUDIO" ? "audio" : "video" : null;
|
|
6949
|
+
const newMediaType = this.getTrackMediaType(track);
|
|
6950
|
+
const newElementType = newMediaType === "audio" || newMediaType === "soundcloud" ? "audio" : "video";
|
|
6951
|
+
if (currentMediaType !== newElementType) {
|
|
6952
|
+
await this.recreatePlayerForTrack(track, false);
|
|
6953
|
+
this.updateTrackInfo(track);
|
|
6954
|
+
this.updatePlaylistUI();
|
|
6955
|
+
this.player.emit("playlisttrackchange", {
|
|
6956
|
+
index,
|
|
6957
|
+
item: track,
|
|
6958
|
+
total: this.tracks.length
|
|
6959
|
+
});
|
|
6960
|
+
setTimeout(() => {
|
|
6961
|
+
this.isChangingTrack = false;
|
|
6962
|
+
}, 150);
|
|
6963
|
+
return;
|
|
6964
|
+
}
|
|
6965
|
+
}
|
|
6722
6966
|
this.player.load({
|
|
6723
6967
|
src: track.src,
|
|
6724
6968
|
type: track.type,
|
|
@@ -6743,7 +6987,7 @@ var PlaylistManager = class {
|
|
|
6743
6987
|
* @param {number} index - Track index
|
|
6744
6988
|
* @param {boolean} userInitiated - Whether this was triggered by user action (default: false)
|
|
6745
6989
|
*/
|
|
6746
|
-
play(index, userInitiated = false) {
|
|
6990
|
+
async play(index, userInitiated = false) {
|
|
6747
6991
|
if (index < 0 || index >= this.tracks.length) {
|
|
6748
6992
|
console.warn("VidPly Playlist: Invalid track index", index);
|
|
6749
6993
|
return;
|
|
@@ -6751,6 +6995,25 @@ var PlaylistManager = class {
|
|
|
6751
6995
|
const track = this.tracks[index];
|
|
6752
6996
|
this.isChangingTrack = true;
|
|
6753
6997
|
this.currentIndex = index;
|
|
6998
|
+
if (this.options.recreatePlayers && this.hostElement && this.PlayerClass) {
|
|
6999
|
+
const currentMediaType = this.player ? this.player.element.tagName === "AUDIO" ? "audio" : "video" : null;
|
|
7000
|
+
const newMediaType = this.getTrackMediaType(track);
|
|
7001
|
+
const newElementType = newMediaType === "audio" || newMediaType === "soundcloud" ? "audio" : "video";
|
|
7002
|
+
if (currentMediaType !== newElementType) {
|
|
7003
|
+
await this.recreatePlayerForTrack(track, true);
|
|
7004
|
+
this.updateTrackInfo(track);
|
|
7005
|
+
this.updatePlaylistUI();
|
|
7006
|
+
this.player.emit("playlisttrackchange", {
|
|
7007
|
+
index,
|
|
7008
|
+
item: track,
|
|
7009
|
+
total: this.tracks.length
|
|
7010
|
+
});
|
|
7011
|
+
setTimeout(() => {
|
|
7012
|
+
this.isChangingTrack = false;
|
|
7013
|
+
}, 150);
|
|
7014
|
+
return;
|
|
7015
|
+
}
|
|
7016
|
+
}
|
|
6754
7017
|
this.player.load({
|
|
6755
7018
|
src: track.src,
|
|
6756
7019
|
type: track.type,
|
|
@@ -6812,10 +7075,26 @@ var PlaylistManager = class {
|
|
|
6812
7075
|
this.next();
|
|
6813
7076
|
}
|
|
6814
7077
|
}
|
|
7078
|
+
/**
|
|
7079
|
+
* Check if a source URL requires an external renderer
|
|
7080
|
+
* @param {string} src - Source URL
|
|
7081
|
+
* @returns {boolean}
|
|
7082
|
+
*/
|
|
7083
|
+
isExternalRendererUrl(src) {
|
|
7084
|
+
if (!src) return false;
|
|
7085
|
+
return src.includes("youtube.com") || src.includes("youtu.be") || src.includes("vimeo.com") || src.includes("soundcloud.com") || src.includes("api.soundcloud.com") || src.includes(".m3u8");
|
|
7086
|
+
}
|
|
6815
7087
|
/**
|
|
6816
7088
|
* Handle track error
|
|
6817
7089
|
*/
|
|
6818
7090
|
handleTrackError(e) {
|
|
7091
|
+
const currentTrack = this.getCurrentTrack();
|
|
7092
|
+
if (currentTrack && currentTrack.src && this.isExternalRendererUrl(currentTrack.src)) {
|
|
7093
|
+
return;
|
|
7094
|
+
}
|
|
7095
|
+
if (this.isChangingTrack) {
|
|
7096
|
+
return;
|
|
7097
|
+
}
|
|
6819
7098
|
console.error("VidPly Playlist: Track error", e);
|
|
6820
7099
|
if (this.options.autoAdvance) {
|
|
6821
7100
|
setTimeout(() => {
|