vidply 1.0.26 → 1.0.28

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 (87) hide show
  1. package/dist/dev/{vidply.HLSRenderer-X46P47LY.js → vidply.HLSRenderer-ENLZE4QS.js} +13 -8
  2. package/dist/dev/vidply.HLSRenderer-ENLZE4QS.js.map +7 -0
  3. package/dist/dev/{vidply.HTML5Renderer-LXQ3I45Q.js → vidply.HTML5Renderer-6SBDI6S2.js} +2 -2
  4. package/dist/dev/vidply.SoundCloudRenderer-CD7VJKNS.js +280 -0
  5. package/dist/dev/vidply.SoundCloudRenderer-CD7VJKNS.js.map +7 -0
  6. package/dist/dev/vidply.TranscriptManager-QSF2PWUN.js +1744 -0
  7. package/dist/dev/vidply.TranscriptManager-QSF2PWUN.js.map +7 -0
  8. package/dist/dev/vidply.TranscriptManager-UTJBQC5B.js +1744 -0
  9. package/dist/dev/vidply.TranscriptManager-UTJBQC5B.js.map +7 -0
  10. package/dist/dev/{vidply.VimeoRenderer-DCETT5IZ.js → vidply.VimeoRenderer-VPH4RNES.js} +17 -4
  11. package/dist/dev/vidply.VimeoRenderer-VPH4RNES.js.map +7 -0
  12. package/dist/dev/{vidply.YouTubeRenderer-QLMMD757.js → vidply.YouTubeRenderer-6MGKEFTZ.js} +14 -6
  13. package/dist/dev/vidply.YouTubeRenderer-6MGKEFTZ.js.map +7 -0
  14. package/dist/dev/vidply.chunk-5663PYKK.js +1631 -0
  15. package/dist/dev/vidply.chunk-5663PYKK.js.map +7 -0
  16. package/dist/dev/{vidply.chunk-UEIJOJH6.js → vidply.chunk-BCOFCT6U.js} +4 -1
  17. package/dist/dev/vidply.chunk-BCOFCT6U.js.map +7 -0
  18. package/dist/dev/vidply.chunk-SRM7VNHG.js +1638 -0
  19. package/dist/dev/vidply.chunk-SRM7VNHG.js.map +7 -0
  20. package/dist/dev/vidply.de-RXAJM5QE.js +181 -0
  21. package/dist/dev/vidply.de-RXAJM5QE.js.map +7 -0
  22. package/dist/dev/vidply.de-SNL6AJ4D.js +188 -0
  23. package/dist/dev/vidply.de-SNL6AJ4D.js.map +7 -0
  24. package/dist/dev/vidply.es-2QCQKZ4U.js +188 -0
  25. package/dist/dev/vidply.es-2QCQKZ4U.js.map +7 -0
  26. package/dist/dev/vidply.es-SADVLJTQ.js +181 -0
  27. package/dist/dev/vidply.es-SADVLJTQ.js.map +7 -0
  28. package/dist/dev/vidply.esm.js +297 -21
  29. package/dist/dev/vidply.esm.js.map +2 -2
  30. package/dist/dev/vidply.fr-FJAZRL4L.js +188 -0
  31. package/dist/dev/vidply.fr-FJAZRL4L.js.map +7 -0
  32. package/dist/dev/vidply.fr-V3VAYBBT.js +181 -0
  33. package/dist/dev/vidply.fr-V3VAYBBT.js.map +7 -0
  34. package/dist/dev/vidply.ja-2XQOW53T.js +188 -0
  35. package/dist/dev/vidply.ja-2XQOW53T.js.map +7 -0
  36. package/dist/dev/vidply.ja-KL2TLZGJ.js +181 -0
  37. package/dist/dev/vidply.ja-KL2TLZGJ.js.map +7 -0
  38. package/dist/legacy/vidply.js +662 -36
  39. package/dist/legacy/vidply.js.map +3 -3
  40. package/dist/legacy/vidply.min.js +1 -1
  41. package/dist/legacy/vidply.min.meta.json +38 -25
  42. package/dist/prod/vidply.HLSRenderer-CBXZ4RF2.min.js +6 -0
  43. package/dist/prod/{vidply.HTML5Renderer-XJCSUETP.min.js → vidply.HTML5Renderer-MY7XDV7R.min.js} +1 -1
  44. package/dist/prod/vidply.SoundCloudRenderer-MOR2CUFH.min.js +6 -0
  45. package/dist/prod/vidply.TranscriptManager-DZ2WZU3K.min.js +6 -0
  46. package/dist/prod/vidply.TranscriptManager-E5QHGFIR.min.js +6 -0
  47. package/dist/prod/vidply.VimeoRenderer-3HBMM2WR.min.js +6 -0
  48. package/dist/prod/vidply.YouTubeRenderer-MFC2GMAC.min.js +6 -0
  49. package/dist/prod/vidply.chunk-5DWTMWEO.min.js +6 -0
  50. package/dist/prod/vidply.chunk-IBNYTGGM.min.js +6 -0
  51. package/dist/prod/vidply.chunk-OXXPY2XB.min.js +6 -0
  52. package/dist/prod/vidply.de-FR3XX54P.min.js +6 -0
  53. package/dist/prod/vidply.de-HGJBCLLE.min.js +6 -0
  54. package/dist/prod/vidply.es-3IJCQLJ7.min.js +6 -0
  55. package/dist/prod/vidply.es-CZEBXCZN.min.js +6 -0
  56. package/dist/prod/vidply.esm.min.js +5 -5
  57. package/dist/prod/vidply.fr-HFOL7MWA.min.js +6 -0
  58. package/dist/prod/vidply.fr-NC4VEAPH.min.js +6 -0
  59. package/dist/prod/vidply.ja-4ZC6ZQLV.min.js +6 -0
  60. package/dist/prod/vidply.ja-QTVU5C25.min.js +6 -0
  61. package/dist/vidply.css +51 -0
  62. package/dist/vidply.esm.min.meta.json +87 -59
  63. package/dist/vidply.min.css +1 -1
  64. package/package.json +1 -1
  65. package/src/controls/TranscriptManager.js +1 -1
  66. package/src/core/Player.js +117 -8
  67. package/src/features/PlaylistManager.js +324 -16
  68. package/src/i18n/languages/de.js +9 -1
  69. package/src/i18n/languages/en.js +9 -1
  70. package/src/i18n/languages/es.js +9 -1
  71. package/src/i18n/languages/fr.js +9 -1
  72. package/src/i18n/languages/ja.js +9 -1
  73. package/src/renderers/HLSRenderer.js +17 -9
  74. package/src/renderers/HTML5Renderer.js +5 -0
  75. package/src/renderers/SoundCloudRenderer.js +355 -0
  76. package/src/renderers/VimeoRenderer.js +20 -4
  77. package/src/renderers/YouTubeRenderer.js +12 -6
  78. package/src/styles/vidply.css +51 -0
  79. package/dist/dev/vidply.HLSRenderer-X46P47LY.js.map +0 -7
  80. package/dist/dev/vidply.VimeoRenderer-DCETT5IZ.js.map +0 -7
  81. package/dist/dev/vidply.YouTubeRenderer-QLMMD757.js.map +0 -7
  82. package/dist/dev/vidply.chunk-UEIJOJH6.js.map +0 -7
  83. package/dist/prod/vidply.HLSRenderer-LDXSMWTI.min.js +0 -6
  84. package/dist/prod/vidply.VimeoRenderer-P3PU27S7.min.js +0 -6
  85. package/dist/prod/vidply.YouTubeRenderer-DGKKWB5M.min.js +0 -6
  86. package/dist/prod/vidply.chunk-BQBGEJF7.min.js +0 -6
  87. /package/dist/dev/{vidply.HTML5Renderer-LXQ3I45Q.js.map → vidply.HTML5Renderer-6SBDI6S2.js.map} +0 -0
