vidply 1.0.28 → 1.0.30

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 (75) hide show
  1. package/dist/dev/vidply.HLSRenderer-UMPUDSYL.js +266 -0
  2. package/dist/dev/vidply.HLSRenderer-UMPUDSYL.js.map +7 -0
  3. package/dist/dev/vidply.HTML5Renderer-FXBZQL6Y.js +12 -0
  4. package/dist/dev/vidply.HTML5Renderer-FXBZQL6Y.js.map +7 -0
  5. package/dist/dev/{vidply.TranscriptManager-QSF2PWUN.js → vidply.TranscriptManager-T677KF4N.js} +4 -5
  6. package/dist/dev/{vidply.TranscriptManager-QSF2PWUN.js.map → vidply.TranscriptManager-T677KF4N.js.map} +2 -2
  7. package/dist/dev/{vidply.chunk-SRM7VNHG.js → vidply.chunk-GS2JX5RQ.js} +136 -95
  8. package/dist/dev/vidply.chunk-GS2JX5RQ.js.map +7 -0
  9. package/dist/dev/vidply.chunk-W2LSBD6Y.js +251 -0
  10. package/dist/dev/vidply.chunk-W2LSBD6Y.js.map +7 -0
  11. package/dist/dev/vidply.esm.js +1880 -258
  12. package/dist/dev/vidply.esm.js.map +4 -4
  13. package/dist/legacy/vidply.js +2056 -365
  14. package/dist/legacy/vidply.js.map +4 -4
  15. package/dist/legacy/vidply.min.js +1 -1
  16. package/dist/legacy/vidply.min.meta.json +111 -25
  17. package/dist/prod/vidply.HLSRenderer-3CG7BZKA.min.js +6 -0
  18. package/dist/prod/vidply.HTML5Renderer-KKW3OLHM.min.js +6 -0
  19. package/dist/prod/vidply.TranscriptManager-WFZSW6NR.min.js +6 -0
  20. package/dist/prod/vidply.chunk-34RH2THY.min.js +6 -0
  21. package/dist/prod/vidply.chunk-LGTJRPUL.min.js +6 -0
  22. package/dist/prod/vidply.esm.min.js +8 -8
  23. package/dist/vidply.css +20 -1
  24. package/dist/vidply.esm.min.meta.json +120 -34
  25. package/dist/vidply.min.css +1 -1
  26. package/package.json +2 -2
  27. package/src/controls/ControlBar.js +182 -10
  28. package/src/controls/TranscriptManager.js +7 -7
  29. package/src/core/AudioDescriptionManager.js +701 -0
  30. package/src/core/Player.js +203 -256
  31. package/src/core/SignLanguageManager.js +1134 -0
  32. package/src/renderers/HTML5Renderer.js +7 -0
  33. package/src/styles/vidply.css +20 -1
  34. package/src/utils/DOMUtils.js +153 -114
  35. package/src/utils/MenuFactory.js +374 -0
  36. package/src/utils/VideoFrameCapture.js +110 -0
  37. package/dist/dev/vidply.TranscriptManager-GZKY44ON.js +0 -1744
  38. package/dist/dev/vidply.TranscriptManager-GZKY44ON.js.map +0 -7
  39. package/dist/dev/vidply.TranscriptManager-UTJBQC5B.js +0 -1744
  40. package/dist/dev/vidply.TranscriptManager-UTJBQC5B.js.map +0 -7
  41. package/dist/dev/vidply.chunk-5663PYKK.js +0 -1631
  42. package/dist/dev/vidply.chunk-5663PYKK.js.map +0 -7
  43. package/dist/dev/vidply.chunk-SRM7VNHG.js.map +0 -7
  44. package/dist/dev/vidply.chunk-UH5MTGKF.js +0 -1630
  45. package/dist/dev/vidply.chunk-UH5MTGKF.js.map +0 -7
  46. package/dist/dev/vidply.de-RXAJM5QE.js +0 -181
  47. package/dist/dev/vidply.de-RXAJM5QE.js.map +0 -7
  48. package/dist/dev/vidply.de-THBIMP4S.js +0 -180
  49. package/dist/dev/vidply.de-THBIMP4S.js.map +0 -7
  50. package/dist/dev/vidply.es-6VWDNNNL.js +0 -180
  51. package/dist/dev/vidply.es-6VWDNNNL.js.map +0 -7
  52. package/dist/dev/vidply.es-SADVLJTQ.js +0 -181
  53. package/dist/dev/vidply.es-SADVLJTQ.js.map +0 -7
  54. package/dist/dev/vidply.fr-V3VAYBBT.js +0 -181
  55. package/dist/dev/vidply.fr-V3VAYBBT.js.map +0 -7
  56. package/dist/dev/vidply.fr-WHTWCHWT.js +0 -180
  57. package/dist/dev/vidply.fr-WHTWCHWT.js.map +0 -7
  58. package/dist/dev/vidply.ja-BFQNPOFI.js +0 -180
  59. package/dist/dev/vidply.ja-BFQNPOFI.js.map +0 -7
  60. package/dist/dev/vidply.ja-KL2TLZGJ.js +0 -181
  61. package/dist/dev/vidply.ja-KL2TLZGJ.js.map +0 -7
  62. package/dist/prod/vidply.TranscriptManager-DZ2WZU3K.min.js +0 -6
  63. package/dist/prod/vidply.TranscriptManager-E5QHGFIR.min.js +0 -6
  64. package/dist/prod/vidply.TranscriptManager-UZ6DUFB6.min.js +0 -6
  65. package/dist/prod/vidply.chunk-5DWTMWEO.min.js +0 -6
  66. package/dist/prod/vidply.chunk-IBNYTGGM.min.js +0 -6
  67. package/dist/prod/vidply.chunk-MBUR3U5L.min.js +0 -6
  68. package/dist/prod/vidply.de-HGJBCLLE.min.js +0 -6
  69. package/dist/prod/vidply.de-SWFW4HYT.min.js +0 -6
  70. package/dist/prod/vidply.es-7BJ2DJAY.min.js +0 -6
  71. package/dist/prod/vidply.es-CZEBXCZN.min.js +0 -6
  72. package/dist/prod/vidply.fr-DPVR5DFY.min.js +0 -6
  73. package/dist/prod/vidply.fr-HFOL7MWA.min.js +0 -6
  74. package/dist/prod/vidply.ja-PEBVWKVH.min.js +0 -6
  75. package/dist/prod/vidply.ja-QTVU5C25.min.js +0 -6
