unified-video-framework 1.4.249 → 1.4.251
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.
|
@@ -1115,11 +1115,20 @@ export class WebPlayer extends BasePlayer {
|
|
|
1115
1115
|
if (this.video && metadata.thumbnail) {
|
|
1116
1116
|
this.video.poster = metadata.thumbnail;
|
|
1117
1117
|
}
|
|
1118
|
+
|
|
1119
|
+
// Update metadata UI immediately with YouTube title and thumbnail
|
|
1120
|
+
this.updateMetadataUI();
|
|
1118
1121
|
|
|
1119
1122
|
// Create YouTube iframe player with custom controls integration
|
|
1120
1123
|
await this.createYouTubePlayer(videoId);
|
|
1121
1124
|
|
|
1125
|
+
// Force another metadata update after player creation
|
|
1126
|
+
setTimeout(() => {
|
|
1127
|
+
this.updateMetadataUI();
|
|
1128
|
+
}, 1000);
|
|
1129
|
+
|
|
1122
1130
|
this.debugLog('✅ YouTube video loaded successfully');
|
|
1131
|
+
this.debugLog('YouTube video title:', metadata.title);
|
|
1123
1132
|
} catch (error) {
|
|
1124
1133
|
this.debugError('Failed to load YouTube video:', error);
|
|
1125
1134
|
throw new Error(`YouTube video loading failed: ${error}`);
|
|
@@ -1245,6 +1254,12 @@ export class WebPlayer extends BasePlayer {
|
|
|
1245
1254
|
|
|
1246
1255
|
// Extract available YouTube qualities
|
|
1247
1256
|
this.extractYouTubeAvailableQualities();
|
|
1257
|
+
|
|
1258
|
+
// Update metadata UI and settings after player is ready
|
|
1259
|
+
setTimeout(() => {
|
|
1260
|
+
this.updateMetadataUI();
|
|
1261
|
+
this.updateSettingsMenu();
|
|
1262
|
+
}, 500);
|
|
1248
1263
|
}
|
|
1249
1264
|
|
|
1250
1265
|
// Start time tracking
|
|
@@ -1366,15 +1381,15 @@ export class WebPlayer extends BasePlayer {
|
|
|
1366
1381
|
|
|
1367
1382
|
this.youtubeAvailableQualities = [];
|
|
1368
1383
|
availableQualityLevels.forEach((qualityLevel: string) => {
|
|
1384
|
+
// Skip 'auto' from YouTube API - we'll add it explicitly
|
|
1385
|
+
if (qualityLevel === 'auto') return;
|
|
1369
1386
|
if (qualityMap[qualityLevel]) {
|
|
1370
1387
|
this.youtubeAvailableQualities.push(qualityMap[qualityLevel]);
|
|
1371
1388
|
}
|
|
1372
1389
|
});
|
|
1373
1390
|
|
|
1374
|
-
//
|
|
1375
|
-
|
|
1376
|
-
this.youtubeAvailableQualities.unshift({ label: 'Auto', value: 'auto', height: 0 });
|
|
1377
|
-
}
|
|
1391
|
+
// Always add auto quality option as the first item (exactly once)
|
|
1392
|
+
this.youtubeAvailableQualities.unshift({ label: 'Auto', value: 'auto', height: 0 });
|
|
1378
1393
|
|
|
1379
1394
|
this.debugLog('Mapped YouTube qualities:', this.youtubeAvailableQualities);
|
|
1380
1395
|
|
|
@@ -1482,16 +1497,18 @@ export class WebPlayer extends BasePlayer {
|
|
|
1482
1497
|
|
|
1483
1498
|
const percent = (currentTime / duration) * 100;
|
|
1484
1499
|
|
|
1485
|
-
// Update progress filled
|
|
1500
|
+
// Update progress filled (only if not dragging)
|
|
1486
1501
|
const progressFilled = document.getElementById('uvf-progress-filled') as HTMLElement;
|
|
1487
1502
|
if (progressFilled && !this.isDragging) {
|
|
1488
1503
|
progressFilled.style.width = percent + '%';
|
|
1489
1504
|
}
|
|
1490
1505
|
|
|
1491
|
-
// Update progress handle
|
|
1506
|
+
// Update progress handle (only if not dragging)
|
|
1492
1507
|
const progressHandle = document.getElementById('uvf-progress-handle') as HTMLElement;
|
|
1493
1508
|
if (progressHandle && !this.isDragging) {
|
|
1494
1509
|
progressHandle.style.left = percent + '%';
|
|
1510
|
+
// Remove dragging class if it was set
|
|
1511
|
+
progressHandle.classList.remove('dragging');
|
|
1495
1512
|
}
|
|
1496
1513
|
|
|
1497
1514
|
// Update buffered progress
|
|
@@ -1500,8 +1517,13 @@ export class WebPlayer extends BasePlayer {
|
|
|
1500
1517
|
progressBuffered.style.width = buffered + '%';
|
|
1501
1518
|
}
|
|
1502
1519
|
|
|
1503
|
-
// Update time display
|
|
1504
|
-
|
|
1520
|
+
// Update time display with YouTube-specific times
|
|
1521
|
+
const timeDisplay = document.getElementById('uvf-time-display');
|
|
1522
|
+
if (timeDisplay) {
|
|
1523
|
+
const currentTimeStr = this.formatTime(currentTime);
|
|
1524
|
+
const durationStr = this.formatTime(duration);
|
|
1525
|
+
timeDisplay.textContent = `${currentTimeStr} / ${durationStr}`;
|
|
1526
|
+
}
|
|
1505
1527
|
}
|
|
1506
1528
|
|
|
1507
1529
|
|
|
@@ -8124,12 +8146,27 @@ export class WebPlayer extends BasePlayer {
|
|
|
8124
8146
|
const progressBar = document.querySelector('.uvf-progress-bar') as HTMLElement;
|
|
8125
8147
|
const progressFilled = document.getElementById('uvf-progress-filled') as HTMLElement;
|
|
8126
8148
|
const progressHandle = document.getElementById('uvf-progress-handle') as HTMLElement;
|
|
8127
|
-
if (!progressBar
|
|
8149
|
+
if (!progressBar) return;
|
|
8150
|
+
|
|
8151
|
+
// Get duration from appropriate source
|
|
8152
|
+
let duration = 0;
|
|
8153
|
+
if (this.youtubePlayer && this.youtubePlayerReady) {
|
|
8154
|
+
try {
|
|
8155
|
+
duration = this.youtubePlayer.getDuration() || 0;
|
|
8156
|
+
} catch (error) {
|
|
8157
|
+
this.debugWarn('Error getting YouTube duration for seeking:', error);
|
|
8158
|
+
return;
|
|
8159
|
+
}
|
|
8160
|
+
} else if (this.video) {
|
|
8161
|
+
duration = this.video.duration;
|
|
8162
|
+
} else {
|
|
8163
|
+
this.debugWarn('No video source available for seeking');
|
|
8164
|
+
return;
|
|
8165
|
+
}
|
|
8128
8166
|
|
|
8129
|
-
const duration = this.video.duration;
|
|
8130
8167
|
// Validate duration before calculating seek time
|
|
8131
8168
|
if (!isFinite(duration) || isNaN(duration) || duration <= 0) {
|
|
8132
|
-
this.debugWarn('Invalid video duration, cannot seek via progress bar');
|
|
8169
|
+
this.debugWarn('Invalid video duration, cannot seek via progress bar:', duration);
|
|
8133
8170
|
return;
|
|
8134
8171
|
}
|
|
8135
8172
|
|
|
@@ -8144,21 +8181,24 @@ export class WebPlayer extends BasePlayer {
|
|
|
8144
8181
|
return;
|
|
8145
8182
|
}
|
|
8146
8183
|
|
|
8184
|
+
this.debugLog('Seeking to position:', time, 'seconds (', Math.round(percent), '%)');
|
|
8185
|
+
|
|
8147
8186
|
// Update UI immediately for responsive feedback
|
|
8148
|
-
if (progressFilled) {
|
|
8187
|
+
if (progressFilled && !this.isDragging) {
|
|
8149
8188
|
progressFilled.style.width = percent + '%';
|
|
8150
8189
|
}
|
|
8151
|
-
if (progressHandle) {
|
|
8190
|
+
if (progressHandle && !this.isDragging) {
|
|
8152
8191
|
progressHandle.style.left = percent + '%';
|
|
8153
|
-
|
|
8154
|
-
if (this.isDragging) {
|
|
8155
|
-
progressHandle.classList.add('dragging');
|
|
8156
|
-
} else {
|
|
8157
|
-
progressHandle.classList.remove('dragging');
|
|
8158
|
-
}
|
|
8192
|
+
progressHandle.classList.add('dragging');
|
|
8159
8193
|
}
|
|
8160
8194
|
|
|
8195
|
+
// Perform the actual seek
|
|
8161
8196
|
this.seek(time);
|
|
8197
|
+
|
|
8198
|
+
// For YouTube, provide immediate visual feedback since API might be delayed
|
|
8199
|
+
if (this.youtubePlayer && this.youtubePlayerReady) {
|
|
8200
|
+
this.emit('onSeeking');
|
|
8201
|
+
}
|
|
8162
8202
|
}
|
|
8163
8203
|
|
|
8164
8204
|
private formatTime(seconds: number): string {
|
|
@@ -9192,6 +9232,13 @@ export class WebPlayer extends BasePlayer {
|
|
|
9192
9232
|
option.classList.add('active');
|
|
9193
9233
|
}
|
|
9194
9234
|
});
|
|
9235
|
+
|
|
9236
|
+
// Update quality badge
|
|
9237
|
+
const qualityBadge = document.getElementById('uvf-quality-badge');
|
|
9238
|
+
if (qualityBadge) {
|
|
9239
|
+
const qualityOption = this.youtubeAvailableQualities.find(q => q.value === quality);
|
|
9240
|
+
qualityBadge.textContent = qualityOption ? qualityOption.label : 'AUTO';
|
|
9241
|
+
}
|
|
9195
9242
|
return;
|
|
9196
9243
|
}
|
|
9197
9244
|
|
|
@@ -9588,17 +9635,21 @@ export class WebPlayer extends BasePlayer {
|
|
|
9588
9635
|
* Detect available video qualities from different sources
|
|
9589
9636
|
*/
|
|
9590
9637
|
private detectAvailableQualities(): void {
|
|
9591
|
-
|
|
9638
|
+
// Check if we're using YouTube and have detected qualities
|
|
9639
|
+
const isYouTube = this.youtubePlayer && this.youtubePlayerReady && this.youtubeAvailableQualities.length > 0;
|
|
9640
|
+
this.availableQualities = [];
|
|
9592
9641
|
let detectedQualities: Array<{ value: string; label: string; height?: number }> = [];
|
|
9593
9642
|
|
|
9594
9643
|
// YouTube qualities
|
|
9595
|
-
if (
|
|
9644
|
+
if (isYouTube) {
|
|
9596
9645
|
detectedQualities = this.youtubeAvailableQualities.map(q => ({
|
|
9597
9646
|
value: q.value,
|
|
9598
9647
|
label: q.label,
|
|
9599
9648
|
height: q.height
|
|
9600
9649
|
}));
|
|
9601
9650
|
this.debugLog('Using YouTube qualities:', detectedQualities);
|
|
9651
|
+
this.availableQualities = detectedQualities;
|
|
9652
|
+
return; // Early return for YouTube
|
|
9602
9653
|
} else if (this.hls && this.hls.levels) {
|
|
9603
9654
|
// HLS qualities
|
|
9604
9655
|
this.hls.levels.forEach((level: any, index: number) => {
|