@@ -30,7 +30,7 @@ var HLSRenderer = class {
30
30
  return video.canPlayType("application/vnd.apple.mpegurl") !== "";
31
31
  }
32
32
  async initNative() {
33
- const HTML5Renderer = (await import("./vidply.HTML5Renderer-LXQ3I45Q.js")).HTML5Renderer;
33
+ const HTML5Renderer = (await import("./vidply.HTML5Renderer-6SBDI6S2.js")).HTML5Renderer;
34
34
  const renderer = new HTML5Renderer(this.player);
35
35
  await renderer.init();
36
36
  Object.getOwnPropertyNames(Object.getPrototypeOf(renderer)).forEach((method) => {
@@ -72,12 +72,14 @@ var HLSRenderer = class {
72
72
  fragLoadingMaxRetryTimeout: 64e3
73
73
  });
74
74
  this.hls.attachMedia(this.media);
75
- let src;
76
- const sourceElement = this.player.element.querySelector("source");
77
- if (sourceElement) {
78
- src = sourceElement.getAttribute("src");
79
- } else {
80
- src = this.player.element.getAttribute("src") || this.player.element.src;
75
+ let src = this.player.currentSource;
76
+ if (!src) {
77
+ const sourceElement = this.player.element.querySelector("source");
78
+ if (sourceElement) {
79
+ src = sourceElement.getAttribute("src");
80
+ } else {
81
+ src = this.player.element.getAttribute("src") || this.player.element.src;
82
+ }
81
83
  }
82
84
  this.player.log(`Loading HLS source: ${src}`, "log");
83
85
  if (!src) {
@@ -100,6 +102,9 @@ var HLSRenderer = class {
100
102
  this.hls.on(window.Hls.Events.MANIFEST_PARSED, (event, data) => {
101
103
  this.player.log("HLS manifest loaded, found " + data.levels.length + " quality levels");
102
104
  this.player.emit("hlsmanifestparsed", data);
105
+ if (this.player.container) {
106
+ this.player.container.classList.remove("vidply-external-controls");
107
+ }
103
108
  });
104
109
  this.hls.on(window.Hls.Events.LEVEL_SWITCHED, (event, data) => {
105
110
  this.player.log("HLS level switched to " + data.level);
@@ -258,4 +263,4 @@ var HLSRenderer = class {
258
263
  export {
259
264
  HLSRenderer
260
265
  };
261
- //# sourceMappingURL=vidply.HLSRenderer-X46P47LY.js.map
266
+ //# sourceMappingURL=vidply.HLSRenderer-ENLZE4QS.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/renderers/HLSRenderer.js"],
4
+ "sourcesContent": ["/**\r\n * HLS Streaming Renderer\r\n * Uses hls.js for browsers that don't natively support HLS\r\n */\r\n\r\nexport class HLSRenderer {\r\n constructor(player) {\r\n this.player = player;\r\n this.media = player.element;\r\n this.hls = null;\r\n }\r\n\r\n async init() {\r\n // Check if browser natively supports HLS (Safari)\r\n if (this.canPlayNatively()) {\r\n this.player.log('Using native HLS support');\r\n await this.initNative();\r\n } else {\r\n this.player.log('Using hls.js for HLS support');\r\n await this.initHlsJs();\r\n }\r\n }\r\n\r\n canPlayNatively() {\r\n // Only use native HLS on Safari/iOS where it actually works properly\r\n // Chrome reports it can play HLS but doesn't have proper quality switching\r\n const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\r\n const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;\r\n \r\n if (!isSafari && !isIOS) {\r\n // Force hls.js on non-Safari browsers for proper quality switching\r\n return false;\r\n }\r\n \r\n const video = document.createElement('video');\r\n return video.canPlayType('application/vnd.apple.mpegurl') !== '';\r\n }\r\n\r\n async initNative() {\r\n // Use HTML5 renderer for native HLS support\r\n const HTML5Renderer = (await import('./HTML5Renderer.js')).HTML5Renderer;\r\n const renderer = new HTML5Renderer(this.player);\r\n await renderer.init();\r\n \r\n // Copy methods\r\n Object.getOwnPropertyNames(Object.getPrototypeOf(renderer)).forEach(method => {\r\n if (method !== 'constructor' && typeof renderer[method] === 'function') {\r\n this[method] = renderer[method].bind(renderer);\r\n }\r\n });\r\n }\r\n\r\n async initHlsJs() {\r\n // Hide native controls\r\n this.media.controls = false;\r\n this.media.removeAttribute('controls');\r\n \r\n // Load hls.js if not already loaded\r\n if (!window.Hls) {\r\n await this.loadHlsJs();\r\n }\r\n\r\n if (!window.Hls.isSupported()) {\r\n throw new Error('HLS is not supported in this browser');\r\n }\r\n\r\n // Create hls.js instance with better error recovery\r\n this.hls = new window.Hls({\r\n debug: this.player.options.debug,\r\n enableWorker: true,\r\n lowLatencyMode: false,\r\n backBufferLength: 90,\r\n maxBufferLength: 30,\r\n maxMaxBufferLength: 600,\r\n maxBufferSize: 60 * 1000 * 1000,\r\n maxBufferHole: 0.5,\r\n // Network retry settings\r\n manifestLoadingTimeOut: 10000,\r\n manifestLoadingMaxRetry: 4,\r\n manifestLoadingRetryDelay: 1000,\r\n manifestLoadingMaxRetryTimeout: 64000,\r\n levelLoadingTimeOut: 10000,\r\n levelLoadingMaxRetry: 4,\r\n levelLoadingRetryDelay: 1000,\r\n levelLoadingMaxRetryTimeout: 64000,\r\n fragLoadingTimeOut: 20000,\r\n fragLoadingMaxRetry: 6,\r\n fragLoadingRetryDelay: 1000,\r\n fragLoadingMaxRetryTimeout: 64000\r\n });\r\n\r\n // Attach media element\r\n this.hls.attachMedia(this.media);\r\n\r\n // Load source - use currentSource for external renderers, or get from attribute\r\n let src = this.player.currentSource;\r\n \r\n if (!src) {\r\n const sourceElement = this.player.element.querySelector('source');\r\n if (sourceElement) {\r\n // Use getAttribute to get the original URL, not the blob-converted one\r\n src = sourceElement.getAttribute('src');\r\n } else {\r\n // Fallback to element's src attribute\r\n src = this.player.element.getAttribute('src') || this.player.element.src;\r\n }\r\n }\r\n \r\n this.player.log(`Loading HLS source: ${src}`, 'log');\r\n \r\n if (!src) {\r\n throw new Error('No HLS source found');\r\n }\r\n \r\n this.hls.loadSource(src);\r\n\r\n // Attach events\r\n this.attachHlsEvents();\r\n this.attachMediaEvents();\r\n }\r\n\r\n async loadHlsJs() {\r\n return new Promise((resolve, reject) => {\r\n const script = document.createElement('script');\r\n script.src = 'https://cdn.jsdelivr.net/npm/hls.js@latest';\r\n script.onload = () => resolve();\r\n script.onerror = () => reject(new Error('Failed to load hls.js'));\r\n document.head.appendChild(script);\r\n });\r\n }\r\n\r\n attachHlsEvents() {\r\n this.hls.on(window.Hls.Events.MANIFEST_PARSED, (event, data) => {\r\n this.player.log('HLS manifest loaded, found ' + data.levels.length + ' quality levels');\r\n this.player.emit('hlsmanifestparsed', data);\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 this.hls.on(window.Hls.Events.LEVEL_SWITCHED, (event, data) => {\r\n this.player.log('HLS level switched to ' + data.level);\r\n this.player.emit('hlslevelswitched', data);\r\n });\r\n\r\n this.hls.on(window.Hls.Events.ERROR, (event, data) => {\r\n this.handleHlsError(data);\r\n });\r\n\r\n this.hls.on(window.Hls.Events.FRAG_BUFFERED, () => {\r\n this.player.state.buffering = false;\r\n });\r\n }\r\n\r\n attachMediaEvents() {\r\n // Use same events as HTML5 renderer\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\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 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\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('error', () => {\r\n this.player.handleError(this.media.error);\r\n });\r\n }\r\n\r\n handleHlsError(data) {\r\n // Log detailed error info\r\n this.player.log(`HLS Error - Type: ${data.type}, Details: ${data.details}, Fatal: ${data.fatal}`, 'warn');\r\n if (data.response) {\r\n this.player.log(`Response code: ${data.response.code}, URL: ${data.response.url}`, 'warn');\r\n }\r\n \r\n if (data.fatal) {\r\n switch (data.type) {\r\n case window.Hls.ErrorTypes.NETWORK_ERROR:\r\n this.player.log('Fatal network error, trying to recover...', 'error');\r\n this.player.log(`Network error details: ${data.details}`, 'error');\r\n setTimeout(() => {\r\n this.hls.startLoad();\r\n }, 1000);\r\n break;\r\n \r\n case window.Hls.ErrorTypes.MEDIA_ERROR:\r\n this.player.log('Fatal media error, trying to recover...', 'error');\r\n this.hls.recoverMediaError();\r\n break;\r\n \r\n default:\r\n this.player.log('Fatal error, cannot recover', 'error');\r\n this.player.handleError(new Error(`HLS Error: ${data.type} - ${data.details}`));\r\n this.hls.destroy();\r\n break;\r\n }\r\n } else {\r\n this.player.log('Non-fatal HLS error: ' + data.details, 'warn');\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 }\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 switchQuality(levelIndex) {\r\n if (this.hls) {\r\n this.hls.currentLevel = levelIndex;\r\n }\r\n }\r\n\r\n getQualities() {\r\n if (this.hls && this.hls.levels) {\r\n return this.hls.levels.map((level, index) => ({\r\n index,\r\n height: level.height,\r\n width: level.width,\r\n bitrate: level.bitrate,\r\n name: `${level.height}p`\r\n }));\r\n }\r\n return [];\r\n }\r\n\r\n getCurrentQuality() {\r\n if (this.hls) {\r\n return this.hls.currentLevel;\r\n }\r\n return -1;\r\n }\r\n\r\n destroy() {\r\n if (this.hls) {\r\n this.hls.destroy();\r\n this.hls = null;\r\n }\r\n }\r\n}\r\n\r\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -5,8 +5,8 @@
5
5
  */
6
6
  import {
7
7
  HTML5Renderer
8
- } from "./vidply.chunk-UEIJOJH6.js";
8
+ } from "./vidply.chunk-BCOFCT6U.js";
9
9
  export {
10
10
  HTML5Renderer
11
11
  };
12
- //# sourceMappingURL=vidply.HTML5Renderer-LXQ3I45Q.js.map
12
+ //# sourceMappingURL=vidply.HTML5Renderer-6SBDI6S2.js.map
@@ -0,0 +1,280 @@
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/SoundCloudRenderer.js
8
+ var SoundCloudRenderer = class {
9
+ constructor(player) {
10
+ this.player = player;
11
+ this.widget = null;
12
+ this.trackUrl = null;
13
+ this.isReady = false;
14
+ this.iframe = null;
15
+ this.iframeId = null;
16
+ }
17
+ async init() {
18
+ this.trackUrl = this.player.currentSource || this.player.element.src || this.player.element.querySelector("source")?.src;
19
+ if (!this.trackUrl || !this.isValidSoundCloudUrl(this.trackUrl)) {
20
+ throw new Error("Invalid SoundCloud URL");
21
+ }
22
+ await this.loadSoundCloudAPI();
23
+ this.createIframe();
24
+ await this.initializeWidget();
25
+ }
26
+ /**
27
+ * Validate SoundCloud URL
28
+ * @param {string} url
29
+ * @returns {boolean}
30
+ */
31
+ isValidSoundCloudUrl(url) {
32
+ return url.includes("soundcloud.com") || url.includes("api.soundcloud.com");
33
+ }
34
+ /**
35
+ * Check if URL is a playlist/set
36
+ */
37
+ isPlaylist() {
38
+ return this.trackUrl && this.trackUrl.includes("/sets/");
39
+ }
40
+ /**
41
+ * Extract track/playlist info from URL for embed
42
+ * SoundCloud URLs can be:
43
+ * - https://soundcloud.com/artist/track
44
+ * - https://soundcloud.com/artist/sets/playlist
45
+ * - https://api.soundcloud.com/tracks/123456
46
+ */
47
+ getEmbedUrl() {
48
+ const encodedUrl = encodeURIComponent(this.trackUrl);
49
+ const params = new URLSearchParams({
50
+ url: this.trackUrl,
51
+ auto_play: this.player.options.autoplay ? "true" : "false",
52
+ hide_related: "true",
53
+ show_comments: "false",
54
+ show_user: "true",
55
+ show_reposts: "false",
56
+ show_teaser: "false",
57
+ visual: "false",
58
+ // Use classic player for better control
59
+ color: "%23007bff"
60
+ });
61
+ return `https://w.soundcloud.com/player/?${params.toString()}`;
62
+ }
63
+ async loadSoundCloudAPI() {
64
+ if (window.SC && window.SC.Widget) {
65
+ return Promise.resolve();
66
+ }
67
+ return new Promise((resolve, reject) => {
68
+ const script = document.createElement("script");
69
+ script.src = "https://w.soundcloud.com/player/api.js";
70
+ script.onload = () => {
71
+ setTimeout(() => {
72
+ if (window.SC && window.SC.Widget) {
73
+ resolve();
74
+ } else {
75
+ reject(new Error("SoundCloud Widget API not available"));
76
+ }
77
+ }, 100);
78
+ };
79
+ script.onerror = () => reject(new Error("Failed to load SoundCloud Widget API"));
80
+ document.head.appendChild(script);
81
+ });
82
+ }
83
+ createIframe() {
84
+ this.player.element.style.display = "none";
85
+ this.player.element.removeAttribute("poster");
86
+ if (this.player.videoWrapper) {
87
+ this.player.videoWrapper.classList.remove("vidply-forced-poster");
88
+ this.player.videoWrapper.style.removeProperty("--vidply-poster-image");
89
+ }
90
+ this.iframeId = `soundcloud-player-${Math.random().toString(36).substr(2, 9)}`;
91
+ this.iframe = document.createElement("iframe");
92
+ this.iframe.id = this.iframeId;
93
+ this.iframe.scrolling = "no";
94
+ this.iframe.frameBorder = "no";
95
+ this.iframe.allow = "autoplay";
96
+ this.iframe.src = this.getEmbedUrl();
97
+ this.iframe.style.width = "100%";
98
+ this.iframe.style.display = "block";
99
+ if (this.isPlaylist()) {
100
+ this.iframe.style.aspectRatio = "16 / 9";
101
+ this.iframe.classList.add("vidply-soundcloud-iframe", "vidply-soundcloud-playlist");
102
+ } else {
103
+ this.iframe.style.aspectRatio = "16 / 3";
104
+ this.iframe.classList.add("vidply-soundcloud-iframe");
105
+ }
106
+ this.iframe.style.maxHeight = "100%";
107
+ this.player.element.parentNode.insertBefore(this.iframe, this.player.element);
108
+ }
109
+ async initializeWidget() {
110
+ return new Promise((resolve, reject) => {
111
+ this.iframe.addEventListener("load", () => {
112
+ try {
113
+ this.widget = window.SC.Widget(this.iframe);
114
+ this.widget.bind(window.SC.Widget.Events.READY, () => {
115
+ this.isReady = true;
116
+ this.attachEvents();
117
+ if (this.player.container) {
118
+ this.player.container.classList.add("vidply-external-controls");
119
+ }
120
+ this.widget.getCurrentSound((sound) => {
121
+ if (sound) {
122
+ this.player.state.duration = sound.duration / 1e3;
123
+ this.player.emit("loadedmetadata");
124
+ }
125
+ });
126
+ resolve();
127
+ });
128
+ this.widget.bind(window.SC.Widget.Events.ERROR, (error) => {
129
+ this.player.handleError(new Error(`SoundCloud error: ${error.message || "Unknown error"}`));
130
+ });
131
+ } catch (error) {
132
+ reject(error);
133
+ }
134
+ });
135
+ setTimeout(() => {
136
+ if (!this.isReady) {
137
+ reject(new Error("SoundCloud widget initialization timeout"));
138
+ }
139
+ }, 1e4);
140
+ });
141
+ }
142
+ attachEvents() {
143
+ if (!this.widget) return;
144
+ const Events = window.SC.Widget.Events;
145
+ this.widget.bind(Events.PLAY, () => {
146
+ this.player.state.playing = true;
147
+ this.player.state.paused = false;
148
+ this.player.state.ended = false;
149
+ this.player.emit("play");
150
+ if (this.player.options.onPlay) {
151
+ this.player.options.onPlay.call(this.player);
152
+ }
153
+ });
154
+ this.widget.bind(Events.PAUSE, () => {
155
+ this.player.state.playing = false;
156
+ this.player.state.paused = true;
157
+ this.player.emit("pause");
158
+ if (this.player.options.onPause) {
159
+ this.player.options.onPause.call(this.player);
160
+ }
161
+ });
162
+ this.widget.bind(Events.FINISH, () => {
163
+ this.player.state.playing = false;
164
+ this.player.state.paused = true;
165
+ this.player.state.ended = true;
166
+ this.player.emit("ended");
167
+ if (this.player.options.onEnded) {
168
+ this.player.options.onEnded.call(this.player);
169
+ }
170
+ if (this.player.options.loop) {
171
+ this.seek(0);
172
+ this.play();
173
+ }
174
+ });
175
+ this.widget.bind(Events.PLAY_PROGRESS, (data) => {
176
+ const currentTime = data.currentPosition / 1e3;
177
+ this.player.state.currentTime = currentTime;
178
+ this.player.emit("timeupdate", currentTime);
179
+ if (this.player.options.onTimeUpdate) {
180
+ this.player.options.onTimeUpdate.call(this.player, currentTime);
181
+ }
182
+ });
183
+ this.widget.bind(Events.SEEK, (data) => {
184
+ this.player.state.currentTime = data.currentPosition / 1e3;
185
+ this.player.emit("seeked");
186
+ });
187
+ this.widget.bind(Events.LOAD_PROGRESS, (data) => {
188
+ if (this.player.state.duration) {
189
+ const buffered = data.loadedProgress * this.player.state.duration;
190
+ this.player.emit("progress", buffered);
191
+ }
192
+ });
193
+ }
194
+ play() {
195
+ if (this.isReady && this.widget) {
196
+ const scrollX = window.scrollX;
197
+ const scrollY = window.scrollY;
198
+ this.widget.play();
199
+ window.scrollTo(scrollX, scrollY);
200
+ }
201
+ }
202
+ pause() {
203
+ if (this.isReady && this.widget) {
204
+ this.widget.pause();
205
+ }
206
+ }
207
+ seek(time) {
208
+ if (this.isReady && this.widget) {
209
+ this.widget.seekTo(time * 1e3);
210
+ this.player.state.currentTime = time;
211
+ }
212
+ }
213
+ setVolume(volume) {
214
+ if (this.isReady && this.widget) {
215
+ this.widget.setVolume(volume * 100);
216
+ this.player.state.volume = volume;
217
+ }
218
+ }
219
+ setMuted(muted) {
220
+ if (this.isReady && this.widget) {
221
+ if (muted) {
222
+ this.widget.getVolume((vol) => {
223
+ this._previousVolume = vol;
224
+ this.widget.setVolume(0);
225
+ });
226
+ } else {
227
+ this.widget.setVolume(this._previousVolume || 100);
228
+ }
229
+ this.player.state.muted = muted;
230
+ }
231
+ }
232
+ setPlaybackSpeed(speed) {
233
+ this.player.log("SoundCloud does not support playback speed control", "warn");
234
+ }
235
+ /**
236
+ * Get current track info
237
+ * @returns {Promise<Object>}
238
+ */
239
+ getCurrentSound() {
240
+ return new Promise((resolve) => {
241
+ if (this.isReady && this.widget) {
242
+ this.widget.getCurrentSound((sound) => {
243
+ resolve(sound);
244
+ });
245
+ } else {
246
+ resolve(null);
247
+ }
248
+ });
249
+ }
250
+ destroy() {
251
+ if (this.widget) {
252
+ const Events = window.SC.Widget.Events;
253
+ try {
254
+ this.widget.unbind(Events.READY);
255
+ this.widget.unbind(Events.PLAY);
256
+ this.widget.unbind(Events.PAUSE);
257
+ this.widget.unbind(Events.FINISH);
258
+ this.widget.unbind(Events.PLAY_PROGRESS);
259
+ this.widget.unbind(Events.SEEK);
260
+ this.widget.unbind(Events.LOAD_PROGRESS);
261
+ this.widget.unbind(Events.ERROR);
262
+ } catch (e) {
263
+ }
264
+ }
265
+ if (this.iframe && this.iframe.parentNode) {
266
+ this.iframe.parentNode.removeChild(this.iframe);
267
+ }
268
+ if (this.player.element) {
269
+ this.player.element.style.display = "";
270
+ }
271
+ this.widget = null;
272
+ this.isReady = false;
273
+ }
274
+ };
275
+ var SoundCloudRenderer_default = SoundCloudRenderer;
276
+ export {
277
+ SoundCloudRenderer,
278
+ SoundCloudRenderer_default as default
279
+ };
280
+ //# sourceMappingURL=vidply.SoundCloudRenderer-CD7VJKNS.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/renderers/SoundCloudRenderer.js"],
4
+ "sourcesContent": ["/**\r\n * SoundCloud Renderer\r\n * Uses SoundCloud Widget API for embedded track playback\r\n */\r\n\r\nexport class SoundCloudRenderer {\r\n constructor(player) {\r\n this.player = player;\r\n this.widget = null;\r\n this.trackUrl = null;\r\n this.isReady = false;\r\n this.iframe = null;\r\n this.iframeId = null;\r\n }\r\n\r\n async init() {\r\n // Extract track URL - use currentSource which works for external renderers\r\n this.trackUrl = this.player.currentSource || this.player.element.src || this.player.element.querySelector('source')?.src;\r\n \r\n if (!this.trackUrl || !this.isValidSoundCloudUrl(this.trackUrl)) {\r\n throw new Error('Invalid SoundCloud URL');\r\n }\r\n\r\n // Load SoundCloud Widget API\r\n await this.loadSoundCloudAPI();\r\n\r\n // Create iframe\r\n this.createIframe();\r\n\r\n // Initialize widget\r\n await this.initializeWidget();\r\n }\r\n\r\n /**\r\n * Validate SoundCloud URL\r\n * @param {string} url \r\n * @returns {boolean}\r\n */\r\n isValidSoundCloudUrl(url) {\r\n return url.includes('soundcloud.com') || url.includes('api.soundcloud.com');\r\n }\r\n\r\n /**\r\n * Check if URL is a playlist/set\r\n */\r\n isPlaylist() {\r\n return this.trackUrl && this.trackUrl.includes('/sets/');\r\n }\r\n\r\n /**\r\n * Extract track/playlist info from URL for embed\r\n * SoundCloud URLs can be:\r\n * - https://soundcloud.com/artist/track\r\n * - https://soundcloud.com/artist/sets/playlist\r\n * - https://api.soundcloud.com/tracks/123456\r\n */\r\n getEmbedUrl() {\r\n // SoundCloud widget needs the track URL encoded\r\n const encodedUrl = encodeURIComponent(this.trackUrl);\r\n \r\n // Build widget URL with parameters\r\n const params = new URLSearchParams({\r\n url: this.trackUrl,\r\n auto_play: this.player.options.autoplay ? 'true' : 'false',\r\n hide_related: 'true',\r\n show_comments: 'false',\r\n show_user: 'true',\r\n show_reposts: 'false',\r\n show_teaser: 'false',\r\n visual: 'false', // Use classic player for better control\r\n color: '%23007bff'\r\n });\r\n \r\n return `https://w.soundcloud.com/player/?${params.toString()}`;\r\n }\r\n\r\n async loadSoundCloudAPI() {\r\n // Check if API is already loaded\r\n if (window.SC && window.SC.Widget) {\r\n return Promise.resolve();\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n const script = document.createElement('script');\r\n script.src = 'https://w.soundcloud.com/player/api.js';\r\n script.onload = () => {\r\n // Wait a bit for SC.Widget to be fully available\r\n setTimeout(() => {\r\n if (window.SC && window.SC.Widget) {\r\n resolve();\r\n } else {\r\n reject(new Error('SoundCloud Widget API not available'));\r\n }\r\n }, 100);\r\n };\r\n script.onerror = () => reject(new Error('Failed to load SoundCloud Widget API'));\r\n document.head.appendChild(script);\r\n });\r\n }\r\n\r\n createIframe() {\r\n // Hide original element and remove poster (SoundCloud has its own visual widget)\r\n this.player.element.style.display = 'none';\r\n this.player.element.removeAttribute('poster');\r\n \r\n // Remove poster overlay from video wrapper if present\r\n if (this.player.videoWrapper) {\r\n this.player.videoWrapper.classList.remove('vidply-forced-poster');\r\n this.player.videoWrapper.style.removeProperty('--vidply-poster-image');\r\n }\r\n\r\n // Generate unique ID for iframe\r\n this.iframeId = `soundcloud-player-${Math.random().toString(36).substr(2, 9)}`;\r\n\r\n // Create iframe for SoundCloud widget\r\n this.iframe = document.createElement('iframe');\r\n this.iframe.id = this.iframeId;\r\n this.iframe.scrolling = 'no';\r\n this.iframe.frameBorder = 'no';\r\n this.iframe.allow = 'autoplay';\r\n this.iframe.src = this.getEmbedUrl();\r\n this.iframe.style.width = '100%';\r\n this.iframe.style.display = 'block';\r\n \r\n // Use different aspect ratio for playlists vs single tracks\r\n // Playlists need more height to show the track list\r\n if (this.isPlaylist()) {\r\n this.iframe.style.aspectRatio = '16 / 9'; // More height for playlist\r\n this.iframe.classList.add('vidply-soundcloud-iframe', 'vidply-soundcloud-playlist');\r\n } else {\r\n this.iframe.style.aspectRatio = '16 / 3'; // Banner-like for single track\r\n this.iframe.classList.add('vidply-soundcloud-iframe');\r\n }\r\n this.iframe.style.maxHeight = '100%';\r\n \r\n this.player.element.parentNode.insertBefore(this.iframe, this.player.element);\r\n }\r\n\r\n async initializeWidget() {\r\n return new Promise((resolve, reject) => {\r\n // Wait for iframe to load\r\n this.iframe.addEventListener('load', () => {\r\n try {\r\n this.widget = window.SC.Widget(this.iframe);\r\n \r\n this.widget.bind(window.SC.Widget.Events.READY, () => {\r\n this.isReady = true;\r\n this.attachEvents();\r\n \r\n // Hide VidPly controls - SoundCloud has its own\r\n if (this.player.container) {\r\n this.player.container.classList.add('vidply-external-controls');\r\n }\r\n \r\n // Get initial sound info\r\n this.widget.getCurrentSound((sound) => {\r\n if (sound) {\r\n this.player.state.duration = sound.duration / 1000; // Convert ms to seconds\r\n this.player.emit('loadedmetadata');\r\n }\r\n });\r\n \r\n resolve();\r\n });\r\n \r\n this.widget.bind(window.SC.Widget.Events.ERROR, (error) => {\r\n this.player.handleError(new Error(`SoundCloud error: ${error.message || 'Unknown error'}`));\r\n });\r\n } catch (error) {\r\n reject(error);\r\n }\r\n });\r\n \r\n // Timeout after 10 seconds\r\n setTimeout(() => {\r\n if (!this.isReady) {\r\n reject(new Error('SoundCloud widget initialization timeout'));\r\n }\r\n }, 10000);\r\n });\r\n }\r\n\r\n attachEvents() {\r\n if (!this.widget) return;\r\n \r\n const Events = window.SC.Widget.Events;\r\n\r\n this.widget.bind(Events.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\r\n this.widget.bind(Events.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.widget.bind(Events.FINISH, () => {\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.seek(0);\r\n this.play();\r\n }\r\n });\r\n\r\n this.widget.bind(Events.PLAY_PROGRESS, (data) => {\r\n // data.currentPosition is in milliseconds\r\n const currentTime = data.currentPosition / 1000;\r\n this.player.state.currentTime = currentTime;\r\n this.player.emit('timeupdate', currentTime);\r\n \r\n if (this.player.options.onTimeUpdate) {\r\n this.player.options.onTimeUpdate.call(this.player, currentTime);\r\n }\r\n });\r\n\r\n this.widget.bind(Events.SEEK, (data) => {\r\n this.player.state.currentTime = data.currentPosition / 1000;\r\n this.player.emit('seeked');\r\n });\r\n\r\n this.widget.bind(Events.LOAD_PROGRESS, (data) => {\r\n // data.loadedProgress is 0-1\r\n if (this.player.state.duration) {\r\n const buffered = data.loadedProgress * this.player.state.duration;\r\n this.player.emit('progress', buffered);\r\n }\r\n });\r\n }\r\n\r\n play() {\r\n if (this.isReady && this.widget) {\r\n // Save scroll position to prevent browser from scrolling\r\n const scrollX = window.scrollX;\r\n const scrollY = window.scrollY;\r\n \r\n this.widget.play();\r\n \r\n // Restore scroll position\r\n window.scrollTo(scrollX, scrollY);\r\n }\r\n }\r\n\r\n pause() {\r\n if (this.isReady && this.widget) {\r\n this.widget.pause();\r\n }\r\n }\r\n\r\n seek(time) {\r\n if (this.isReady && this.widget) {\r\n // SoundCloud seekTo uses milliseconds\r\n this.widget.seekTo(time * 1000);\r\n this.player.state.currentTime = time;\r\n }\r\n }\r\n\r\n setVolume(volume) {\r\n if (this.isReady && this.widget) {\r\n // SoundCloud setVolume expects 0-100\r\n this.widget.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.widget) {\r\n // SoundCloud doesn't have a native mute, use volume instead\r\n if (muted) {\r\n // Store current volume before muting\r\n this.widget.getVolume((vol) => {\r\n this._previousVolume = vol;\r\n this.widget.setVolume(0);\r\n });\r\n } else {\r\n this.widget.setVolume(this._previousVolume || 100);\r\n }\r\n this.player.state.muted = muted;\r\n }\r\n }\r\n\r\n setPlaybackSpeed(speed) {\r\n // SoundCloud Widget API doesn't support playback speed\r\n this.player.log('SoundCloud does not support playback speed control', 'warn');\r\n }\r\n\r\n /**\r\n * Get current track info\r\n * @returns {Promise<Object>}\r\n */\r\n getCurrentSound() {\r\n return new Promise((resolve) => {\r\n if (this.isReady && this.widget) {\r\n this.widget.getCurrentSound((sound) => {\r\n resolve(sound);\r\n });\r\n } else {\r\n resolve(null);\r\n }\r\n });\r\n }\r\n\r\n destroy() {\r\n // Unbind all events\r\n if (this.widget) {\r\n const Events = window.SC.Widget.Events;\r\n try {\r\n this.widget.unbind(Events.READY);\r\n this.widget.unbind(Events.PLAY);\r\n this.widget.unbind(Events.PAUSE);\r\n this.widget.unbind(Events.FINISH);\r\n this.widget.unbind(Events.PLAY_PROGRESS);\r\n this.widget.unbind(Events.SEEK);\r\n this.widget.unbind(Events.LOAD_PROGRESS);\r\n this.widget.unbind(Events.ERROR);\r\n } catch (e) {\r\n // Ignore unbind errors\r\n }\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 this.widget = null;\r\n this.isReady = false;\r\n }\r\n}\r\n\r\nexport default SoundCloudRenderer;\r\n\r\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }