vidply 1.0.24 → 1.0.26

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.
Files changed (56) hide show
  1. package/README.md +5 -0
  2. package/dist/dev/vidply.HLSRenderer-X46P47LY.js +261 -0
  3. package/dist/dev/vidply.HLSRenderer-X46P47LY.js.map +7 -0
  4. package/dist/dev/vidply.HTML5Renderer-LXQ3I45Q.js +12 -0
  5. package/dist/dev/vidply.HTML5Renderer-LXQ3I45Q.js.map +7 -0
  6. package/dist/dev/vidply.TranscriptManager-GZKY44ON.js +1744 -0
  7. package/dist/dev/vidply.TranscriptManager-GZKY44ON.js.map +7 -0
  8. package/dist/dev/vidply.VimeoRenderer-DCETT5IZ.js +213 -0
  9. package/dist/dev/vidply.VimeoRenderer-DCETT5IZ.js.map +7 -0
  10. package/dist/dev/vidply.YouTubeRenderer-QLMMD757.js +227 -0
  11. package/dist/dev/vidply.YouTubeRenderer-QLMMD757.js.map +7 -0
  12. package/dist/dev/vidply.chunk-UEIJOJH6.js +243 -0
  13. package/dist/dev/vidply.chunk-UEIJOJH6.js.map +7 -0
  14. package/dist/dev/vidply.chunk-UH5MTGKF.js +1630 -0
  15. package/dist/dev/vidply.chunk-UH5MTGKF.js.map +7 -0
  16. package/dist/dev/vidply.de-THBIMP4S.js +180 -0
  17. package/dist/dev/vidply.de-THBIMP4S.js.map +7 -0
  18. package/dist/dev/vidply.es-6VWDNNNL.js +180 -0
  19. package/dist/dev/vidply.es-6VWDNNNL.js.map +7 -0
  20. package/dist/{vidply.esm.js → dev/vidply.esm.js} +279 -5135
  21. package/dist/dev/vidply.esm.js.map +7 -0
  22. package/dist/dev/vidply.fr-WHTWCHWT.js +180 -0
  23. package/dist/dev/vidply.fr-WHTWCHWT.js.map +7 -0
  24. package/dist/dev/vidply.ja-BFQNPOFI.js +180 -0
  25. package/dist/dev/vidply.ja-BFQNPOFI.js.map +7 -0
  26. package/dist/{vidply.js → legacy/vidply.js} +7676 -7458
  27. package/dist/legacy/vidply.js.map +7 -0
  28. package/dist/legacy/vidply.min.js +6 -0
  29. package/dist/{vidply.min.meta.json → legacy/vidply.min.meta.json} +108 -87
  30. package/dist/prod/vidply.HLSRenderer-LDXSMWTI.min.js +6 -0
  31. package/dist/prod/vidply.HTML5Renderer-XJCSUETP.min.js +6 -0
  32. package/dist/prod/vidply.TranscriptManager-UZ6DUFB6.min.js +6 -0
  33. package/dist/prod/vidply.VimeoRenderer-P3PU27S7.min.js +6 -0
  34. package/dist/prod/vidply.YouTubeRenderer-DGKKWB5M.min.js +6 -0
  35. package/dist/prod/vidply.chunk-BQBGEJF7.min.js +6 -0
  36. package/dist/prod/vidply.chunk-MBUR3U5L.min.js +6 -0
  37. package/dist/prod/vidply.de-SWFW4HYT.min.js +6 -0
  38. package/dist/prod/vidply.es-7BJ2DJAY.min.js +6 -0
  39. package/dist/prod/vidply.esm.min.js +21 -0
  40. package/dist/prod/vidply.fr-DPVR5DFY.min.js +6 -0
  41. package/dist/prod/vidply.ja-PEBVWKVH.min.js +6 -0
  42. package/dist/vidply.css +1 -1
  43. package/dist/vidply.esm.min.meta.json +273 -96
  44. package/dist/vidply.min.css +1 -1
  45. package/package.json +3 -3
  46. package/src/controls/ControlBar.js +2 -4
  47. package/src/core/Player.js +64 -20
  48. package/src/features/PlaylistManager.js +5 -4
  49. package/src/i18n/i18n.js +51 -7
  50. package/src/i18n/translations.js +35 -18
  51. package/src/icons/Icons.js +2 -20
  52. package/src/renderers/HLSRenderer.js +7 -0
  53. package/dist/vidply.esm.js.map +0 -7
  54. package/dist/vidply.esm.min.js +0 -22
  55. package/dist/vidply.js.map +0 -7
  56. package/dist/vidply.min.js +0 -22
