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
|
@@ -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,
|
|
@@ -3499,10 +3500,12 @@ var Player = class _Player extends EventEmitter {
|
|
|
3499
3500
|
this.playButtonOverlay.style.top = `${videoCenter}px`;
|
|
3500
3501
|
}
|
|
3501
3502
|
async initializeRenderer() {
|
|
3502
|
-
|
|
3503
|
+
let src = this._pendingSource || this.element.src || this.element.querySelector("source")?.src;
|
|
3503
3504
|
if (!src) {
|
|
3504
3505
|
throw new Error("No media source found");
|
|
3505
3506
|
}
|
|
3507
|
+
this.currentSource = src;
|
|
3508
|
+
this._pendingSource = null;
|
|
3506
3509
|
const sourceElements = this.sourceElements;
|
|
3507
3510
|
for (const sourceEl of sourceElements) {
|
|
3508
3511
|
const descSrc = sourceEl.getAttribute("data-desc-src");
|
|
@@ -3555,14 +3558,17 @@ var Player = class _Player extends EventEmitter {
|
|
|
3555
3558
|
}
|
|
3556
3559
|
let rendererClass = HTML5Renderer;
|
|
3557
3560
|
if (src.includes("youtube.com") || src.includes("youtu.be")) {
|
|
3558
|
-
const module = await import("./vidply.YouTubeRenderer-
|
|
3561
|
+
const module = await import("./vidply.YouTubeRenderer-6MGKEFTZ.js");
|
|
3559
3562
|
rendererClass = module.YouTubeRenderer || module.default;
|
|
3560
3563
|
} else if (src.includes("vimeo.com")) {
|
|
3561
|
-
const module = await import("./vidply.VimeoRenderer-
|
|
3564
|
+
const module = await import("./vidply.VimeoRenderer-VPH4RNES.js");
|
|
3562
3565
|
rendererClass = module.VimeoRenderer || module.default;
|
|
3563
3566
|
} else if (src.includes(".m3u8")) {
|
|
3564
|
-
const module = await import("./vidply.HLSRenderer-
|
|
3567
|
+
const module = await import("./vidply.HLSRenderer-ENLZE4QS.js");
|
|
3565
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;
|
|
3566
3572
|
}
|
|
3567
3573
|
this.log(`Using ${rendererClass?.name || "HTML5Renderer"} renderer`);
|
|
3568
3574
|
this.renderer = new rendererClass(this);
|
|
@@ -3674,6 +3680,11 @@ var Player = class _Player extends EventEmitter {
|
|
|
3674
3680
|
const resolvedPoster = this.resolvePosterPath(poster);
|
|
3675
3681
|
this.videoWrapper.style.setProperty("--vidply-poster-image", `url("${resolvedPoster}")`);
|
|
3676
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
|
+
}
|
|
3677
3688
|
}
|
|
3678
3689
|
hidePosterOverlay() {
|
|
3679
3690
|
if (!this.videoWrapper) {
|
|
@@ -3716,6 +3727,15 @@ var Player = class _Player extends EventEmitter {
|
|
|
3716
3727
|
* @param {string} [config.audioDescriptionSrc] - Audio description video URL
|
|
3717
3728
|
* @param {string} [config.signLanguageSrc] - Sign language video URL
|
|
3718
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
|
+
}
|
|
3719
3739
|
async load(config) {
|
|
3720
3740
|
try {
|
|
3721
3741
|
this.log("Loading new media:", config.src);
|
|
@@ -3727,12 +3747,44 @@ var Player = class _Player extends EventEmitter {
|
|
|
3727
3747
|
const existingTracks = this.trackElements;
|
|
3728
3748
|
existingTracks.forEach((track) => track.remove());
|
|
3729
3749
|
this.invalidateTrackCache();
|
|
3730
|
-
|
|
3731
|
-
if (
|
|
3732
|
-
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
|
+
}
|
|
3733
3772
|
}
|
|
3734
3773
|
if (config.poster && this.element.tagName === "VIDEO") {
|
|
3735
|
-
|
|
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
|
+
}
|
|
3736
3788
|
}
|
|
3737
3789
|
if (config.tracks && config.tracks.length > 0) {
|
|
3738
3790
|
config.tracks.forEach((trackConfig) => {
|
|
@@ -3775,6 +3827,13 @@ var Player = class _Player extends EventEmitter {
|
|
|
3775
3827
|
this.renderer.media = this.element;
|
|
3776
3828
|
this.element.load();
|
|
3777
3829
|
}
|
|
3830
|
+
if (isExternalRenderer) {
|
|
3831
|
+
setTimeout(() => {
|
|
3832
|
+
this._switchingRenderer = false;
|
|
3833
|
+
}, 500);
|
|
3834
|
+
} else {
|
|
3835
|
+
this._switchingRenderer = false;
|
|
3836
|
+
}
|
|
3778
3837
|
window.scrollTo(scrollX, scrollY);
|
|
3779
3838
|
if (this.captionManager) {
|
|
3780
3839
|
this.captionManager.destroy();
|
|
@@ -3833,11 +3892,13 @@ var Player = class _Player extends EventEmitter {
|
|
|
3833
3892
|
const isYouTube = src.includes("youtube.com") || src.includes("youtu.be");
|
|
3834
3893
|
const isVimeo = src.includes("vimeo.com");
|
|
3835
3894
|
const isHLS = src.includes(".m3u8");
|
|
3895
|
+
const isSoundCloud = src.includes("soundcloud.com") || src.includes("api.soundcloud.com");
|
|
3836
3896
|
const currentRendererName = this.renderer.constructor.name;
|
|
3837
3897
|
if (isYouTube && currentRendererName !== "YouTubeRenderer") return true;
|
|
3838
3898
|
if (isVimeo && currentRendererName !== "VimeoRenderer") return true;
|
|
3839
3899
|
if (isHLS && currentRendererName !== "HLSRenderer") return true;
|
|
3840
|
-
if (
|
|
3900
|
+
if (isSoundCloud && currentRendererName !== "SoundCloudRenderer") return true;
|
|
3901
|
+
if (!isYouTube && !isVimeo && !isHLS && !isSoundCloud && currentRendererName !== "HTML5Renderer") return true;
|
|
3841
3902
|
return false;
|
|
3842
3903
|
}
|
|
3843
3904
|
// Playback controls
|
|
@@ -6049,6 +6110,10 @@ var Player = class _Player extends EventEmitter {
|
|
|
6049
6110
|
}
|
|
6050
6111
|
// Error handling
|
|
6051
6112
|
handleError(error) {
|
|
6113
|
+
if (this._switchingRenderer) {
|
|
6114
|
+
this.log("Suppressing error during renderer switch:", error, "debug");
|
|
6115
|
+
return;
|
|
6116
|
+
}
|
|
6052
6117
|
this.log("Error:", error, "error");
|
|
6053
6118
|
this.emit("error", error);
|
|
6054
6119
|
if (this.options.onError) {
|
|
@@ -6587,6 +6652,8 @@ var PlaylistManager = class {
|
|
|
6587
6652
|
loop: options.loop || false,
|
|
6588
6653
|
showPanel: options.showPanel !== false,
|
|
6589
6654
|
// Default true
|
|
6655
|
+
recreatePlayers: options.recreatePlayers || false,
|
|
6656
|
+
// New: recreate player for each track type
|
|
6590
6657
|
...options
|
|
6591
6658
|
};
|
|
6592
6659
|
this.container = null;
|
|
@@ -6595,6 +6662,8 @@ var PlaylistManager = class {
|
|
|
6595
6662
|
this.navigationFeedback = null;
|
|
6596
6663
|
this.isPanelVisible = this.options.showPanel !== false;
|
|
6597
6664
|
this.isChangingTrack = false;
|
|
6665
|
+
this.hostElement = options.hostElement || null;
|
|
6666
|
+
this.PlayerClass = options.PlayerClass || null;
|
|
6598
6667
|
this.handleTrackEnd = this.handleTrackEnd.bind(this);
|
|
6599
6668
|
this.handleTrackError = this.handleTrackError.bind(this);
|
|
6600
6669
|
this.player.playlistManager = this;
|
|
@@ -6604,6 +6673,159 @@ var PlaylistManager = class {
|
|
|
6604
6673
|
this.loadPlaylist(this.initialTracks);
|
|
6605
6674
|
}
|
|
6606
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
|
+
}
|
|
6607
6829
|
init() {
|
|
6608
6830
|
this.player.on("ended", this.handleTrackEnd);
|
|
6609
6831
|
this.player.on("error", this.handleTrackError);
|
|
@@ -6714,7 +6936,7 @@ var PlaylistManager = class {
|
|
|
6714
6936
|
* Load a track without playing
|
|
6715
6937
|
* @param {number} index - Track index
|
|
6716
6938
|
*/
|
|
6717
|
-
loadTrack(index) {
|
|
6939
|
+
async loadTrack(index) {
|
|
6718
6940
|
if (index < 0 || index >= this.tracks.length) {
|
|
6719
6941
|
console.warn("VidPly Playlist: Invalid track index", index);
|
|
6720
6942
|
return;
|
|
@@ -6722,6 +6944,25 @@ var PlaylistManager = class {
|
|
|
6722
6944
|
const track = this.tracks[index];
|
|
6723
6945
|
this.isChangingTrack = true;
|
|
6724
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
|
+
}
|
|
6725
6966
|
this.player.load({
|
|
6726
6967
|
src: track.src,
|
|
6727
6968
|
type: track.type,
|
|
@@ -6746,7 +6987,7 @@ var PlaylistManager = class {
|
|
|
6746
6987
|
* @param {number} index - Track index
|
|
6747
6988
|
* @param {boolean} userInitiated - Whether this was triggered by user action (default: false)
|
|
6748
6989
|
*/
|
|
6749
|
-
play(index, userInitiated = false) {
|
|
6990
|
+
async play(index, userInitiated = false) {
|
|
6750
6991
|
if (index < 0 || index >= this.tracks.length) {
|
|
6751
6992
|
console.warn("VidPly Playlist: Invalid track index", index);
|
|
6752
6993
|
return;
|
|
@@ -6754,6 +6995,25 @@ var PlaylistManager = class {
|
|
|
6754
6995
|
const track = this.tracks[index];
|
|
6755
6996
|
this.isChangingTrack = true;
|
|
6756
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
|
+
}
|
|
6757
7017
|
this.player.load({
|
|
6758
7018
|
src: track.src,
|
|
6759
7019
|
type: track.type,
|
|
@@ -6815,10 +7075,26 @@ var PlaylistManager = class {
|
|
|
6815
7075
|
this.next();
|
|
6816
7076
|
}
|
|
6817
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
|
+
}
|
|
6818
7087
|
/**
|
|
6819
7088
|
* Handle track error
|
|
6820
7089
|
*/
|
|
6821
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
|
+
}
|
|
6822
7098
|
console.error("VidPly Playlist: Track error", e);
|
|
6823
7099
|
if (this.options.autoAdvance) {
|
|
6824
7100
|
setTimeout(() => {
|