unified-video-framework 1.4.252 → 1.4.254

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.
@@ -1280,6 +1280,12 @@ export class WebPlayer extends BasePlayer {
1280
1280
  this.state.isPaused = false;
1281
1281
  this.state.isBuffering = false;
1282
1282
  this.updateYouTubeUI('playing');
1283
+
1284
+ // Extract qualities when video starts playing
1285
+ setTimeout(() => {
1286
+ this.extractYouTubeAvailableQualities();
1287
+ }, 1000);
1288
+
1283
1289
  this.emit('onPlay');
1284
1290
  break;
1285
1291
 
@@ -1294,6 +1300,12 @@ export class WebPlayer extends BasePlayer {
1294
1300
  case window.YT.PlayerState.BUFFERING:
1295
1301
  this.state.isBuffering = true;
1296
1302
  this.updateYouTubeUI('buffering');
1303
+
1304
+ // Try to extract qualities during buffering as well
1305
+ setTimeout(() => {
1306
+ this.extractYouTubeAvailableQualities();
1307
+ }, 500);
1308
+
1297
1309
  this.emit('onBuffering', true);
1298
1310
  break;
1299
1311
 
@@ -1425,17 +1437,33 @@ export class WebPlayer extends BasePlayer {
1425
1437
  private youtubeCurrentQuality: any = null;
1426
1438
 
1427
1439
  /**
1428
- * Extract available YouTube video qualities
1440
+ * Extract available YouTube video qualities with retry logic
1429
1441
  */
1430
- private extractYouTubeAvailableQualities(): void {
1431
- if (!this.youtubePlayer) return;
1442
+ private extractYouTubeAvailableQualities(retryCount: number = 0): void {
1443
+ if (!this.youtubePlayer || !this.youtubePlayerReady) {
1444
+ this.debugLog('YouTube player not ready for quality extraction');
1445
+ return;
1446
+ }
1432
1447
 
1433
1448
  try {
1434
1449
  const availableQualityLevels = this.youtubePlayer.getAvailableQualityLevels();
1435
- this.debugLog('YouTube available quality levels:', availableQualityLevels);
1450
+ this.debugLog('🔍 YouTube quality detection attempt', retryCount + 1, '- Found levels:', availableQualityLevels);
1451
+ this.debugLog('🔍 YouTube player state:', this.youtubePlayer.getPlayerState());
1452
+ this.debugLog('🔍 Current YouTube quality:', this.youtubePlayer.getPlaybackQuality());
1453
+
1454
+ // If no qualities detected and we haven't retried too much, retry after a delay
1455
+ if ((!availableQualityLevels || availableQualityLevels.length === 0 || (availableQualityLevels.length === 1 && availableQualityLevels[0] === 'auto')) && retryCount < 5) {
1456
+ this.debugLog('No meaningful qualities detected, retrying in', (retryCount + 1) * 1000, 'ms...');
1457
+ setTimeout(() => {
1458
+ this.extractYouTubeAvailableQualities(retryCount + 1);
1459
+ }, (retryCount + 1) * 1000);
1460
+ return;
1461
+ }
1436
1462
 
1437
1463
  // Map YouTube quality levels to standard labels
1438
1464
  const qualityMap: Record<string, any> = {
1465
+ 'hd2160': { label: '4K', value: 'hd2160', height: 2160 },
1466
+ 'hd1440': { label: '1440p', value: 'hd1440', height: 1440 },
1439
1467
  'hd1080': { label: '1080p', value: 'hd1080', height: 1080 },
1440
1468
  'hd720': { label: '720p', value: 'hd720', height: 720 },
1441
1469
  'large': { label: '480p', value: 'large', height: 480 },
@@ -1446,18 +1474,25 @@ export class WebPlayer extends BasePlayer {
1446
1474
  };
1447
1475
 
1448
1476
  this.youtubeAvailableQualities = [];
1449
- availableQualityLevels.forEach((qualityLevel: string) => {
1450
- // Skip 'auto' from YouTube API - we'll add it explicitly
1451
- if (qualityLevel === 'auto') return;
1452
- if (qualityMap[qualityLevel]) {
1453
- this.youtubeAvailableQualities.push(qualityMap[qualityLevel]);
1454
- }
1455
- });
1456
1477
 
1457
- // Always add auto quality option as the first item (exactly once)
1458
- this.youtubeAvailableQualities.unshift({ label: 'Auto', value: 'auto', height: 0 });
1478
+ // Always add auto quality option first
1479
+ this.youtubeAvailableQualities.push({ label: 'Auto', value: 'auto', height: 0 });
1459
1480
 
1460
- this.debugLog('Mapped YouTube qualities:', this.youtubeAvailableQualities);
1481
+ // Add detected qualities, filtering out 'auto' since we already added it
1482
+ if (availableQualityLevels && availableQualityLevels.length > 0) {
1483
+ availableQualityLevels.forEach((qualityLevel: string) => {
1484
+ if (qualityLevel !== 'auto' && qualityMap[qualityLevel]) {
1485
+ this.youtubeAvailableQualities.push(qualityMap[qualityLevel]);
1486
+ }
1487
+ });
1488
+
1489
+ // Sort qualities by height (descending, excluding auto)
1490
+ const autoQuality = this.youtubeAvailableQualities.shift(); // Remove auto temporarily
1491
+ this.youtubeAvailableQualities.sort((a, b) => (b.height || 0) - (a.height || 0));
1492
+ if (autoQuality) this.youtubeAvailableQualities.unshift(autoQuality); // Add auto back at beginning
1493
+ }
1494
+
1495
+ this.debugLog('✅ Successfully mapped YouTube qualities:', this.youtubeAvailableQualities);
1461
1496
 
1462
1497
  // Get current quality
1463
1498
  try {
@@ -1469,14 +1504,28 @@ export class WebPlayer extends BasePlayer {
1469
1504
  this.youtubeCurrentQuality = qualityMap['auto'];
1470
1505
  }
1471
1506
 
1507
+ // Update detected qualities to include YouTube qualities
1508
+ this.detectAvailableQualities();
1509
+
1510
+ this.debugLog('🚀 YouTube qualities successfully detected! Available qualities now:', this.availableQualities.length);
1511
+
1472
1512
  // Update quality badge with current YouTube quality
1473
1513
  this.updateQualityBadge();
1474
1514
 
1475
- // Update settings menu to show YouTube qualities
1476
- this.updateSettingsMenu();
1515
+ // Force settings menu refresh with new qualities
1516
+ setTimeout(() => {
1517
+ this.debugLog('🔄 Force refreshing settings menu with YouTube qualities');
1518
+ this.updateSettingsMenu();
1519
+ }, 100);
1477
1520
 
1478
1521
  } catch (error) {
1479
1522
  this.debugWarn('Could not extract YouTube qualities:', error);
1523
+ // Retry if we haven't tried too many times
1524
+ if (retryCount < 3) {
1525
+ setTimeout(() => {
1526
+ this.extractYouTubeAvailableQualities(retryCount + 1);
1527
+ }, 2000);
1528
+ }
1480
1529
  }
1481
1530
  }
1482
1531
 
@@ -1488,6 +1537,8 @@ export class WebPlayer extends BasePlayer {
1488
1537
 
1489
1538
  try {
1490
1539
  const qualityMap: Record<string, any> = {
1540
+ 'hd2160': { label: '4K', value: 'hd2160', height: 2160 },
1541
+ 'hd1440': { label: '1440p', value: 'hd1440', height: 1440 },
1491
1542
  'hd1080': { label: '1080p', value: 'hd1080', height: 1080 },
1492
1543
  'hd720': { label: '720p', value: 'hd720', height: 720 },
1493
1544
  'large': { label: '480p', value: 'large', height: 480 },
@@ -1563,6 +1614,8 @@ export class WebPlayer extends BasePlayer {
1563
1614
  clearInterval(this.youtubeTimeTrackingInterval);
1564
1615
  }
1565
1616
 
1617
+ let qualityCheckCounter = 0;
1618
+
1566
1619
  this.youtubeTimeTrackingInterval = setInterval(() => {
1567
1620
  if (this.youtubePlayer && this.youtubePlayerReady) {
1568
1621
  try {
@@ -1574,6 +1627,14 @@ export class WebPlayer extends BasePlayer {
1574
1627
  this.state.duration = duration || 0;
1575
1628
  this.state.bufferedPercentage = buffered || 0;
1576
1629
 
1630
+ // Check for qualities periodically (every 10 seconds) if we don't have them yet
1631
+ qualityCheckCounter++;
1632
+ if (qualityCheckCounter >= 40 && this.youtubeAvailableQualities.length <= 1) { // 40 * 250ms = 10s
1633
+ this.debugLog('Periodic YouTube quality check triggered');
1634
+ this.extractYouTubeAvailableQualities();
1635
+ qualityCheckCounter = 0; // Reset counter
1636
+ }
1637
+
1577
1638
  // Update UI progress bar
1578
1639
  this.updateYouTubeProgressBar(currentTime, duration, buffered);
1579
1640
 
@@ -9648,6 +9709,8 @@ export class WebPlayer extends BasePlayer {
9648
9709
 
9649
9710
  // Quality Accordion Section (only if enabled in config and qualities detected)
9650
9711
  if (this.settingsConfig.quality && this.availableQualities.length > 0) {
9712
+ this.debugLog('🎛️ Building quality menu with', this.availableQualities.length, 'qualities:', this.availableQualities.map(q => q.label));
9713
+
9651
9714
  // For YouTube, use youtubeCurrentQuality; otherwise use currentQuality
9652
9715
  const qualityForDisplay = this.youtubePlayer && this.youtubePlayerReady && this.youtubeCurrentQuality
9653
9716
  ? this.youtubeCurrentQuality.value
@@ -9655,6 +9718,8 @@ export class WebPlayer extends BasePlayer {
9655
9718
  const currentQuality = this.availableQualities.find(q => q.value === qualityForDisplay);
9656
9719
  const currentQualityLabel = currentQuality ? currentQuality.label : 'Auto';
9657
9720
 
9721
+ this.debugLog('🎛️ Current quality for display:', qualityForDisplay, '(', currentQualityLabel, ')');
9722
+
9658
9723
  menuHTML += `
9659
9724
  <div class="uvf-accordion-item">
9660
9725
  <div class="uvf-accordion-header" data-section="quality">