@@ -0,0 +1,227 @@
1
+ /*!
2
+ * Universal, Accessible Video Player
3
+ * (c) 2025 Matthias Peltzer
4
+ * Released under GPL-2.0-or-later License
5
+ */
6
+
7
+ // src/renderers/YouTubeRenderer.js
8
+ var YouTubeRenderer = class {
9
+ constructor(player) {
10
+ this.player = player;
11
+ this.youtube = null;
12
+ this.videoId = null;
13
+ this.isReady = false;
14
+ this.iframe = null;
15
+ }
16
+ async init() {
17
+ this.videoId = this.extractVideoId(this.player.element.src);
18
+ if (!this.videoId) {
19
+ throw new Error("Invalid YouTube URL");
20
+ }
21
+ await this.loadYouTubeAPI();
22
+ this.createIframe();
23
+ await this.initializePlayer();
24
+ }
25
+ extractVideoId(url) {
26
+ const patterns = [
27
+ /(?:youtube\.com\/watch\?v=|youtu\.be\/)([^&\s]+)/,
28
+ /youtube\.com\/embed\/([^&\s]+)/
29
+ ];
30
+ for (const pattern of patterns) {
31
+ const match = url.match(pattern);
32
+ if (match && match[1]) {
33
+ return match[1];
34
+ }
35
+ }
36
+ return null;
37
+ }
38
+ async loadYouTubeAPI() {
39
+ if (window.YT && window.YT.Player) {
40
+ return Promise.resolve();
41
+ }
42
+ return new Promise((resolve, reject) => {
43
+ if (window.onYouTubeIframeAPIReady) {
44
+ const originalCallback = window.onYouTubeIframeAPIReady;
45
+ window.onYouTubeIframeAPIReady = () => {
46
+ originalCallback();
47
+ resolve();
48
+ };
49
+ return;
50
+ }
51
+ const tag = document.createElement("script");
52
+ tag.src = "https://www.youtube.com/iframe_api";
53
+ window.onYouTubeIframeAPIReady = () => {
54
+ resolve();
55
+ };
56
+ tag.onerror = () => reject(new Error("Failed to load YouTube API"));
57
+ const firstScriptTag = document.getElementsByTagName("script")[0];
58
+ firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
59
+ });
60
+ }
61
+ createIframe() {
62
+ this.player.element.style.display = "none";
63
+ this.iframe = document.createElement("div");
64
+ this.iframe.id = `youtube-player-${Math.random().toString(36).substr(2, 9)}`;
65
+ this.iframe.style.width = "100%";
66
+ this.iframe.style.height = "100%";
67
+ this.player.element.parentNode.insertBefore(this.iframe, this.player.element);
68
+ }
69
+ async initializePlayer() {
70
+ return new Promise((resolve) => {
71
+ this.youtube = new window.YT.Player(this.iframe.id, {
72
+ videoId: this.videoId,
73
+ width: "100%",
74
+ height: "100%",
75
+ playerVars: {
76
+ controls: 0,
77
+ disablekb: 1,
78
+ fs: 0,
79
+ modestbranding: 1,
80
+ rel: 0,
81
+ showinfo: 0,
82
+ iv_load_policy: 3,
83
+ autoplay: this.player.options.autoplay ? 1 : 0,
84
+ mute: this.player.options.muted ? 1 : 0,
85
+ start: this.player.options.startTime || 0
86
+ },
87
+ events: {
88
+ onReady: (event) => {
89
+ this.isReady = true;
90
+ this.attachEvents();
91
+ resolve();
92
+ },
93
+ onStateChange: (event) => this.handleStateChange(event),
94
+ onError: (event) => this.handleError(event)
95
+ }
96
+ });
97
+ });
98
+ }
99
+ attachEvents() {
100
+ this.timeUpdateInterval = setInterval(() => {
101
+ if (this.isReady && this.youtube) {
102
+ const currentTime = this.youtube.getCurrentTime();
103
+ const duration = this.youtube.getDuration();
104
+ this.player.state.currentTime = currentTime;
105
+ this.player.state.duration = duration;
106
+ this.player.emit("timeupdate", currentTime);
107
+ }
108
+ }, 250);
109
+ if (this.youtube.getDuration) {
110
+ this.player.state.duration = this.youtube.getDuration();
111
+ this.player.emit("loadedmetadata");
112
+ }
113
+ }
114
+ handleStateChange(event) {
115
+ const states = window.YT.PlayerState;
116
+ switch (event.data) {
117
+ case states.PLAYING:
118
+ this.player.state.playing = true;
119
+ this.player.state.paused = false;
120
+ this.player.state.ended = false;
121
+ this.player.state.buffering = false;
122
+ this.player.emit("play");
123
+ this.player.emit("playing");
124
+ if (this.player.options.onPlay) {
125
+ this.player.options.onPlay.call(this.player);
126
+ }
127
+ break;
128
+ case states.PAUSED:
129
+ this.player.state.playing = false;
130
+ this.player.state.paused = true;
131
+ this.player.emit("pause");
132
+ if (this.player.options.onPause) {
133
+ this.player.options.onPause.call(this.player);
134
+ }
135
+ break;
136
+ case states.ENDED:
137
+ this.player.state.playing = false;
138
+ this.player.state.paused = true;
139
+ this.player.state.ended = true;
140
+ this.player.emit("ended");
141
+ if (this.player.options.onEnded) {
142
+ this.player.options.onEnded.call(this.player);
143
+ }
144
+ if (this.player.options.loop) {
145
+ this.youtube.seekTo(0);
146
+ this.youtube.playVideo();
147
+ }
148
+ break;
149
+ case states.BUFFERING:
150
+ this.player.state.buffering = true;
151
+ this.player.emit("waiting");
152
+ break;
153
+ case states.CUED:
154
+ this.player.emit("loadedmetadata");
155
+ break;
156
+ }
157
+ }
158
+ handleError(event) {
159
+ const errors = {
160
+ 2: "Invalid video ID",
161
+ 5: "HTML5 player error",
162
+ 100: "Video not found",
163
+ 101: "Video not allowed to be played in embedded players",
164
+ 150: "Video not allowed to be played in embedded players"
165
+ };
166
+ const error = new Error(errors[event.data] || "YouTube player error");
167
+ this.player.handleError(error);
168
+ }
169
+ play() {
170
+ if (this.isReady && this.youtube) {
171
+ const scrollX = window.scrollX;
172
+ const scrollY = window.scrollY;
173
+ this.youtube.playVideo();
174
+ window.scrollTo(scrollX, scrollY);
175
+ }
176
+ }
177
+ pause() {
178
+ if (this.isReady && this.youtube) {
179
+ this.youtube.pauseVideo();
180
+ }
181
+ }
182
+ seek(time) {
183
+ if (this.isReady && this.youtube) {
184
+ this.youtube.seekTo(time, true);
185
+ }
186
+ }
187
+ setVolume(volume) {
188
+ if (this.isReady && this.youtube) {
189
+ this.youtube.setVolume(volume * 100);
190
+ this.player.state.volume = volume;
191
+ }
192
+ }
193
+ setMuted(muted) {
194
+ if (this.isReady && this.youtube) {
195
+ if (muted) {
196
+ this.youtube.mute();
197
+ } else {
198
+ this.youtube.unMute();
199
+ }
200
+ this.player.state.muted = muted;
201
+ }
202
+ }
203
+ setPlaybackSpeed(speed) {
204
+ if (this.isReady && this.youtube) {
205
+ this.youtube.setPlaybackRate(speed);
206
+ this.player.state.playbackSpeed = speed;
207
+ }
208
+ }
209
+ destroy() {
210
+ if (this.timeUpdateInterval) {
211
+ clearInterval(this.timeUpdateInterval);
212
+ }
213
+ if (this.youtube && this.youtube.destroy) {
214
+ this.youtube.destroy();
215
+ }
216
+ if (this.iframe && this.iframe.parentNode) {
217
+ this.iframe.parentNode.removeChild(this.iframe);
218
+ }
219
+ if (this.player.element) {
220
+ this.player.element.style.display = "";
221
+ }
222
+ }
223
+ };
224
+ export {
225
+ YouTubeRenderer
226
+ };
227
+ //# sourceMappingURL=vidply.YouTubeRenderer-QLMMD757.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/renderers/YouTubeRenderer.js"],
4
+ "sourcesContent": ["/**\r\n * YouTube Renderer\r\n */\r\n\r\nexport class YouTubeRenderer {\r\n constructor(player) {\r\n this.player = player;\r\n this.youtube = null;\r\n this.videoId = null;\r\n this.isReady = false;\r\n this.iframe = null;\r\n }\r\n\r\n async init() {\r\n // Extract video ID from URL\r\n this.videoId = this.extractVideoId(this.player.element.src);\r\n \r\n if (!this.videoId) {\r\n throw new Error('Invalid YouTube URL');\r\n }\r\n\r\n // Load YouTube IFrame API\r\n await this.loadYouTubeAPI();\r\n\r\n // Create iframe\r\n this.createIframe();\r\n\r\n // Initialize player\r\n await this.initializePlayer();\r\n }\r\n\r\n extractVideoId(url) {\r\n const patterns = [\r\n /(?:youtube\\.com\\/watch\\?v=|youtu\\.be\\/)([^&\\s]+)/,\r\n /youtube\\.com\\/embed\\/([^&\\s]+)/\r\n ];\r\n\r\n for (const pattern of patterns) {\r\n const match = url.match(pattern);\r\n if (match && match[1]) {\r\n return match[1];\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n async loadYouTubeAPI() {\r\n // Check if API is already loaded\r\n if (window.YT && window.YT.Player) {\r\n return Promise.resolve();\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n // Check if script is already being loaded\r\n if (window.onYouTubeIframeAPIReady) {\r\n const originalCallback = window.onYouTubeIframeAPIReady;\r\n window.onYouTubeIframeAPIReady = () => {\r\n originalCallback();\r\n resolve();\r\n };\r\n return;\r\n }\r\n\r\n // Load the API script\r\n const tag = document.createElement('script');\r\n tag.src = 'https://www.youtube.com/iframe_api';\r\n \r\n window.onYouTubeIframeAPIReady = () => {\r\n resolve();\r\n };\r\n\r\n tag.onerror = () => reject(new Error('Failed to load YouTube API'));\r\n \r\n const firstScriptTag = document.getElementsByTagName('script')[0];\r\n firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\r\n });\r\n }\r\n\r\n createIframe() {\r\n // Hide original element\r\n this.player.element.style.display = 'none';\r\n\r\n // Create container for iframe\r\n this.iframe = document.createElement('div');\r\n this.iframe.id = `youtube-player-${Math.random().toString(36).substr(2, 9)}`;\r\n this.iframe.style.width = '100%';\r\n this.iframe.style.height = '100%';\r\n \r\n this.player.element.parentNode.insertBefore(this.iframe, this.player.element);\r\n }\r\n\r\n async initializePlayer() {\r\n return new Promise((resolve) => {\r\n this.youtube = new window.YT.Player(this.iframe.id, {\r\n videoId: this.videoId,\r\n width: '100%',\r\n height: '100%',\r\n playerVars: {\r\n controls: 0,\r\n disablekb: 1,\r\n fs: 0,\r\n modestbranding: 1,\r\n rel: 0,\r\n showinfo: 0,\r\n iv_load_policy: 3,\r\n autoplay: this.player.options.autoplay ? 1 : 0,\r\n mute: this.player.options.muted ? 1 : 0,\r\n start: this.player.options.startTime || 0\r\n },\r\n events: {\r\n onReady: (event) => {\r\n this.isReady = true;\r\n this.attachEvents();\r\n resolve();\r\n },\r\n onStateChange: (event) => this.handleStateChange(event),\r\n onError: (event) => this.handleError(event)\r\n }\r\n });\r\n });\r\n }\r\n\r\n attachEvents() {\r\n // Set up polling for time updates (YouTube doesn't provide timeupdate events)\r\n this.timeUpdateInterval = setInterval(() => {\r\n if (this.isReady && this.youtube) {\r\n const currentTime = this.youtube.getCurrentTime();\r\n const duration = this.youtube.getDuration();\r\n \r\n this.player.state.currentTime = currentTime;\r\n this.player.state.duration = duration;\r\n \r\n this.player.emit('timeupdate', currentTime);\r\n }\r\n }, 250);\r\n\r\n // Initial metadata\r\n if (this.youtube.getDuration) {\r\n this.player.state.duration = this.youtube.getDuration();\r\n this.player.emit('loadedmetadata');\r\n }\r\n }\r\n\r\n handleStateChange(event) {\r\n const states = window.YT.PlayerState;\r\n\r\n switch (event.data) {\r\n case states.PLAYING:\r\n this.player.state.playing = true;\r\n this.player.state.paused = false;\r\n this.player.state.ended = false;\r\n this.player.state.buffering = false;\r\n this.player.emit('play');\r\n this.player.emit('playing');\r\n \r\n if (this.player.options.onPlay) {\r\n this.player.options.onPlay.call(this.player);\r\n }\r\n break;\r\n\r\n case states.PAUSED:\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.emit('pause');\r\n \r\n if (this.player.options.onPause) {\r\n this.player.options.onPause.call(this.player);\r\n }\r\n break;\r\n\r\n case states.ENDED:\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.state.ended = true;\r\n this.player.emit('ended');\r\n \r\n if (this.player.options.onEnded) {\r\n this.player.options.onEnded.call(this.player);\r\n }\r\n \r\n if (this.player.options.loop) {\r\n this.youtube.seekTo(0);\r\n this.youtube.playVideo();\r\n }\r\n break;\r\n\r\n case states.BUFFERING:\r\n this.player.state.buffering = true;\r\n this.player.emit('waiting');\r\n break;\r\n\r\n case states.CUED:\r\n this.player.emit('loadedmetadata');\r\n break;\r\n }\r\n }\r\n\r\n handleError(event) {\r\n const errors = {\r\n 2: 'Invalid video ID',\r\n 5: 'HTML5 player error',\r\n 100: 'Video not found',\r\n 101: 'Video not allowed to be played in embedded players',\r\n 150: 'Video not allowed to be played in embedded players'\r\n };\r\n\r\n const error = new Error(errors[event.data] || 'YouTube player error');\r\n this.player.handleError(error);\r\n }\r\n\r\n play() {\r\n if (this.isReady && this.youtube) {\r\n // Save scroll position to prevent browser from scrolling to video\r\n const scrollX = window.scrollX;\r\n const scrollY = window.scrollY;\r\n \r\n this.youtube.playVideo();\r\n \r\n // Restore scroll position immediately to prevent auto-scroll\r\n window.scrollTo(scrollX, scrollY);\r\n }\r\n }\r\n\r\n pause() {\r\n if (this.isReady && this.youtube) {\r\n this.youtube.pauseVideo();\r\n }\r\n }\r\n\r\n seek(time) {\r\n if (this.isReady && this.youtube) {\r\n this.youtube.seekTo(time, true);\r\n }\r\n }\r\n\r\n setVolume(volume) {\r\n if (this.isReady && this.youtube) {\r\n this.youtube.setVolume(volume * 100);\r\n this.player.state.volume = volume;\r\n }\r\n }\r\n\r\n setMuted(muted) {\r\n if (this.isReady && this.youtube) {\r\n if (muted) {\r\n this.youtube.mute();\r\n } else {\r\n this.youtube.unMute();\r\n }\r\n this.player.state.muted = muted;\r\n }\r\n }\r\n\r\n setPlaybackSpeed(speed) {\r\n if (this.isReady && this.youtube) {\r\n this.youtube.setPlaybackRate(speed);\r\n this.player.state.playbackSpeed = speed;\r\n }\r\n }\r\n\r\n destroy() {\r\n if (this.timeUpdateInterval) {\r\n clearInterval(this.timeUpdateInterval);\r\n }\r\n\r\n if (this.youtube && this.youtube.destroy) {\r\n this.youtube.destroy();\r\n }\r\n\r\n if (this.iframe && this.iframe.parentNode) {\r\n this.iframe.parentNode.removeChild(this.iframe);\r\n }\r\n\r\n // Show original element\r\n if (this.player.element) {\r\n this.player.element.style.display = '';\r\n }\r\n }\r\n}\r\n\r\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,243 @@
1
+ /*!
2
+ * Universal, Accessible Video Player
3
+ * (c) 2025 Matthias Peltzer
4
+ * Released under GPL-2.0-or-later License
5
+ */
6
+
7
+ // src/renderers/HTML5Renderer.js
8
+ var HTML5Renderer = class {
9
+ constructor(player) {
10
+ this.player = player;
11
+ this.media = player.element;
12
+ }
13
+ async init() {
14
+ this.media.controls = false;
15
+ this.media.removeAttribute("controls");
16
+ this.attachEvents();
17
+ this.media.preload = this.player.options.preload;
18
+ this.media.load();
19
+ }
20
+ attachEvents() {
21
+ this.media.addEventListener("loadedmetadata", () => {
22
+ this.player.state.duration = this.media.duration;
23
+ this.player.emit("loadedmetadata");
24
+ });
25
+ this.media.addEventListener("play", () => {
26
+ this.player.state.playing = true;
27
+ this.player.state.paused = false;
28
+ this.player.state.ended = false;
29
+ this.player.emit("play");
30
+ if (this.player.options.onPlay) {
31
+ this.player.options.onPlay.call(this.player);
32
+ }
33
+ if (this.player.options.pauseOthersOnPlay) {
34
+ this.pauseOtherPlayers();
35
+ }
36
+ });
37
+ this.media.addEventListener("pause", () => {
38
+ this.player.state.playing = false;
39
+ this.player.state.paused = true;
40
+ this.player.emit("pause");
41
+ if (this.player.options.onPause) {
42
+ this.player.options.onPause.call(this.player);
43
+ }
44
+ });
45
+ this.media.addEventListener("ended", () => {
46
+ this.player.state.playing = false;
47
+ this.player.state.paused = true;
48
+ this.player.state.ended = true;
49
+ this.player.emit("ended");
50
+ if (this.player.options.onEnded) {
51
+ this.player.options.onEnded.call(this.player);
52
+ }
53
+ if (this.player.options.loop) {
54
+ this.player.seek(0);
55
+ this.player.play();
56
+ }
57
+ });
58
+ this.media.addEventListener("timeupdate", () => {
59
+ this.player.state.currentTime = this.media.currentTime;
60
+ this.player.emit("timeupdate", this.media.currentTime);
61
+ if (this.player.options.onTimeUpdate) {
62
+ this.player.options.onTimeUpdate.call(this.player, this.media.currentTime);
63
+ }
64
+ });
65
+ this.media.addEventListener("volumechange", () => {
66
+ this.player.state.volume = this.media.volume;
67
+ this.player.state.muted = this.media.muted;
68
+ this.player.emit("volumechange", this.media.volume);
69
+ if (this.player.options.onVolumeChange) {
70
+ this.player.options.onVolumeChange.call(this.player, this.media.volume);
71
+ }
72
+ });
73
+ this.media.addEventListener("seeking", () => {
74
+ this.player.state.seeking = true;
75
+ this.player.emit("seeking");
76
+ });
77
+ this.media.addEventListener("seeked", () => {
78
+ this.player.state.seeking = false;
79
+ this.player.emit("seeked");
80
+ });
81
+ this.media.addEventListener("waiting", () => {
82
+ this.player.state.buffering = true;
83
+ this.player.emit("waiting");
84
+ });
85
+ this.media.addEventListener("canplay", () => {
86
+ this.player.state.buffering = false;
87
+ this.player.emit("canplay");
88
+ });
89
+ this.media.addEventListener("progress", () => {
90
+ if (this.media.buffered.length > 0) {
91
+ const buffered = this.media.buffered.end(this.media.buffered.length - 1);
92
+ this.player.emit("progress", buffered);
93
+ }
94
+ });
95
+ this.media.addEventListener("error", (e) => {
96
+ this.player.handleError(this.media.error);
97
+ });
98
+ this.media.addEventListener("ratechange", () => {
99
+ this.player.state.playbackSpeed = this.media.playbackRate;
100
+ this.player.emit("ratechange", this.media.playbackRate);
101
+ });
102
+ }
103
+ pauseOtherPlayers() {
104
+ const allPlayers = document.querySelectorAll(".vidply-player");
105
+ allPlayers.forEach((playerEl) => {
106
+ if (playerEl !== this.player.container) {
107
+ const video = playerEl.querySelector("video, audio");
108
+ if (video && !video.paused) {
109
+ video.pause();
110
+ }
111
+ }
112
+ });
113
+ }
114
+ play() {
115
+ const scrollX = window.scrollX;
116
+ const scrollY = window.scrollY;
117
+ const promise = this.media.play();
118
+ window.scrollTo(scrollX, scrollY);
119
+ if (promise !== void 0) {
120
+ promise.catch((error) => {
121
+ this.player.log("Play failed:", error, "warn");
122
+ if (this.player.options.autoplay && !this.player.state.muted) {
123
+ this.player.log("Retrying play with muted audio", "info");
124
+ this.media.muted = true;
125
+ const retryScrollX = window.scrollX;
126
+ const retryScrollY = window.scrollY;
127
+ this.media.play().then(() => {
128
+ window.scrollTo(retryScrollX, retryScrollY);
129
+ }).catch((err) => {
130
+ this.player.handleError(err);
131
+ });
132
+ }
133
+ });
134
+ }
135
+ }
136
+ pause() {
137
+ this.media.pause();
138
+ }
139
+ seek(time) {
140
+ this.media.currentTime = time;
141
+ }
142
+ setVolume(volume) {
143
+ this.media.volume = volume;
144
+ }
145
+ setMuted(muted) {
146
+ this.media.muted = muted;
147
+ }
148
+ setPlaybackSpeed(speed) {
149
+ this.media.playbackRate = speed;
150
+ }
151
+ /**
152
+ * Get available quality levels from source elements
153
+ * @returns {Array} Array of quality objects with index, height, width, and src
154
+ */
155
+ getQualities() {
156
+ const sources = Array.from(this.media.querySelectorAll("source"));
157
+ if (sources.length <= 1) {
158
+ return [];
159
+ }
160
+ return sources.map((source, index) => {
161
+ const label = source.getAttribute("data-quality") || source.getAttribute("label") || "";
162
+ const height = source.getAttribute("data-height") || this.extractHeightFromLabel(label);
163
+ const width = source.getAttribute("data-width") || "";
164
+ return {
165
+ index,
166
+ height: height ? parseInt(height) : 0,
167
+ width: width ? parseInt(width) : 0,
168
+ src: source.src,
169
+ type: source.type,
170
+ name: label || (height ? `${height}p` : `Quality ${index + 1}`)
171
+ };
172
+ }).filter((q) => q.height > 0);
173
+ }
174
+ /**
175
+ * Extract height from quality label (e.g., "1080p" -> 1080)
176
+ * @param {string} label
177
+ * @returns {number}
178
+ */
179
+ extractHeightFromLabel(label) {
180
+ const match = label.match(/(\d+)p/i);
181
+ return match ? parseInt(match[1]) : 0;
182
+ }
183
+ /**
184
+ * Switch to a specific quality level
185
+ * @param {number} qualityIndex - Index of the quality level (-1 for auto, not applicable for HTML5)
186
+ */
187
+ switchQuality(qualityIndex) {
188
+ const qualities = this.getQualities();
189
+ if (qualityIndex < 0 || qualityIndex >= qualities.length) {
190
+ this.player.log("Invalid quality index", "warn");
191
+ return;
192
+ }
193
+ const quality = qualities[qualityIndex];
194
+ const currentTime = this.media.currentTime;
195
+ const wasPlaying = !this.media.paused;
196
+ const currentSrc = this.media.currentSrc;
197
+ if (currentSrc === quality.src) {
198
+ this.player.log("Already at this quality level", "info");
199
+ return;
200
+ }
201
+ this.player.log(`Switching to quality: ${quality.name}`, "info");
202
+ this.media.src = quality.src;
203
+ const onLoadedMetadata = () => {
204
+ this.media.removeEventListener("loadedmetadata", onLoadedMetadata);
205
+ this.media.currentTime = currentTime;
206
+ if (wasPlaying) {
207
+ this.media.play().catch((err) => {
208
+ this.player.log("Failed to resume playback after quality switch", "warn");
209
+ });
210
+ }
211
+ this.player.emit("qualitychange", { quality: quality.name, index: qualityIndex });
212
+ };
213
+ this.media.addEventListener("loadedmetadata", onLoadedMetadata);
214
+ this.media.load();
215
+ }
216
+ /**
217
+ * Get current quality index
218
+ * @returns {number}
219
+ */
220
+ getCurrentQuality() {
221
+ const qualities = this.getQualities();
222
+ const currentSrc = this.media.currentSrc;
223
+ for (let i = 0; i < qualities.length; i++) {
224
+ if (qualities[i].src === currentSrc) {
225
+ return i;
226
+ }
227
+ }
228
+ return 0;
229
+ }
230
+ destroy() {
231
+ this.media.removeEventListener("loadedmetadata", () => {
232
+ });
233
+ this.media.removeEventListener("play", () => {
234
+ });
235
+ this.media.removeEventListener("pause", () => {
236
+ });
237
+ }
238
+ };
239
+
240
+ export {
241
+ HTML5Renderer
242
+ };
243
+ //# sourceMappingURL=vidply.chunk-UEIJOJH6.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/renderers/HTML5Renderer.js"],
4
+ "sourcesContent": ["/**\r\n * HTML5 Media Renderer\r\n */\r\n\r\nexport class HTML5Renderer {\r\n constructor(player) {\r\n this.player = player;\r\n this.media = player.element;\r\n }\r\n\r\n async init() {\r\n // Hide native controls\r\n this.media.controls = false;\r\n this.media.removeAttribute('controls');\r\n \r\n this.attachEvents();\r\n \r\n // Set preload\r\n this.media.preload = this.player.options.preload;\r\n \r\n // Load media\r\n this.media.load();\r\n }\r\n\r\n attachEvents() {\r\n // Playback events\r\n this.media.addEventListener('loadedmetadata', () => {\r\n this.player.state.duration = this.media.duration;\r\n this.player.emit('loadedmetadata');\r\n });\r\n\r\n this.media.addEventListener('play', () => {\r\n this.player.state.playing = true;\r\n this.player.state.paused = false;\r\n this.player.state.ended = false;\r\n this.player.emit('play');\r\n \r\n if (this.player.options.onPlay) {\r\n this.player.options.onPlay.call(this.player);\r\n }\r\n \r\n // Pause other players if enabled\r\n if (this.player.options.pauseOthersOnPlay) {\r\n this.pauseOtherPlayers();\r\n }\r\n });\r\n\r\n this.media.addEventListener('pause', () => {\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.emit('pause');\r\n \r\n if (this.player.options.onPause) {\r\n this.player.options.onPause.call(this.player);\r\n }\r\n });\r\n\r\n this.media.addEventListener('ended', () => {\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.state.ended = true;\r\n this.player.emit('ended');\r\n \r\n if (this.player.options.onEnded) {\r\n this.player.options.onEnded.call(this.player);\r\n }\r\n \r\n // Handle loop\r\n if (this.player.options.loop) {\r\n this.player.seek(0);\r\n this.player.play();\r\n }\r\n });\r\n\r\n this.media.addEventListener('timeupdate', () => {\r\n this.player.state.currentTime = this.media.currentTime;\r\n this.player.emit('timeupdate', this.media.currentTime);\r\n \r\n if (this.player.options.onTimeUpdate) {\r\n this.player.options.onTimeUpdate.call(this.player, this.media.currentTime);\r\n }\r\n });\r\n\r\n this.media.addEventListener('volumechange', () => {\r\n this.player.state.volume = this.media.volume;\r\n this.player.state.muted = this.media.muted;\r\n this.player.emit('volumechange', this.media.volume);\r\n \r\n if (this.player.options.onVolumeChange) {\r\n this.player.options.onVolumeChange.call(this.player, this.media.volume);\r\n }\r\n });\r\n\r\n this.media.addEventListener('seeking', () => {\r\n this.player.state.seeking = true;\r\n this.player.emit('seeking');\r\n });\r\n\r\n this.media.addEventListener('seeked', () => {\r\n this.player.state.seeking = false;\r\n this.player.emit('seeked');\r\n });\r\n\r\n this.media.addEventListener('waiting', () => {\r\n this.player.state.buffering = true;\r\n this.player.emit('waiting');\r\n });\r\n\r\n this.media.addEventListener('canplay', () => {\r\n this.player.state.buffering = false;\r\n this.player.emit('canplay');\r\n });\r\n\r\n this.media.addEventListener('progress', () => {\r\n if (this.media.buffered.length > 0) {\r\n const buffered = this.media.buffered.end(this.media.buffered.length - 1);\r\n this.player.emit('progress', buffered);\r\n }\r\n });\r\n\r\n this.media.addEventListener('error', (e) => {\r\n this.player.handleError(this.media.error);\r\n });\r\n\r\n this.media.addEventListener('ratechange', () => {\r\n this.player.state.playbackSpeed = this.media.playbackRate;\r\n this.player.emit('ratechange', this.media.playbackRate);\r\n });\r\n }\r\n\r\n pauseOtherPlayers() {\r\n // Pause other VidPly instances\r\n const allPlayers = document.querySelectorAll('.vidply-player');\r\n allPlayers.forEach(playerEl => {\r\n if (playerEl !== this.player.container) {\r\n const video = playerEl.querySelector('video, audio');\r\n if (video && !video.paused) {\r\n video.pause();\r\n }\r\n }\r\n });\r\n }\r\n\r\n play() {\r\n // Save scroll position to prevent browser from scrolling to video\r\n const scrollX = window.scrollX;\r\n const scrollY = window.scrollY;\r\n \r\n const promise = this.media.play();\r\n \r\n // Restore scroll position immediately to prevent auto-scroll\r\n window.scrollTo(scrollX, scrollY);\r\n \r\n if (promise !== undefined) {\r\n promise.catch(error => {\r\n this.player.log('Play failed:', error, 'warn');\r\n \r\n // If autoplay failed, try muted autoplay\r\n if (this.player.options.autoplay && !this.player.state.muted) {\r\n this.player.log('Retrying play with muted audio', 'info');\r\n this.media.muted = true;\r\n \r\n // Save scroll position again for retry\r\n const retryScrollX = window.scrollX;\r\n const retryScrollY = window.scrollY;\r\n this.media.play().then(() => {\r\n window.scrollTo(retryScrollX, retryScrollY);\r\n }).catch(err => {\r\n this.player.handleError(err);\r\n });\r\n }\r\n });\r\n }\r\n }\r\n\r\n pause() {\r\n this.media.pause();\r\n }\r\n\r\n seek(time) {\r\n this.media.currentTime = time;\r\n }\r\n\r\n setVolume(volume) {\r\n this.media.volume = volume;\r\n }\r\n\r\n setMuted(muted) {\r\n this.media.muted = muted;\r\n }\r\n\r\n setPlaybackSpeed(speed) {\r\n this.media.playbackRate = speed;\r\n }\r\n\r\n /**\r\n * Get available quality levels from source elements\r\n * @returns {Array} Array of quality objects with index, height, width, and src\r\n */\r\n getQualities() {\r\n const sources = Array.from(this.media.querySelectorAll('source'));\r\n \r\n if (sources.length <= 1) {\r\n return [];\r\n }\r\n\r\n return sources.map((source, index) => {\r\n // Try to extract quality from data attributes or label\r\n const label = source.getAttribute('data-quality') || source.getAttribute('label') || '';\r\n const height = source.getAttribute('data-height') || this.extractHeightFromLabel(label);\r\n const width = source.getAttribute('data-width') || '';\r\n \r\n return {\r\n index,\r\n height: height ? parseInt(height) : 0,\r\n width: width ? parseInt(width) : 0,\r\n src: source.src,\r\n type: source.type,\r\n name: label || (height ? `${height}p` : `Quality ${index + 1}`)\r\n };\r\n }).filter(q => q.height > 0); // Only return qualities with valid height\r\n }\r\n\r\n /**\r\n * Extract height from quality label (e.g., \"1080p\" -> 1080)\r\n * @param {string} label \r\n * @returns {number}\r\n */\r\n extractHeightFromLabel(label) {\r\n const match = label.match(/(\\d+)p/i);\r\n return match ? parseInt(match[1]) : 0;\r\n }\r\n\r\n /**\r\n * Switch to a specific quality level\r\n * @param {number} qualityIndex - Index of the quality level (-1 for auto, not applicable for HTML5)\r\n */\r\n switchQuality(qualityIndex) {\r\n const qualities = this.getQualities();\r\n \r\n if (qualityIndex < 0 || qualityIndex >= qualities.length) {\r\n this.player.log('Invalid quality index', 'warn');\r\n return;\r\n }\r\n\r\n const quality = qualities[qualityIndex];\r\n const currentTime = this.media.currentTime;\r\n const wasPlaying = !this.media.paused;\r\n\r\n // Store the current source for comparison\r\n const currentSrc = this.media.currentSrc;\r\n \r\n // Don't switch if already at this quality\r\n if (currentSrc === quality.src) {\r\n this.player.log('Already at this quality level', 'info');\r\n return;\r\n }\r\n\r\n this.player.log(`Switching to quality: ${quality.name}`, 'info');\r\n\r\n // Update the src\r\n this.media.src = quality.src;\r\n \r\n // Wait for the new source to load, then restore playback state\r\n const onLoadedMetadata = () => {\r\n this.media.removeEventListener('loadedmetadata', onLoadedMetadata);\r\n \r\n // Restore playback position\r\n this.media.currentTime = currentTime;\r\n \r\n // Resume playback if it was playing\r\n if (wasPlaying) {\r\n this.media.play().catch(err => {\r\n this.player.log('Failed to resume playback after quality switch', 'warn');\r\n });\r\n }\r\n \r\n // Emit quality change event\r\n this.player.emit('qualitychange', { quality: quality.name, index: qualityIndex });\r\n };\r\n\r\n this.media.addEventListener('loadedmetadata', onLoadedMetadata);\r\n this.media.load();\r\n }\r\n\r\n /**\r\n * Get current quality index\r\n * @returns {number}\r\n */\r\n getCurrentQuality() {\r\n const qualities = this.getQualities();\r\n const currentSrc = this.media.currentSrc;\r\n \r\n for (let i = 0; i < qualities.length; i++) {\r\n if (qualities[i].src === currentSrc) {\r\n return i;\r\n }\r\n }\r\n \r\n return 0; // Default to first quality if not found\r\n }\r\n\r\n destroy() {\r\n // Remove event listeners\r\n this.media.removeEventListener('loadedmetadata', () => {});\r\n this.media.removeEventListener('play', () => {});\r\n this.media.removeEventListener('pause', () => {});\r\n // ... (other listeners would be removed in a real implementation)\r\n }\r\n}\r\n\r\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }