unified-video-framework 1.4.241 → 1.4.243
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/package.json +1 -1
- package/packages/web/dist/WebPlayer.d.ts +13 -0
- package/packages/web/dist/WebPlayer.d.ts.map +1 -1
- package/packages/web/dist/WebPlayer.js +240 -1
- package/packages/web/dist/WebPlayer.js.map +1 -1
- package/packages/web/dist/utils/YouTubeExtractor.d.ts +38 -0
- package/packages/web/dist/utils/YouTubeExtractor.d.ts.map +1 -0
- package/packages/web/dist/utils/YouTubeExtractor.js +89 -0
- package/packages/web/dist/utils/YouTubeExtractor.js.map +1 -0
- package/packages/web/src/WebPlayer.ts +312 -1
- package/packages/web/src/utils/YouTubeExtractor.ts +159 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "unified-video-framework",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.243",
|
|
4
4
|
"description": "Cross-platform video player framework supporting iOS, Android, Web, Smart TVs (Samsung/LG), Roku, and more",
|
|
5
5
|
"main": "packages/core/dist/index.js",
|
|
6
6
|
"types": "packages/core/dist/index.d.ts",
|
|
@@ -7,6 +7,7 @@ declare global {
|
|
|
7
7
|
dashjs: any;
|
|
8
8
|
cast?: any;
|
|
9
9
|
chrome?: any;
|
|
10
|
+
YT?: any;
|
|
10
11
|
__onGCastApiAvailable?: (isAvailable: boolean) => void;
|
|
11
12
|
}
|
|
12
13
|
}
|
|
@@ -104,6 +105,18 @@ export declare class WebPlayer extends BasePlayer {
|
|
|
104
105
|
private loadDASH;
|
|
105
106
|
private updateDASHQuality;
|
|
106
107
|
private loadNative;
|
|
108
|
+
private loadYouTube;
|
|
109
|
+
private youtubePlayer;
|
|
110
|
+
private youtubePlayerReady;
|
|
111
|
+
private youtubeIframe;
|
|
112
|
+
private createYouTubePlayer;
|
|
113
|
+
private loadYouTubeAPI;
|
|
114
|
+
private waitForYouTubeAPI;
|
|
115
|
+
private onYouTubePlayerReady;
|
|
116
|
+
private onYouTubePlayerStateChange;
|
|
117
|
+
private onYouTubePlayerError;
|
|
118
|
+
private youtubeTimeTrackingInterval;
|
|
119
|
+
private startYouTubeTimeTracking;
|
|
107
120
|
protected loadScript(src: string): Promise<void>;
|
|
108
121
|
private loadSubtitles;
|
|
109
122
|
private isAbortPlayError;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebPlayer.d.ts","sourceRoot":"","sources":["../src/WebPlayer.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAOL,OAAO,EACP,cAAc,EACf,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,aAAa,EACb,aAAa,EACb,YAAY,EAEb,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"WebPlayer.d.ts","sourceRoot":"","sources":["../src/WebPlayer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BasePlayer } from "../../core/dist/BasePlayer.js";
|
|
2
2
|
import { ChapterManager as CoreChapterManager } from "../../core/dist/index.js";
|
|
3
3
|
import { ChapterManager } from "./chapters/ChapterManager.js";
|
|
4
|
+
import YouTubeExtractor from "./utils/YouTubeExtractor.js";
|
|
4
5
|
export class WebPlayer extends BasePlayer {
|
|
5
6
|
constructor() {
|
|
6
7
|
super(...arguments);
|
|
@@ -89,6 +90,10 @@ export class WebPlayer extends BasePlayer {
|
|
|
89
90
|
this.lastFailedUrl = '';
|
|
90
91
|
this.isFallbackPosterMode = false;
|
|
91
92
|
this.autoplayAttempted = false;
|
|
93
|
+
this.youtubePlayer = null;
|
|
94
|
+
this.youtubePlayerReady = false;
|
|
95
|
+
this.youtubeIframe = null;
|
|
96
|
+
this.youtubeTimeTrackingInterval = null;
|
|
92
97
|
this.clickToUnmuteHandler = null;
|
|
93
98
|
}
|
|
94
99
|
debugLog(message, ...args) {
|
|
@@ -505,6 +510,9 @@ export class WebPlayer extends BasePlayer {
|
|
|
505
510
|
case 'dash':
|
|
506
511
|
await this.loadDASH(url);
|
|
507
512
|
break;
|
|
513
|
+
case 'youtube':
|
|
514
|
+
await this.loadYouTube(url, source);
|
|
515
|
+
break;
|
|
508
516
|
default:
|
|
509
517
|
await this.loadNative(url);
|
|
510
518
|
}
|
|
@@ -647,7 +655,7 @@ export class WebPlayer extends BasePlayer {
|
|
|
647
655
|
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="2" xmlns="http://www.w3.org/2000/svg">
|
|
648
656
|
<rect x="10" y="16" width="20" height="16" rx="2" />
|
|
649
657
|
<polygon points="34,20 42,16 42,32 34,28" />
|
|
650
|
-
<line x1="
|
|
658
|
+
<line x1="5" y1="8" x2="38" y2="40" stroke="currentColor" stroke-width="2"/>
|
|
651
659
|
</svg>
|
|
652
660
|
<div style="font-size: 18px; font-weight: 600; margin-bottom: 8px;">Video Unavailable</div>
|
|
653
661
|
<div style="font-size: 14px; opacity: 0.9;">This video cannot be played at the moment.</div>
|
|
@@ -669,6 +677,9 @@ export class WebPlayer extends BasePlayer {
|
|
|
669
677
|
return source.type;
|
|
670
678
|
}
|
|
671
679
|
const url = source.url.toLowerCase();
|
|
680
|
+
if (YouTubeExtractor.isYouTubeUrl(url)) {
|
|
681
|
+
return 'youtube';
|
|
682
|
+
}
|
|
672
683
|
if (url.includes('.m3u8'))
|
|
673
684
|
return 'hls';
|
|
674
685
|
if (url.includes('.mpd'))
|
|
@@ -814,6 +825,207 @@ export class WebPlayer extends BasePlayer {
|
|
|
814
825
|
this.video.src = url;
|
|
815
826
|
this.video.load();
|
|
816
827
|
}
|
|
828
|
+
async loadYouTube(url, source) {
|
|
829
|
+
try {
|
|
830
|
+
this.debugLog('Loading YouTube video:', url);
|
|
831
|
+
const videoId = YouTubeExtractor.extractVideoId(url);
|
|
832
|
+
if (!videoId) {
|
|
833
|
+
throw new Error('Invalid YouTube URL');
|
|
834
|
+
}
|
|
835
|
+
const metadata = await YouTubeExtractor.getVideoMetadata(url);
|
|
836
|
+
this.source = {
|
|
837
|
+
url: source.url || url,
|
|
838
|
+
...this.source,
|
|
839
|
+
metadata: {
|
|
840
|
+
...source.metadata,
|
|
841
|
+
title: metadata.title,
|
|
842
|
+
thumbnail: metadata.thumbnail,
|
|
843
|
+
duration: metadata.duration,
|
|
844
|
+
source: 'youtube',
|
|
845
|
+
videoId: videoId,
|
|
846
|
+
posterUrl: metadata.thumbnail
|
|
847
|
+
}
|
|
848
|
+
};
|
|
849
|
+
if (this.video && metadata.thumbnail) {
|
|
850
|
+
this.video.poster = metadata.thumbnail;
|
|
851
|
+
}
|
|
852
|
+
await this.createYouTubePlayer(videoId);
|
|
853
|
+
this.debugLog('✅ YouTube video loaded successfully');
|
|
854
|
+
}
|
|
855
|
+
catch (error) {
|
|
856
|
+
this.debugError('Failed to load YouTube video:', error);
|
|
857
|
+
throw new Error(`YouTube video loading failed: ${error}`);
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
async createYouTubePlayer(videoId) {
|
|
861
|
+
const container = this.playerWrapper || this.video?.parentElement;
|
|
862
|
+
if (!container) {
|
|
863
|
+
throw new Error('No container found for YouTube player');
|
|
864
|
+
}
|
|
865
|
+
if (this.video) {
|
|
866
|
+
this.video.style.display = 'none';
|
|
867
|
+
}
|
|
868
|
+
const iframeContainer = document.createElement('div');
|
|
869
|
+
iframeContainer.id = `youtube-player-${videoId}`;
|
|
870
|
+
iframeContainer.style.cssText = `
|
|
871
|
+
position: absolute;
|
|
872
|
+
top: 0;
|
|
873
|
+
left: 0;
|
|
874
|
+
width: 100%;
|
|
875
|
+
height: 100%;
|
|
876
|
+
z-index: 1;
|
|
877
|
+
`;
|
|
878
|
+
const existingPlayer = container.querySelector(`#youtube-player-${videoId}`);
|
|
879
|
+
if (existingPlayer) {
|
|
880
|
+
existingPlayer.remove();
|
|
881
|
+
}
|
|
882
|
+
container.appendChild(iframeContainer);
|
|
883
|
+
if (!window.YT) {
|
|
884
|
+
await this.loadYouTubeAPI();
|
|
885
|
+
}
|
|
886
|
+
await this.waitForYouTubeAPI();
|
|
887
|
+
this.youtubePlayer = new window.YT.Player(iframeContainer.id, {
|
|
888
|
+
videoId: videoId,
|
|
889
|
+
width: '100%',
|
|
890
|
+
height: '100%',
|
|
891
|
+
playerVars: {
|
|
892
|
+
controls: 0,
|
|
893
|
+
disablekb: 1,
|
|
894
|
+
fs: 0,
|
|
895
|
+
iv_load_policy: 3,
|
|
896
|
+
modestbranding: 1,
|
|
897
|
+
rel: 0,
|
|
898
|
+
showinfo: 0,
|
|
899
|
+
autoplay: this.config.autoPlay ? 1 : 0,
|
|
900
|
+
mute: this.config.muted ? 1 : 0
|
|
901
|
+
},
|
|
902
|
+
events: {
|
|
903
|
+
onReady: () => this.onYouTubePlayerReady(),
|
|
904
|
+
onStateChange: (event) => this.onYouTubePlayerStateChange(event),
|
|
905
|
+
onError: (event) => this.onYouTubePlayerError(event)
|
|
906
|
+
}
|
|
907
|
+
});
|
|
908
|
+
this.debugLog('YouTube player created');
|
|
909
|
+
}
|
|
910
|
+
async loadYouTubeAPI() {
|
|
911
|
+
return new Promise((resolve) => {
|
|
912
|
+
if (window.YT) {
|
|
913
|
+
resolve();
|
|
914
|
+
return;
|
|
915
|
+
}
|
|
916
|
+
window.onYouTubeIframeAPIReady = () => {
|
|
917
|
+
this.debugLog('YouTube IFrame API loaded');
|
|
918
|
+
resolve();
|
|
919
|
+
};
|
|
920
|
+
const script = document.createElement('script');
|
|
921
|
+
script.src = 'https://www.youtube.com/iframe_api';
|
|
922
|
+
script.async = true;
|
|
923
|
+
document.body.appendChild(script);
|
|
924
|
+
});
|
|
925
|
+
}
|
|
926
|
+
async waitForYouTubeAPI() {
|
|
927
|
+
return new Promise((resolve) => {
|
|
928
|
+
const checkAPI = () => {
|
|
929
|
+
if (window.YT && window.YT.Player) {
|
|
930
|
+
resolve();
|
|
931
|
+
}
|
|
932
|
+
else {
|
|
933
|
+
setTimeout(checkAPI, 100);
|
|
934
|
+
}
|
|
935
|
+
};
|
|
936
|
+
checkAPI();
|
|
937
|
+
});
|
|
938
|
+
}
|
|
939
|
+
onYouTubePlayerReady() {
|
|
940
|
+
this.youtubePlayerReady = true;
|
|
941
|
+
this.debugLog('YouTube player ready');
|
|
942
|
+
if (this.youtubePlayer) {
|
|
943
|
+
const volume = this.config.volume ? this.config.volume * 100 : 100;
|
|
944
|
+
this.youtubePlayer.setVolume(volume);
|
|
945
|
+
if (this.config.muted) {
|
|
946
|
+
this.youtubePlayer.mute();
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
this.startYouTubeTimeTracking();
|
|
950
|
+
this.emit('onReady');
|
|
951
|
+
}
|
|
952
|
+
onYouTubePlayerStateChange(event) {
|
|
953
|
+
const state = event.data;
|
|
954
|
+
switch (state) {
|
|
955
|
+
case window.YT.PlayerState.PLAYING:
|
|
956
|
+
this.state.isPlaying = true;
|
|
957
|
+
this.state.isPaused = false;
|
|
958
|
+
this.state.isBuffering = false;
|
|
959
|
+
this.emit('onPlay');
|
|
960
|
+
break;
|
|
961
|
+
case window.YT.PlayerState.PAUSED:
|
|
962
|
+
this.state.isPlaying = false;
|
|
963
|
+
this.state.isPaused = true;
|
|
964
|
+
this.state.isBuffering = false;
|
|
965
|
+
this.emit('onPause');
|
|
966
|
+
break;
|
|
967
|
+
case window.YT.PlayerState.BUFFERING:
|
|
968
|
+
this.state.isBuffering = true;
|
|
969
|
+
this.emit('onBuffering', true);
|
|
970
|
+
break;
|
|
971
|
+
case window.YT.PlayerState.ENDED:
|
|
972
|
+
this.state.isPlaying = false;
|
|
973
|
+
this.state.isPaused = true;
|
|
974
|
+
this.state.isEnded = true;
|
|
975
|
+
this.emit('onEnded');
|
|
976
|
+
break;
|
|
977
|
+
case window.YT.PlayerState.CUED:
|
|
978
|
+
this.state.duration = this.youtubePlayer.getDuration();
|
|
979
|
+
break;
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
onYouTubePlayerError(event) {
|
|
983
|
+
const errorCode = event.data;
|
|
984
|
+
let errorMessage = 'YouTube player error';
|
|
985
|
+
switch (errorCode) {
|
|
986
|
+
case 2:
|
|
987
|
+
errorMessage = 'Invalid video ID';
|
|
988
|
+
break;
|
|
989
|
+
case 5:
|
|
990
|
+
errorMessage = 'HTML5 player error';
|
|
991
|
+
break;
|
|
992
|
+
case 100:
|
|
993
|
+
errorMessage = 'Video not found or private';
|
|
994
|
+
break;
|
|
995
|
+
case 101:
|
|
996
|
+
case 150:
|
|
997
|
+
errorMessage = 'Video cannot be embedded';
|
|
998
|
+
break;
|
|
999
|
+
}
|
|
1000
|
+
this.handleError({
|
|
1001
|
+
code: 'YOUTUBE_ERROR',
|
|
1002
|
+
message: errorMessage,
|
|
1003
|
+
type: 'media',
|
|
1004
|
+
fatal: true,
|
|
1005
|
+
details: { errorCode }
|
|
1006
|
+
});
|
|
1007
|
+
}
|
|
1008
|
+
startYouTubeTimeTracking() {
|
|
1009
|
+
if (this.youtubeTimeTrackingInterval) {
|
|
1010
|
+
clearInterval(this.youtubeTimeTrackingInterval);
|
|
1011
|
+
}
|
|
1012
|
+
this.youtubeTimeTrackingInterval = setInterval(() => {
|
|
1013
|
+
if (this.youtubePlayer && this.youtubePlayerReady) {
|
|
1014
|
+
try {
|
|
1015
|
+
const currentTime = this.youtubePlayer.getCurrentTime();
|
|
1016
|
+
const duration = this.youtubePlayer.getDuration();
|
|
1017
|
+
const buffered = this.youtubePlayer.getVideoLoadedFraction() * 100;
|
|
1018
|
+
this.state.currentTime = currentTime || 0;
|
|
1019
|
+
this.state.duration = duration || 0;
|
|
1020
|
+
this.state.bufferedPercentage = buffered || 0;
|
|
1021
|
+
this.emit('onTimeUpdate', this.state.currentTime);
|
|
1022
|
+
this.emit('onProgress', this.state.bufferedPercentage);
|
|
1023
|
+
}
|
|
1024
|
+
catch (error) {
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
}, 250);
|
|
1028
|
+
}
|
|
817
1029
|
loadScript(src) {
|
|
818
1030
|
return new Promise((resolve, reject) => {
|
|
819
1031
|
const script = document.createElement('script');
|
|
@@ -1179,6 +1391,10 @@ export class WebPlayer extends BasePlayer {
|
|
|
1179
1391
|
}
|
|
1180
1392
|
}
|
|
1181
1393
|
async play() {
|
|
1394
|
+
if (this.youtubePlayer && this.youtubePlayerReady) {
|
|
1395
|
+
this.youtubePlayer.playVideo();
|
|
1396
|
+
return;
|
|
1397
|
+
}
|
|
1182
1398
|
if (!this.video)
|
|
1183
1399
|
throw new Error('Video element not initialized');
|
|
1184
1400
|
if (this.isFallbackPosterMode) {
|
|
@@ -1230,6 +1446,10 @@ export class WebPlayer extends BasePlayer {
|
|
|
1230
1446
|
}
|
|
1231
1447
|
}
|
|
1232
1448
|
pause() {
|
|
1449
|
+
if (this.youtubePlayer && this.youtubePlayerReady) {
|
|
1450
|
+
this.youtubePlayer.pauseVideo();
|
|
1451
|
+
return;
|
|
1452
|
+
}
|
|
1233
1453
|
if (!this.video)
|
|
1234
1454
|
return;
|
|
1235
1455
|
const now = Date.now();
|
|
@@ -1286,6 +1506,12 @@ export class WebPlayer extends BasePlayer {
|
|
|
1286
1506
|
}
|
|
1287
1507
|
}
|
|
1288
1508
|
seek(time) {
|
|
1509
|
+
if (this.youtubePlayer && this.youtubePlayerReady) {
|
|
1510
|
+
this.youtubePlayer.seekTo(time, true);
|
|
1511
|
+
this.emit('onSeeking');
|
|
1512
|
+
setTimeout(() => this.emit('onSeeked'), 500);
|
|
1513
|
+
return;
|
|
1514
|
+
}
|
|
1289
1515
|
if (!this.video)
|
|
1290
1516
|
return;
|
|
1291
1517
|
if (!isFinite(time) || isNaN(time)) {
|
|
@@ -1305,24 +1531,37 @@ export class WebPlayer extends BasePlayer {
|
|
|
1305
1531
|
this.safeSetCurrentTime(time);
|
|
1306
1532
|
}
|
|
1307
1533
|
setVolume(level) {
|
|
1534
|
+
if (this.youtubePlayer && this.youtubePlayerReady) {
|
|
1535
|
+
const volumePercent = level * 100;
|
|
1536
|
+
this.youtubePlayer.setVolume(volumePercent);
|
|
1537
|
+
}
|
|
1308
1538
|
if (!this.video)
|
|
1309
1539
|
return;
|
|
1310
1540
|
this.video.volume = Math.max(0, Math.min(1, level));
|
|
1311
1541
|
super.setVolume(level);
|
|
1312
1542
|
}
|
|
1313
1543
|
mute() {
|
|
1544
|
+
if (this.youtubePlayer && this.youtubePlayerReady) {
|
|
1545
|
+
this.youtubePlayer.mute();
|
|
1546
|
+
}
|
|
1314
1547
|
if (!this.video)
|
|
1315
1548
|
return;
|
|
1316
1549
|
this.video.muted = true;
|
|
1317
1550
|
super.mute();
|
|
1318
1551
|
}
|
|
1319
1552
|
unmute() {
|
|
1553
|
+
if (this.youtubePlayer && this.youtubePlayerReady) {
|
|
1554
|
+
this.youtubePlayer.unMute();
|
|
1555
|
+
}
|
|
1320
1556
|
if (!this.video)
|
|
1321
1557
|
return;
|
|
1322
1558
|
this.video.muted = false;
|
|
1323
1559
|
super.unmute();
|
|
1324
1560
|
}
|
|
1325
1561
|
getCurrentTime() {
|
|
1562
|
+
if (this.youtubePlayer && this.youtubePlayerReady) {
|
|
1563
|
+
return this.youtubePlayer.getCurrentTime();
|
|
1564
|
+
}
|
|
1326
1565
|
if (this.video && typeof this.video.currentTime === 'number') {
|
|
1327
1566
|
return this.video.currentTime;
|
|
1328
1567
|
}
|