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
|
@@ -28,6 +28,7 @@ export class PlaylistManager {
|
|
|
28
28
|
autoPlayFirst: options.autoPlayFirst !== false, // Default true - auto-play first track on load
|
|
29
29
|
loop: options.loop || false,
|
|
30
30
|
showPanel: options.showPanel !== false, // Default true
|
|
31
|
+
recreatePlayers: options.recreatePlayers || false, // New: recreate player for each track type
|
|
31
32
|
...options
|
|
32
33
|
};
|
|
33
34
|
|
|
@@ -41,6 +42,10 @@ export class PlaylistManager {
|
|
|
41
42
|
// Track change guard to prevent cascade of next() calls
|
|
42
43
|
this.isChangingTrack = false;
|
|
43
44
|
|
|
45
|
+
// Store the host element for player recreation
|
|
46
|
+
this.hostElement = options.hostElement || null;
|
|
47
|
+
this.PlayerClass = options.PlayerClass || null;
|
|
48
|
+
|
|
44
49
|
// Bind methods
|
|
45
50
|
this.handleTrackEnd = this.handleTrackEnd.bind(this);
|
|
46
51
|
this.handleTrackError = this.handleTrackError.bind(this);
|
|
@@ -60,6 +65,221 @@ export class PlaylistManager {
|
|
|
60
65
|
}
|
|
61
66
|
}
|
|
62
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Determine the media type for a track
|
|
70
|
+
* @param {Object} track - Track object
|
|
71
|
+
* @returns {string} - 'audio', 'video', 'youtube', 'vimeo', 'soundcloud', 'hls'
|
|
72
|
+
*/
|
|
73
|
+
getTrackMediaType(track) {
|
|
74
|
+
const src = track.src || '';
|
|
75
|
+
|
|
76
|
+
if (src.includes('youtube.com') || src.includes('youtu.be')) {
|
|
77
|
+
return 'youtube';
|
|
78
|
+
}
|
|
79
|
+
if (src.includes('vimeo.com')) {
|
|
80
|
+
return 'vimeo';
|
|
81
|
+
}
|
|
82
|
+
if (src.includes('soundcloud.com') || src.includes('api.soundcloud.com')) {
|
|
83
|
+
return 'soundcloud';
|
|
84
|
+
}
|
|
85
|
+
if (src.includes('.m3u8')) {
|
|
86
|
+
return 'hls';
|
|
87
|
+
}
|
|
88
|
+
if (track.type && track.type.startsWith('audio/')) {
|
|
89
|
+
return 'audio';
|
|
90
|
+
}
|
|
91
|
+
// Default to video for video types or unknown
|
|
92
|
+
return 'video';
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Recreate the player with the appropriate element type for the track
|
|
97
|
+
* @param {Object} track - Track to load
|
|
98
|
+
* @param {boolean} autoPlay - Whether to auto-play after creation
|
|
99
|
+
*/
|
|
100
|
+
async recreatePlayerForTrack(track, autoPlay = false) {
|
|
101
|
+
if (!this.hostElement || !this.PlayerClass) {
|
|
102
|
+
console.warn('VidPly Playlist: Cannot recreate player - missing hostElement or PlayerClass');
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const mediaType = this.getTrackMediaType(track);
|
|
107
|
+
// SoundCloud uses an iframe widget, so it doesn't need an audio element
|
|
108
|
+
// Only local audio files need an actual <audio> element
|
|
109
|
+
const elementType = (mediaType === 'audio') ? 'audio' : 'video';
|
|
110
|
+
|
|
111
|
+
// Store playlist panel state
|
|
112
|
+
const wasVisible = this.isPanelVisible;
|
|
113
|
+
const savedTracks = [...this.tracks]; // Keep track data
|
|
114
|
+
const savedIndex = this.currentIndex;
|
|
115
|
+
|
|
116
|
+
// Detach all playlist UI elements from DOM (keep references)
|
|
117
|
+
// These will be reattached to the new player container
|
|
118
|
+
if (this.trackArtworkElement && this.trackArtworkElement.parentNode) {
|
|
119
|
+
this.trackArtworkElement.parentNode.removeChild(this.trackArtworkElement);
|
|
120
|
+
}
|
|
121
|
+
if (this.trackInfoElement && this.trackInfoElement.parentNode) {
|
|
122
|
+
this.trackInfoElement.parentNode.removeChild(this.trackInfoElement);
|
|
123
|
+
}
|
|
124
|
+
if (this.navigationFeedback && this.navigationFeedback.parentNode) {
|
|
125
|
+
this.navigationFeedback.parentNode.removeChild(this.navigationFeedback);
|
|
126
|
+
}
|
|
127
|
+
if (this.playlistPanel && this.playlistPanel.parentNode) {
|
|
128
|
+
this.playlistPanel.parentNode.removeChild(this.playlistPanel);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Remove event listeners before destroying
|
|
132
|
+
if (this.player) {
|
|
133
|
+
this.player.off('ended', this.handleTrackEnd);
|
|
134
|
+
this.player.off('error', this.handleTrackError);
|
|
135
|
+
this.player.destroy();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Clear the host element
|
|
139
|
+
this.hostElement.innerHTML = '';
|
|
140
|
+
|
|
141
|
+
// Create new media element with appropriate type
|
|
142
|
+
const mediaElement = document.createElement(elementType);
|
|
143
|
+
mediaElement.setAttribute('preload', 'metadata');
|
|
144
|
+
|
|
145
|
+
// For video elements with local media, set poster
|
|
146
|
+
if (elementType === 'video' && track.poster &&
|
|
147
|
+
(mediaType === 'video' || mediaType === 'hls')) {
|
|
148
|
+
mediaElement.setAttribute('poster', track.poster);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// For external renderers (YouTube, Vimeo, SoundCloud, HLS), don't add source
|
|
152
|
+
// The renderer will handle the source directly
|
|
153
|
+
const isExternalRenderer = ['youtube', 'vimeo', 'soundcloud', 'hls'].includes(mediaType);
|
|
154
|
+
|
|
155
|
+
if (!isExternalRenderer) {
|
|
156
|
+
// Add source for HTML5 media
|
|
157
|
+
const source = document.createElement('source');
|
|
158
|
+
source.src = track.src;
|
|
159
|
+
if (track.type) {
|
|
160
|
+
source.type = track.type;
|
|
161
|
+
}
|
|
162
|
+
mediaElement.appendChild(source);
|
|
163
|
+
|
|
164
|
+
// Add tracks (captions, chapters, etc.)
|
|
165
|
+
if (track.tracks && track.tracks.length > 0) {
|
|
166
|
+
track.tracks.forEach(trackConfig => {
|
|
167
|
+
const trackEl = document.createElement('track');
|
|
168
|
+
trackEl.src = trackConfig.src;
|
|
169
|
+
trackEl.kind = trackConfig.kind || 'captions';
|
|
170
|
+
trackEl.srclang = trackConfig.srclang || 'en';
|
|
171
|
+
trackEl.label = trackConfig.label || trackConfig.srclang;
|
|
172
|
+
if (trackConfig.default) {
|
|
173
|
+
trackEl.default = true;
|
|
174
|
+
}
|
|
175
|
+
mediaElement.appendChild(trackEl);
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
this.hostElement.appendChild(mediaElement);
|
|
181
|
+
|
|
182
|
+
// Create new player with the media element
|
|
183
|
+
// Pass the source for external renderers via options
|
|
184
|
+
const playerOptions = {
|
|
185
|
+
mediaType: elementType,
|
|
186
|
+
poster: track.poster,
|
|
187
|
+
audioDescriptionSrc: track.audioDescriptionSrc || null,
|
|
188
|
+
audioDescriptionDuration: track.audioDescriptionDuration || null,
|
|
189
|
+
signLanguageSrc: track.signLanguageSrc || null
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
this.player = new this.PlayerClass(mediaElement, playerOptions);
|
|
193
|
+
|
|
194
|
+
// Re-register playlist manager
|
|
195
|
+
this.player.playlistManager = this;
|
|
196
|
+
|
|
197
|
+
// Wait for player to be ready
|
|
198
|
+
await new Promise(resolve => {
|
|
199
|
+
this.player.on('ready', resolve);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// Re-attach event listeners
|
|
203
|
+
this.player.on('ended', this.handleTrackEnd);
|
|
204
|
+
this.player.on('error', this.handleTrackError);
|
|
205
|
+
|
|
206
|
+
// Re-attach all playlist UI elements to the new player's container
|
|
207
|
+
if (this.player.container) {
|
|
208
|
+
// Track artwork goes before video wrapper
|
|
209
|
+
if (this.trackArtworkElement) {
|
|
210
|
+
const videoWrapper = this.player.container.querySelector('.vidply-video-wrapper');
|
|
211
|
+
if (videoWrapper) {
|
|
212
|
+
this.player.container.insertBefore(this.trackArtworkElement, videoWrapper);
|
|
213
|
+
} else {
|
|
214
|
+
this.player.container.appendChild(this.trackArtworkElement);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
// Track info
|
|
218
|
+
if (this.trackInfoElement) {
|
|
219
|
+
this.player.container.appendChild(this.trackInfoElement);
|
|
220
|
+
}
|
|
221
|
+
// Navigation feedback (screen reader only)
|
|
222
|
+
if (this.navigationFeedback) {
|
|
223
|
+
this.player.container.appendChild(this.navigationFeedback);
|
|
224
|
+
}
|
|
225
|
+
// Playlist panel
|
|
226
|
+
if (this.playlistPanel) {
|
|
227
|
+
this.player.container.appendChild(this.playlistPanel);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Update container reference
|
|
232
|
+
this.container = this.player.container;
|
|
233
|
+
|
|
234
|
+
// Update controls (adds playlist prev/next buttons)
|
|
235
|
+
this.updatePlayerControls();
|
|
236
|
+
|
|
237
|
+
// Restore tracks data (we kept it during recreation)
|
|
238
|
+
this.tracks = savedTracks;
|
|
239
|
+
this.currentIndex = savedIndex;
|
|
240
|
+
|
|
241
|
+
// Update playlist UI to reflect current state
|
|
242
|
+
this.updatePlaylistUI();
|
|
243
|
+
|
|
244
|
+
// Restore playlist panel visibility
|
|
245
|
+
this.isPanelVisible = wasVisible;
|
|
246
|
+
if (this.playlistPanel) {
|
|
247
|
+
this.playlistPanel.style.display = wasVisible ? '' : 'none';
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// For external renderers, load the track via player.load()
|
|
251
|
+
// For HTML5, the source is already set on the element
|
|
252
|
+
if (isExternalRenderer) {
|
|
253
|
+
this.player.load({
|
|
254
|
+
src: track.src,
|
|
255
|
+
type: track.type,
|
|
256
|
+
poster: track.poster,
|
|
257
|
+
tracks: track.tracks || [],
|
|
258
|
+
audioDescriptionSrc: track.audioDescriptionSrc || null,
|
|
259
|
+
signLanguageSrc: track.signLanguageSrc || null
|
|
260
|
+
});
|
|
261
|
+
} else {
|
|
262
|
+
// For HTML5 media, also load to set up accessibility features
|
|
263
|
+
this.player.load({
|
|
264
|
+
src: track.src,
|
|
265
|
+
type: track.type,
|
|
266
|
+
poster: track.poster,
|
|
267
|
+
tracks: track.tracks || [],
|
|
268
|
+
audioDescriptionSrc: track.audioDescriptionSrc || null,
|
|
269
|
+
signLanguageSrc: track.signLanguageSrc || null
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Auto-play if requested
|
|
274
|
+
if (autoPlay) {
|
|
275
|
+
setTimeout(() => {
|
|
276
|
+
this.player.play();
|
|
277
|
+
}, 100);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return true;
|
|
281
|
+
}
|
|
282
|
+
|
|
63
283
|
init() {
|
|
64
284
|
// Listen for track end
|
|
65
285
|
this.player.on('ended', this.handleTrackEnd);
|
|
@@ -218,7 +438,7 @@ export class PlaylistManager {
|
|
|
218
438
|
* Load a track without playing
|
|
219
439
|
* @param {number} index - Track index
|
|
220
440
|
*/
|
|
221
|
-
loadTrack(index) {
|
|
441
|
+
async loadTrack(index) {
|
|
222
442
|
if (index < 0 || index >= this.tracks.length) {
|
|
223
443
|
console.warn('VidPly Playlist: Invalid track index', index);
|
|
224
444
|
return;
|
|
@@ -232,7 +452,36 @@ export class PlaylistManager {
|
|
|
232
452
|
// Update current index
|
|
233
453
|
this.currentIndex = index;
|
|
234
454
|
|
|
235
|
-
//
|
|
455
|
+
// Check if we should recreate the player for this track type
|
|
456
|
+
if (this.options.recreatePlayers && this.hostElement && this.PlayerClass) {
|
|
457
|
+
const currentMediaType = this.player ?
|
|
458
|
+
(this.player.element.tagName === 'AUDIO' ? 'audio' : 'video') : null;
|
|
459
|
+
const newMediaType = this.getTrackMediaType(track);
|
|
460
|
+
const newElementType = (newMediaType === 'audio' || newMediaType === 'soundcloud') ? 'audio' : 'video';
|
|
461
|
+
|
|
462
|
+
// Recreate if element type is different
|
|
463
|
+
if (currentMediaType !== newElementType) {
|
|
464
|
+
await this.recreatePlayerForTrack(track, false);
|
|
465
|
+
// Update UI after recreation
|
|
466
|
+
this.updateTrackInfo(track);
|
|
467
|
+
this.updatePlaylistUI();
|
|
468
|
+
|
|
469
|
+
// Emit event
|
|
470
|
+
this.player.emit('playlisttrackchange', {
|
|
471
|
+
index: index,
|
|
472
|
+
item: track,
|
|
473
|
+
total: this.tracks.length
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
// Clear guard flag
|
|
477
|
+
setTimeout(() => {
|
|
478
|
+
this.isChangingTrack = false;
|
|
479
|
+
}, 150);
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// Load track into player (normal path)
|
|
236
485
|
this.player.load({
|
|
237
486
|
src: track.src,
|
|
238
487
|
type: track.type,
|
|
@@ -264,7 +513,7 @@ export class PlaylistManager {
|
|
|
264
513
|
* @param {number} index - Track index
|
|
265
514
|
* @param {boolean} userInitiated - Whether this was triggered by user action (default: false)
|
|
266
515
|
*/
|
|
267
|
-
play(index, userInitiated = false) {
|
|
516
|
+
async play(index, userInitiated = false) {
|
|
268
517
|
if (index < 0 || index >= this.tracks.length) {
|
|
269
518
|
console.warn('VidPly Playlist: Invalid track index', index);
|
|
270
519
|
return;
|
|
@@ -278,7 +527,36 @@ export class PlaylistManager {
|
|
|
278
527
|
// Update current index
|
|
279
528
|
this.currentIndex = index;
|
|
280
529
|
|
|
281
|
-
//
|
|
530
|
+
// Check if we should recreate the player for this track type
|
|
531
|
+
if (this.options.recreatePlayers && this.hostElement && this.PlayerClass) {
|
|
532
|
+
const currentMediaType = this.player ?
|
|
533
|
+
(this.player.element.tagName === 'AUDIO' ? 'audio' : 'video') : null;
|
|
534
|
+
const newMediaType = this.getTrackMediaType(track);
|
|
535
|
+
const newElementType = (newMediaType === 'audio' || newMediaType === 'soundcloud') ? 'audio' : 'video';
|
|
536
|
+
|
|
537
|
+
// Recreate if element type is different
|
|
538
|
+
if (currentMediaType !== newElementType) {
|
|
539
|
+
await this.recreatePlayerForTrack(track, true); // true = autoPlay
|
|
540
|
+
// Update UI after recreation
|
|
541
|
+
this.updateTrackInfo(track);
|
|
542
|
+
this.updatePlaylistUI();
|
|
543
|
+
|
|
544
|
+
// Emit event
|
|
545
|
+
this.player.emit('playlisttrackchange', {
|
|
546
|
+
index: index,
|
|
547
|
+
item: track,
|
|
548
|
+
total: this.tracks.length
|
|
549
|
+
});
|
|
550
|
+
|
|
551
|
+
// Clear guard flag
|
|
552
|
+
setTimeout(() => {
|
|
553
|
+
this.isChangingTrack = false;
|
|
554
|
+
}, 150);
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// Load track into player (normal path)
|
|
282
560
|
this.player.load({
|
|
283
561
|
src: track.src,
|
|
284
562
|
type: track.type,
|
|
@@ -358,10 +636,40 @@ export class PlaylistManager {
|
|
|
358
636
|
}
|
|
359
637
|
}
|
|
360
638
|
|
|
639
|
+
/**
|
|
640
|
+
* Check if a source URL requires an external renderer
|
|
641
|
+
* @param {string} src - Source URL
|
|
642
|
+
* @returns {boolean}
|
|
643
|
+
*/
|
|
644
|
+
isExternalRendererUrl(src) {
|
|
645
|
+
if (!src) return false;
|
|
646
|
+
return src.includes('youtube.com') ||
|
|
647
|
+
src.includes('youtu.be') ||
|
|
648
|
+
src.includes('vimeo.com') ||
|
|
649
|
+
src.includes('soundcloud.com') ||
|
|
650
|
+
src.includes('api.soundcloud.com') ||
|
|
651
|
+
src.includes('.m3u8');
|
|
652
|
+
}
|
|
653
|
+
|
|
361
654
|
/**
|
|
362
655
|
* Handle track error
|
|
363
656
|
*/
|
|
364
657
|
handleTrackError(e) {
|
|
658
|
+
// Don't auto-advance for external renderer tracks
|
|
659
|
+
// External renderers (YouTube, Vimeo, SoundCloud, HLS) may trigger HTML5 errors
|
|
660
|
+
// that should be ignored since the external renderer handles playback
|
|
661
|
+
const currentTrack = this.getCurrentTrack();
|
|
662
|
+
if (currentTrack && currentTrack.src && this.isExternalRendererUrl(currentTrack.src)) {
|
|
663
|
+
// Silently ignore errors for external renderer tracks
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
// Don't auto-advance if we're in the process of changing tracks
|
|
668
|
+
// This prevents a cascade of next() calls when switching between renderer types
|
|
669
|
+
if (this.isChangingTrack) {
|
|
670
|
+
return;
|
|
671
|
+
}
|
|
672
|
+
|
|
365
673
|
console.error('VidPly Playlist: Track error', e);
|
|
366
674
|
|
|
367
675
|
// Try next track
|
|
@@ -92,15 +92,18 @@ export class HLSRenderer {
|
|
|
92
92
|
// Attach media element
|
|
93
93
|
this.hls.attachMedia(this.media);
|
|
94
94
|
|
|
95
|
-
// Load source -
|
|
96
|
-
let src;
|
|
97
|
-
|
|
98
|
-
if (
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
95
|
+
// Load source - use currentSource for external renderers, or get from attribute
|
|
96
|
+
let src = this.player.currentSource;
|
|
97
|
+
|
|
98
|
+
if (!src) {
|
|
99
|
+
const sourceElement = this.player.element.querySelector('source');
|
|
100
|
+
if (sourceElement) {
|
|
101
|
+
// Use getAttribute to get the original URL, not the blob-converted one
|
|
102
|
+
src = sourceElement.getAttribute('src');
|
|
103
|
+
} else {
|
|
104
|
+
// Fallback to element's src attribute
|
|
105
|
+
src = this.player.element.getAttribute('src') || this.player.element.src;
|
|
106
|
+
}
|
|
104
107
|
}
|
|
105
108
|
|
|
106
109
|
this.player.log(`Loading HLS source: ${src}`, 'log');
|
|
@@ -130,6 +133,11 @@ export class HLSRenderer {
|
|
|
130
133
|
this.hls.on(window.Hls.Events.MANIFEST_PARSED, (event, data) => {
|
|
131
134
|
this.player.log('HLS manifest loaded, found ' + data.levels.length + ' quality levels');
|
|
132
135
|
this.player.emit('hlsmanifestparsed', data);
|
|
136
|
+
|
|
137
|
+
// Show VidPly controls (remove external controls class if present)
|
|
138
|
+
if (this.player.container) {
|
|
139
|
+
this.player.container.classList.remove('vidply-external-controls');
|
|
140
|
+
}
|
|
133
141
|
});
|
|
134
142
|
|
|
135
143
|
this.hls.on(window.Hls.Events.LEVEL_SWITCHED, (event, data) => {
|
|
@@ -20,6 +20,11 @@ export class HTML5Renderer {
|
|
|
20
20
|
|
|
21
21
|
// Load media
|
|
22
22
|
this.media.load();
|
|
23
|
+
|
|
24
|
+
// Show VidPly controls (remove external controls class if present)
|
|
25
|
+
if (this.player.container) {
|
|
26
|
+
this.player.container.classList.remove('vidply-external-controls');
|
|
27
|
+
}
|
|
23
28
|
}
|
|
24
29
|
|
|
25
30
|
attachEvents() {
|