@@ -0,0 +1,251 @@
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
+ if (this.player.container) {
20
+ this.player.container.classList.remove("vidply-external-controls");
21
+ }
22
+ }
23
+ attachEvents() {
24
+ this.media.addEventListener("loadedmetadata", () => {
25
+ this.player.state.duration = this.media.duration;
26
+ this.player.emit("loadedmetadata");
27
+ if (this.media.tagName === "VIDEO") {
28
+ this.player.autoGeneratePoster().catch((error) => {
29
+ this.player.log("Failed to auto-generate poster:", error, "warn");
30
+ });
31
+ }
32
+ });
33
+ this.media.addEventListener("play", () => {
34
+ this.player.state.playing = true;
35
+ this.player.state.paused = false;
36
+ this.player.state.ended = false;
37
+ this.player.emit("play");
38
+ if (this.player.options.onPlay) {
39
+ this.player.options.onPlay.call(this.player);
40
+ }
41
+ if (this.player.options.pauseOthersOnPlay) {
42
+ this.pauseOtherPlayers();
43
+ }
44
+ });
45
+ this.media.addEventListener("pause", () => {
46
+ this.player.state.playing = false;
47
+ this.player.state.paused = true;
48
+ this.player.emit("pause");
49
+ if (this.player.options.onPause) {
50
+ this.player.options.onPause.call(this.player);
51
+ }
52
+ });
53
+ this.media.addEventListener("ended", () => {
54
+ this.player.state.playing = false;
55
+ this.player.state.paused = true;
56
+ this.player.state.ended = true;
57
+ this.player.emit("ended");
58
+ if (this.player.options.onEnded) {
59
+ this.player.options.onEnded.call(this.player);
60
+ }
61
+ if (this.player.options.loop) {
62
+ this.player.seek(0);
63
+ this.player.play();
64
+ }
65
+ });
66
+ this.media.addEventListener("timeupdate", () => {
67
+ this.player.state.currentTime = this.media.currentTime;
68
+ this.player.emit("timeupdate", this.media.currentTime);
69
+ if (this.player.options.onTimeUpdate) {
70
+ this.player.options.onTimeUpdate.call(this.player, this.media.currentTime);
71
+ }
72
+ });
73
+ this.media.addEventListener("volumechange", () => {
74
+ this.player.state.volume = this.media.volume;
75
+ this.player.state.muted = this.media.muted;
76
+ this.player.emit("volumechange", this.media.volume);
77
+ if (this.player.options.onVolumeChange) {
78
+ this.player.options.onVolumeChange.call(this.player, this.media.volume);
79
+ }
80
+ });
81
+ this.media.addEventListener("seeking", () => {
82
+ this.player.state.seeking = true;
83
+ this.player.emit("seeking");
84
+ });
85
+ this.media.addEventListener("seeked", () => {
86
+ this.player.state.seeking = false;
87
+ this.player.emit("seeked");
88
+ });
89
+ this.media.addEventListener("waiting", () => {
90
+ this.player.state.buffering = true;
91
+ this.player.emit("waiting");
92
+ });
93
+ this.media.addEventListener("canplay", () => {
94
+ this.player.state.buffering = false;
95
+ this.player.emit("canplay");
96
+ });
97
+ this.media.addEventListener("progress", () => {
98
+ if (this.media.buffered.length > 0) {
99
+ const buffered = this.media.buffered.end(this.media.buffered.length - 1);
100
+ this.player.emit("progress", buffered);
101
+ }
102
+ });
103
+ this.media.addEventListener("error", (e) => {
104
+ this.player.handleError(this.media.error);
105
+ });
106
+ this.media.addEventListener("ratechange", () => {
107
+ this.player.state.playbackSpeed = this.media.playbackRate;
108
+ this.player.emit("ratechange", this.media.playbackRate);
109
+ });
110
+ }
111
+ pauseOtherPlayers() {
112
+ const allPlayers = document.querySelectorAll(".vidply-player");
113
+ allPlayers.forEach((playerEl) => {
114
+ if (playerEl !== this.player.container) {
115
+ const video = playerEl.querySelector("video, audio");
116
+ if (video && !video.paused) {
117
+ video.pause();
118
+ }
119
+ }
120
+ });
121
+ }
122
+ play() {
123
+ const scrollX = window.scrollX;
124
+ const scrollY = window.scrollY;
125
+ const promise = this.media.play();
126
+ window.scrollTo(scrollX, scrollY);
127
+ if (promise !== void 0) {
128
+ promise.catch((error) => {
129
+ this.player.log("Play failed:", error, "warn");
130
+ if (this.player.options.autoplay && !this.player.state.muted) {
131
+ this.player.log("Retrying play with muted audio", "info");
132
+ this.media.muted = true;
133
+ const retryScrollX = window.scrollX;
134
+ const retryScrollY = window.scrollY;
135
+ this.media.play().then(() => {
136
+ window.scrollTo(retryScrollX, retryScrollY);
137
+ }).catch((err) => {
138
+ this.player.handleError(err);
139
+ });
140
+ }
141
+ });
142
+ }
143
+ }
144
+ pause() {
145
+ this.media.pause();
146
+ }
147
+ seek(time) {
148
+ this.media.currentTime = time;
149
+ }
150
+ setVolume(volume) {
151
+ this.media.volume = volume;
152
+ }
153
+ setMuted(muted) {
154
+ this.media.muted = muted;
155
+ }
156
+ setPlaybackSpeed(speed) {
157
+ this.media.playbackRate = speed;
158
+ }
159
+ /**
160
+ * Get available quality levels from source elements
161
+ * @returns {Array} Array of quality objects with index, height, width, and src
162
+ */
163
+ getQualities() {
164
+ const sources = Array.from(this.media.querySelectorAll("source"));
165
+ if (sources.length <= 1) {
166
+ return [];
167
+ }
168
+ return sources.map((source, index) => {
169
+ const label = source.getAttribute("data-quality") || source.getAttribute("label") || "";
170
+ const height = source.getAttribute("data-height") || this.extractHeightFromLabel(label);
171
+ const width = source.getAttribute("data-width") || "";
172
+ return {
173
+ index,
174
+ height: height ? parseInt(height) : 0,
175
+ width: width ? parseInt(width) : 0,
176
+ src: source.src,
177
+ type: source.type,
178
+ name: label || (height ? `${height}p` : `Quality ${index + 1}`)
179
+ };
180
+ }).filter((q) => q.height > 0);
181
+ }
182
+ /**
183
+ * Extract height from quality label (e.g., "1080p" -> 1080)
184
+ * @param {string} label
185
+ * @returns {number}
186
+ */
187
+ extractHeightFromLabel(label) {
188
+ const match = label.match(/(\d+)p/i);
189
+ return match ? parseInt(match[1]) : 0;
190
+ }
191
+ /**
192
+ * Switch to a specific quality level
193
+ * @param {number} qualityIndex - Index of the quality level (-1 for auto, not applicable for HTML5)
194
+ */
195
+ switchQuality(qualityIndex) {
196
+ const qualities = this.getQualities();
197
+ if (qualityIndex < 0 || qualityIndex >= qualities.length) {
198
+ this.player.log("Invalid quality index", "warn");
199
+ return;
200
+ }
201
+ const quality = qualities[qualityIndex];
202
+ const currentTime = this.media.currentTime;
203
+ const wasPlaying = !this.media.paused;
204
+ const currentSrc = this.media.currentSrc;
205
+ if (currentSrc === quality.src) {
206
+ this.player.log("Already at this quality level", "info");
207
+ return;
208
+ }
209
+ this.player.log(`Switching to quality: ${quality.name}`, "info");
210
+ this.media.src = quality.src;
211
+ const onLoadedMetadata = () => {
212
+ this.media.removeEventListener("loadedmetadata", onLoadedMetadata);
213
+ this.media.currentTime = currentTime;
214
+ if (wasPlaying) {
215
+ this.media.play().catch((err) => {
216
+ this.player.log("Failed to resume playback after quality switch", "warn");
217
+ });
218
+ }
219
+ this.player.emit("qualitychange", { quality: quality.name, index: qualityIndex });
220
+ };
221
+ this.media.addEventListener("loadedmetadata", onLoadedMetadata);
222
+ this.media.load();
223
+ }
224
+ /**
225
+ * Get current quality index
226
+ * @returns {number}
227
+ */
228
+ getCurrentQuality() {
229
+ const qualities = this.getQualities();
230
+ const currentSrc = this.media.currentSrc;
231
+ for (let i = 0; i < qualities.length; i++) {
232
+ if (qualities[i].src === currentSrc) {
233
+ return i;
234
+ }
235
+ }
236
+ return 0;
237
+ }
238
+ destroy() {
239
+ this.media.removeEventListener("loadedmetadata", () => {
240
+ });
241
+ this.media.removeEventListener("play", () => {
242
+ });
243
+ this.media.removeEventListener("pause", () => {
244
+ });
245
+ }
246
+ };
247
+
248
+ export {
249
+ HTML5Renderer
250
+ };
251
+ //# sourceMappingURL=vidply.chunk-W2LSBD6Y.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 // Show VidPly controls (remove external controls class if present)\r\n if (this.player.container) {\r\n this.player.container.classList.remove('vidply-external-controls');\r\n }\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 // Auto-generate poster if none exists (for HTML5 video only)\r\n if (this.media.tagName === 'VIDEO') {\r\n this.player.autoGeneratePoster().catch(error => {\r\n this.player.log('Failed to auto-generate poster:', error, 'warn');\r\n });\r\n }\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
+ }