unified-video-framework 1.4.238 → 1.4.240
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.
|
@@ -149,6 +149,7 @@ export class WebPlayer extends BasePlayer {
|
|
|
149
149
|
private fallbackErrors: Array<{ url: string; error: any }> = [];
|
|
150
150
|
private isLoadingFallback: boolean = false;
|
|
151
151
|
private currentRetryAttempt: number = 0;
|
|
152
|
+
private lastFailedUrl: string = ''; // Track last failed URL to avoid duplicate error handling
|
|
152
153
|
|
|
153
154
|
// Debug logging helper
|
|
154
155
|
private debugLog(message: string, ...args: any[]): void {
|
|
@@ -458,9 +459,17 @@ export class WebPlayer extends BasePlayer {
|
|
|
458
459
|
|
|
459
460
|
this.video.addEventListener('canplay', () => {
|
|
460
461
|
this.debugLog('📡 canplay event fired');
|
|
462
|
+
|
|
463
|
+
// Reset fallback tracking on successful load
|
|
464
|
+
if (this.isLoadingFallback) {
|
|
465
|
+
this.debugLog('✅ Fallback source loaded successfully!');
|
|
466
|
+
this.isLoadingFallback = false;
|
|
467
|
+
this.lastFailedUrl = '';
|
|
468
|
+
}
|
|
469
|
+
|
|
461
470
|
this.setBuffering(false);
|
|
462
471
|
this.emit('onReady');
|
|
463
|
-
|
|
472
|
+
|
|
464
473
|
// Update time display when video is ready to play
|
|
465
474
|
this.updateTimeDisplay();
|
|
466
475
|
|
|
@@ -514,28 +523,51 @@ export class WebPlayer extends BasePlayer {
|
|
|
514
523
|
});
|
|
515
524
|
|
|
516
525
|
this.video.addEventListener('error', async (e) => {
|
|
517
|
-
if (!this.video) return;
|
|
526
|
+
if (!this.video || !this.video.src) return;
|
|
527
|
+
|
|
518
528
|
const error = this.video.error;
|
|
519
529
|
if (error) {
|
|
530
|
+
const currentSrc = this.video.src || this.video.currentSrc || '';
|
|
531
|
+
|
|
532
|
+
// Avoid processing the same error multiple times
|
|
533
|
+
if (this.lastFailedUrl === currentSrc && this.isLoadingFallback) {
|
|
534
|
+
this.debugLog(`⚠️ Duplicate error for same URL while loading fallback, ignoring: ${currentSrc}`);
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
this.lastFailedUrl = currentSrc;
|
|
520
539
|
this.debugLog(`Video error detected (code: ${error.code}):`, error.message);
|
|
540
|
+
this.debugLog(`Failed source: ${currentSrc}`);
|
|
541
|
+
this.debugLog(`Fallback check - isLoadingFallback: ${this.isLoadingFallback}`);
|
|
542
|
+
this.debugLog(`Fallback check - fallbackSources:`, this.source?.fallbackSources);
|
|
543
|
+
this.debugLog(`Fallback check - fallbackPoster:`, this.source?.fallbackPoster);
|
|
544
|
+
this.debugLog(`Fallback check - has fallbackSources: ${!!this.source?.fallbackSources?.length}`);
|
|
545
|
+
this.debugLog(`Fallback check - has fallbackPoster: ${!!this.source?.fallbackPoster}`);
|
|
521
546
|
|
|
522
547
|
// Try fallback sources if available and not already loading one
|
|
523
548
|
if (!this.isLoadingFallback && (this.source?.fallbackSources?.length || this.source?.fallbackPoster)) {
|
|
549
|
+
this.debugLog('✅ Attempting to load fallback sources...');
|
|
524
550
|
const fallbackLoaded = await this.tryFallbackSource(error);
|
|
525
551
|
if (fallbackLoaded) {
|
|
552
|
+
this.debugLog('✅ Fallback loaded successfully!');
|
|
526
553
|
// Successfully loaded fallback, don't call handleError
|
|
527
554
|
return;
|
|
528
555
|
}
|
|
556
|
+
this.debugLog('❌ All fallbacks failed');
|
|
557
|
+
} else {
|
|
558
|
+
this.debugLog('❌ No fallback sources available or already loading');
|
|
529
559
|
}
|
|
530
560
|
|
|
531
561
|
// No fallback available or all fallbacks failed - handle error normally
|
|
532
|
-
this.
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
562
|
+
if (!this.isLoadingFallback) {
|
|
563
|
+
this.handleError({
|
|
564
|
+
code: `MEDIA_ERR_${error.code}`,
|
|
565
|
+
message: error.message || this.getMediaErrorMessage(error.code),
|
|
566
|
+
type: 'media',
|
|
567
|
+
fatal: true,
|
|
568
|
+
details: error
|
|
569
|
+
});
|
|
570
|
+
}
|
|
539
571
|
}
|
|
540
572
|
});
|
|
541
573
|
|
|
@@ -578,6 +610,10 @@ export class WebPlayer extends BasePlayer {
|
|
|
578
610
|
this.source = source as any;
|
|
579
611
|
this.subtitles = (source.subtitles || []) as any;
|
|
580
612
|
|
|
613
|
+
this.debugLog('Loading video source:', source.url);
|
|
614
|
+
this.debugLog('Fallback sources provided:', source.fallbackSources);
|
|
615
|
+
this.debugLog('Fallback poster provided:', source.fallbackPoster);
|
|
616
|
+
|
|
581
617
|
// Reset autoplay flag for new source
|
|
582
618
|
this.autoplayAttempted = false;
|
|
583
619
|
|
|
@@ -586,6 +622,7 @@ export class WebPlayer extends BasePlayer {
|
|
|
586
622
|
this.fallbackErrors = [];
|
|
587
623
|
this.isLoadingFallback = false;
|
|
588
624
|
this.currentRetryAttempt = 0;
|
|
625
|
+
this.lastFailedUrl = '';
|
|
589
626
|
|
|
590
627
|
// Clean up previous instances
|
|
591
628
|
await this.cleanup();
|
|
@@ -652,11 +689,24 @@ export class WebPlayer extends BasePlayer {
|
|
|
652
689
|
* Try loading the next fallback source
|
|
653
690
|
*/
|
|
654
691
|
private async tryFallbackSource(error: any): Promise<boolean> {
|
|
655
|
-
|
|
692
|
+
this.debugLog('🔄 tryFallbackSource called');
|
|
693
|
+
this.debugLog('🔄 isLoadingFallback:', this.isLoadingFallback);
|
|
694
|
+
this.debugLog('🔄 fallbackSources:', this.source?.fallbackSources);
|
|
695
|
+
this.debugLog('🔄 fallbackSources length:', this.source?.fallbackSources?.length);
|
|
696
|
+
this.debugLog('🔄 Current fallbackSourceIndex:', this.fallbackSourceIndex);
|
|
697
|
+
this.debugLog('🔄 Current retry attempt:', this.currentRetryAttempt);
|
|
698
|
+
|
|
699
|
+
if (this.isLoadingFallback) {
|
|
700
|
+
this.debugLog('⚠️ Already loading a fallback, skipping');
|
|
701
|
+
return false;
|
|
702
|
+
}
|
|
703
|
+
|
|
656
704
|
if (!this.source?.fallbackSources || this.source.fallbackSources.length === 0) {
|
|
705
|
+
this.debugLog('⚠️ No fallback sources available, trying fallback poster');
|
|
657
706
|
return this.showFallbackPoster();
|
|
658
707
|
}
|
|
659
708
|
|
|
709
|
+
this.debugLog('✅ Starting fallback loading process');
|
|
660
710
|
this.isLoadingFallback = true;
|
|
661
711
|
|
|
662
712
|
// Record current error
|
|
@@ -667,11 +717,15 @@ export class WebPlayer extends BasePlayer {
|
|
|
667
717
|
this.fallbackErrors.push({ url: currentUrl, error });
|
|
668
718
|
this.debugLog(`Source failed: ${currentUrl}`, error);
|
|
669
719
|
|
|
670
|
-
//
|
|
720
|
+
// Don't retry the main URL - go straight to first fallback
|
|
721
|
+
// Only retry actual fallback sources
|
|
722
|
+
const isMainUrl = this.fallbackSourceIndex === -1;
|
|
671
723
|
const maxRetries = this.source.fallbackRetryAttempts || 1;
|
|
672
|
-
|
|
724
|
+
|
|
725
|
+
if (!isMainUrl && this.currentRetryAttempt < maxRetries) {
|
|
726
|
+
// Only retry if this is a fallback source (not the main URL)
|
|
673
727
|
this.currentRetryAttempt++;
|
|
674
|
-
this.debugLog(`Retrying source (attempt ${this.currentRetryAttempt}/${maxRetries}): ${currentUrl}`);
|
|
728
|
+
this.debugLog(`Retrying fallback source (attempt ${this.currentRetryAttempt}/${maxRetries}): ${currentUrl}`);
|
|
675
729
|
|
|
676
730
|
const retryDelay = this.source.fallbackRetryDelay || 1000;
|
|
677
731
|
await new Promise(resolve => setTimeout(resolve, retryDelay));
|
|
@@ -679,14 +733,20 @@ export class WebPlayer extends BasePlayer {
|
|
|
679
733
|
try {
|
|
680
734
|
const sourceType = this.detectSourceType({ url: currentUrl, type: this.source.type });
|
|
681
735
|
await this.loadVideoSource(currentUrl, sourceType, this.source);
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
this.debugLog(`Retry
|
|
685
|
-
|
|
736
|
+
// Don't mark as successful immediately - let it load and see if error happens
|
|
737
|
+
// Just continue and see what happens
|
|
738
|
+
this.debugLog(`Retry initiated for: ${currentUrl} - waiting for load confirmation...`);
|
|
739
|
+
// Return false to continue the fallback chain if this fails again
|
|
686
740
|
} catch (retryError) {
|
|
687
741
|
this.debugLog(`Retry failed for: ${currentUrl}`, retryError);
|
|
688
742
|
// Continue to next fallback
|
|
689
743
|
}
|
|
744
|
+
} else {
|
|
745
|
+
if (isMainUrl) {
|
|
746
|
+
this.debugLog(`⏭️ Skipping retry of main URL, moving to first fallback source`);
|
|
747
|
+
} else {
|
|
748
|
+
this.debugLog(`⏭️ Max retries (${maxRetries}) reached for ${currentUrl}, moving to next fallback`);
|
|
749
|
+
}
|
|
690
750
|
}
|
|
691
751
|
|
|
692
752
|
// Move to next fallback source
|