@videojs/html 10.2.0 → 10.3.0

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 (297) hide show
  1. package/dist/default/define/audio/compat-skin.css +72 -5
  2. package/dist/default/define/audio/compat-skin2.js +1 -1
  3. package/dist/default/define/audio/neutral-skin.css +23 -5
  4. package/dist/default/define/audio/neutral-skin2.js +1 -1
  5. package/dist/default/define/audio/scaffold-skin.css +63 -4
  6. package/dist/default/define/audio/scaffold-skin2.js +1 -1
  7. package/dist/default/define/audio/skin.css +21 -5
  8. package/dist/default/define/audio/skin2.js +1 -1
  9. package/dist/default/define/extensions/google-analytics.js +6 -0
  10. package/dist/default/define/live-audio/compat-skin.css +54 -5
  11. package/dist/default/define/live-audio/compat-skin2.js +1 -1
  12. package/dist/default/define/live-audio/neutral-skin.css +8 -4
  13. package/dist/default/define/live-audio/neutral-skin2.js +1 -1
  14. package/dist/default/define/live-audio/scaffold-skin.css +45 -4
  15. package/dist/default/define/live-audio/scaffold-skin2.js +1 -1
  16. package/dist/default/define/live-audio/skin.css +6 -4
  17. package/dist/default/define/live-audio/skin2.js +1 -1
  18. package/dist/default/define/live-video/compat-skin.css +115 -13
  19. package/dist/default/define/live-video/compat-skin2.js +1 -1
  20. package/dist/default/define/live-video/neutral-skin.css +82 -14
  21. package/dist/default/define/live-video/neutral-skin2.js +1 -1
  22. package/dist/default/define/live-video/scaffold-skin.css +95 -13
  23. package/dist/default/define/live-video/scaffold-skin2.js +1 -1
  24. package/dist/default/define/live-video/skin.css +96 -16
  25. package/dist/default/define/live-video/skin2.js +1 -1
  26. package/dist/default/define/media/dailymotion-video.js +11 -0
  27. package/dist/default/define/media/mixcloud-audio.js +11 -0
  28. package/dist/default/define/media/soundcloud-audio.js +11 -0
  29. package/dist/default/define/video/compat-skin.css +115 -13
  30. package/dist/default/define/video/compat-skin2.js +1 -1
  31. package/dist/default/define/video/neutral-skin.css +83 -14
  32. package/dist/default/define/video/neutral-skin2.js +1 -1
  33. package/dist/default/define/video/scaffold-skin.css +95 -13
  34. package/dist/default/define/video/scaffold-skin2.js +1 -1
  35. package/dist/default/define/video/skin.css +94 -16
  36. package/dist/default/define/video/skin2.js +1 -1
  37. package/dist/default/extensions/google-analytics/extension.js +75 -0
  38. package/dist/default/extensions/mux-data/extension.js +7 -2
  39. package/dist/default/internal/skins/compat-audio/skin.css +72 -5
  40. package/dist/default/internal/skins/compat-audio/template.js +1 -1
  41. package/dist/default/internal/skins/compat-live-audio/skin.css +54 -5
  42. package/dist/default/internal/skins/compat-live-video/skin.css +115 -13
  43. package/dist/default/internal/skins/compat-video/skin.css +115 -13
  44. package/dist/default/internal/skins/default-audio/skin.css +21 -5
  45. package/dist/default/internal/skins/default-live-audio/skin.css +6 -4
  46. package/dist/default/internal/skins/default-live-video/skin.css +96 -16
  47. package/dist/default/internal/skins/default-video/skin.css +94 -16
  48. package/dist/default/internal/skins/neutral-audio/skin.css +23 -5
  49. package/dist/default/internal/skins/neutral-live-audio/skin.css +8 -4
  50. package/dist/default/internal/skins/neutral-live-video/skin.css +82 -14
  51. package/dist/default/internal/skins/neutral-video/skin.css +83 -14
  52. package/dist/default/internal/skins/scaffold-audio/skin.css +63 -4
  53. package/dist/default/internal/skins/scaffold-audio/template.js +1 -1
  54. package/dist/default/internal/skins/scaffold-live-audio/skin.css +45 -4
  55. package/dist/default/internal/skins/scaffold-live-video/skin.css +95 -13
  56. package/dist/default/internal/skins/scaffold-video/skin.css +95 -13
  57. package/dist/default/media/dailymotion-video/adapter.js +31 -0
  58. package/dist/default/media/hls-background-video/adapter.js +7 -0
  59. package/dist/default/media/mixcloud-audio/adapter.js +16 -0
  60. package/dist/default/media/soundcloud-audio/adapter.js +16 -0
  61. package/dist/default/player/element.js +1 -5
  62. package/dist/default/presets/background/skin.js +2 -2
  63. package/dist/default/presets/skin.js +4 -3
  64. package/dist/default/ui/dialog/element.js +13 -1
  65. package/dist/default/ui/gesture/element.js +3 -0
  66. package/dist/default/ui/media-button-element.js +10 -1
  67. package/dist/default/ui/playback-rate-button/element.js +7 -2
  68. package/dist/default/ui/playback-rate-radio-group/element.js +10 -3
  69. package/dist/default/ui/radio-options/controller.js +18 -5
  70. package/dist/default/version.js +1 -1
  71. package/dist/dev/define/audio/compat-skin.css +72 -5
  72. package/dist/dev/define/audio/compat-skin2.js +1 -1
  73. package/dist/dev/define/audio/compat-skin2.js.map +1 -1
  74. package/dist/dev/define/audio/neutral-skin.css +23 -5
  75. package/dist/dev/define/audio/neutral-skin2.js +1 -1
  76. package/dist/dev/define/audio/neutral-skin2.js.map +1 -1
  77. package/dist/dev/define/audio/scaffold-skin.css +63 -4
  78. package/dist/dev/define/audio/scaffold-skin2.js +1 -1
  79. package/dist/dev/define/audio/scaffold-skin2.js.map +1 -1
  80. package/dist/dev/define/audio/skin.css +21 -5
  81. package/dist/dev/define/audio/skin2.js +1 -1
  82. package/dist/dev/define/audio/skin2.js.map +1 -1
  83. package/dist/dev/define/extensions/google-analytics.d.ts +11 -0
  84. package/dist/dev/define/extensions/google-analytics.js +8 -0
  85. package/dist/dev/define/extensions/google-analytics.js.map +1 -0
  86. package/dist/dev/define/live-audio/compat-skin.css +54 -5
  87. package/dist/dev/define/live-audio/compat-skin2.js +1 -1
  88. package/dist/dev/define/live-audio/compat-skin2.js.map +1 -1
  89. package/dist/dev/define/live-audio/neutral-skin.css +8 -4
  90. package/dist/dev/define/live-audio/neutral-skin2.js +1 -1
  91. package/dist/dev/define/live-audio/neutral-skin2.js.map +1 -1
  92. package/dist/dev/define/live-audio/scaffold-skin.css +45 -4
  93. package/dist/dev/define/live-audio/scaffold-skin2.js +1 -1
  94. package/dist/dev/define/live-audio/scaffold-skin2.js.map +1 -1
  95. package/dist/dev/define/live-audio/skin.css +6 -4
  96. package/dist/dev/define/live-audio/skin2.js +1 -1
  97. package/dist/dev/define/live-audio/skin2.js.map +1 -1
  98. package/dist/dev/define/live-video/compat-skin.css +115 -13
  99. package/dist/dev/define/live-video/compat-skin2.js +1 -1
  100. package/dist/dev/define/live-video/compat-skin2.js.map +1 -1
  101. package/dist/dev/define/live-video/neutral-skin.css +82 -14
  102. package/dist/dev/define/live-video/neutral-skin2.js +1 -1
  103. package/dist/dev/define/live-video/neutral-skin2.js.map +1 -1
  104. package/dist/dev/define/live-video/scaffold-skin.css +95 -13
  105. package/dist/dev/define/live-video/scaffold-skin2.js +1 -1
  106. package/dist/dev/define/live-video/scaffold-skin2.js.map +1 -1
  107. package/dist/dev/define/live-video/skin.css +96 -16
  108. package/dist/dev/define/live-video/skin2.js +1 -1
  109. package/dist/dev/define/live-video/skin2.js.map +1 -1
  110. package/dist/dev/define/media/dailymotion-video.d.ts +15 -0
  111. package/dist/dev/define/media/dailymotion-video.js +13 -0
  112. package/dist/dev/define/media/dailymotion-video.js.map +1 -0
  113. package/dist/dev/define/media/mixcloud-audio.d.ts +15 -0
  114. package/dist/dev/define/media/mixcloud-audio.js +13 -0
  115. package/dist/dev/define/media/mixcloud-audio.js.map +1 -0
  116. package/dist/dev/define/media/soundcloud-audio.d.ts +15 -0
  117. package/dist/dev/define/media/soundcloud-audio.js +13 -0
  118. package/dist/dev/define/media/soundcloud-audio.js.map +1 -0
  119. package/dist/dev/define/video/compat-skin.css +115 -13
  120. package/dist/dev/define/video/compat-skin2.js +1 -1
  121. package/dist/dev/define/video/compat-skin2.js.map +1 -1
  122. package/dist/dev/define/video/neutral-skin.css +83 -14
  123. package/dist/dev/define/video/neutral-skin2.js +1 -1
  124. package/dist/dev/define/video/neutral-skin2.js.map +1 -1
  125. package/dist/dev/define/video/scaffold-skin.css +95 -13
  126. package/dist/dev/define/video/scaffold-skin2.js +1 -1
  127. package/dist/dev/define/video/scaffold-skin2.js.map +1 -1
  128. package/dist/dev/define/video/skin.css +94 -16
  129. package/dist/dev/define/video/skin2.js +1 -1
  130. package/dist/dev/define/video/skin2.js.map +1 -1
  131. package/dist/dev/extensions/google-analytics/extension.d.ts +52 -0
  132. package/dist/dev/extensions/google-analytics/extension.js +77 -0
  133. package/dist/dev/extensions/google-analytics/extension.js.map +1 -0
  134. package/dist/dev/extensions/google-analytics/index.d.ts +2 -0
  135. package/dist/dev/extensions/mux-data/extension.d.ts +4 -1
  136. package/dist/dev/extensions/mux-data/extension.js +7 -2
  137. package/dist/dev/extensions/mux-data/extension.js.map +1 -1
  138. package/dist/dev/index.d.ts +3 -3
  139. package/dist/dev/internal/skins/compat-audio/skin.css +72 -5
  140. package/dist/dev/internal/skins/compat-audio/template.js +1 -1
  141. package/dist/dev/internal/skins/compat-audio/template.js.map +1 -1
  142. package/dist/dev/internal/skins/compat-live-audio/skin.css +54 -5
  143. package/dist/dev/internal/skins/compat-live-video/skin.css +115 -13
  144. package/dist/dev/internal/skins/compat-video/skin.css +115 -13
  145. package/dist/dev/internal/skins/default-audio/skin.css +21 -5
  146. package/dist/dev/internal/skins/default-live-audio/skin.css +6 -4
  147. package/dist/dev/internal/skins/default-live-video/skin.css +96 -16
  148. package/dist/dev/internal/skins/default-video/skin.css +94 -16
  149. package/dist/dev/internal/skins/neutral-audio/skin.css +23 -5
  150. package/dist/dev/internal/skins/neutral-live-audio/skin.css +8 -4
  151. package/dist/dev/internal/skins/neutral-live-video/skin.css +82 -14
  152. package/dist/dev/internal/skins/neutral-video/skin.css +83 -14
  153. package/dist/dev/internal/skins/scaffold-audio/skin.css +63 -4
  154. package/dist/dev/internal/skins/scaffold-audio/template.js +1 -1
  155. package/dist/dev/internal/skins/scaffold-audio/template.js.map +1 -1
  156. package/dist/dev/internal/skins/scaffold-live-audio/skin.css +45 -4
  157. package/dist/dev/internal/skins/scaffold-live-video/skin.css +95 -13
  158. package/dist/dev/internal/skins/scaffold-video/skin.css +95 -13
  159. package/dist/dev/media/dailymotion-video/adapter.d.ts +17 -0
  160. package/dist/dev/media/dailymotion-video/adapter.js +47 -0
  161. package/dist/dev/media/dailymotion-video/adapter.js.map +1 -0
  162. package/dist/dev/media/dailymotion-video/index.d.ts +2 -0
  163. package/dist/dev/media/hls-background-video/adapter.d.ts +6 -1
  164. package/dist/dev/media/hls-background-video/adapter.js +7 -0
  165. package/dist/dev/media/hls-background-video/adapter.js.map +1 -1
  166. package/dist/dev/media/mixcloud-audio/adapter.d.ts +11 -0
  167. package/dist/dev/media/mixcloud-audio/adapter.js +52 -0
  168. package/dist/dev/media/mixcloud-audio/adapter.js.map +1 -0
  169. package/dist/dev/media/mixcloud-audio/index.d.ts +2 -0
  170. package/dist/dev/media/soundcloud-audio/adapter.d.ts +11 -0
  171. package/dist/dev/media/soundcloud-audio/adapter.js +53 -0
  172. package/dist/dev/media/soundcloud-audio/adapter.js.map +1 -0
  173. package/dist/dev/media/soundcloud-audio/index.d.ts +2 -0
  174. package/dist/dev/player/element.js +1 -5
  175. package/dist/dev/player/element.js.map +1 -1
  176. package/dist/dev/presets/background/skin.d.ts +2 -1
  177. package/dist/dev/presets/background/skin.js +2 -2
  178. package/dist/dev/presets/background/skin.js.map +1 -1
  179. package/dist/dev/presets/skin.d.ts +4 -3
  180. package/dist/dev/presets/skin.js +4 -3
  181. package/dist/dev/presets/skin.js.map +1 -1
  182. package/dist/dev/ui/dialog/element.js +13 -1
  183. package/dist/dev/ui/dialog/element.js.map +1 -1
  184. package/dist/dev/ui/gesture/element.js +3 -0
  185. package/dist/dev/ui/gesture/element.js.map +1 -1
  186. package/dist/dev/ui/media-button-element.d.ts +9 -0
  187. package/dist/dev/ui/media-button-element.js +10 -1
  188. package/dist/dev/ui/media-button-element.js.map +1 -1
  189. package/dist/dev/ui/play-button/element.d.ts +2 -0
  190. package/dist/dev/ui/playback-rate-button/element.d.ts +9 -1
  191. package/dist/dev/ui/playback-rate-button/element.js +7 -2
  192. package/dist/dev/ui/playback-rate-button/element.js.map +1 -1
  193. package/dist/dev/ui/playback-rate-radio-group/element.d.ts +4 -0
  194. package/dist/dev/ui/playback-rate-radio-group/element.js +10 -3
  195. package/dist/dev/ui/playback-rate-radio-group/element.js.map +1 -1
  196. package/dist/dev/ui/radio-options/controller.js +18 -5
  197. package/dist/dev/ui/radio-options/controller.js.map +1 -1
  198. package/dist/dev/version.js +1 -1
  199. package/docs/README.md +1 -1
  200. package/docs/guides/autoplay.md +1 -1
  201. package/docs/guides/browser-support.md +2 -0
  202. package/docs/guides/build-your-own-skin.md +3 -1
  203. package/docs/guides/cdn.md +10 -9
  204. package/docs/guides/content-security-policy.md +3 -0
  205. package/docs/guides/customize-skins.md +4 -2
  206. package/docs/guides/features.md +1 -1
  207. package/docs/guides/google-analytics.md +199 -0
  208. package/docs/guides/installation-cdn.md +4 -4
  209. package/docs/guides/installation-shadcn.md +3 -3
  210. package/docs/guides/installation-svelte.md +4 -4
  211. package/docs/guides/installation-vue.md +4 -4
  212. package/docs/guides/installation.md +4 -4
  213. package/docs/guides/internationalization.md +5 -5
  214. package/docs/guides/keyboard-shortcuts.md +1 -1
  215. package/docs/guides/llms.txt +2 -1
  216. package/docs/guides/media-sources.md +3 -0
  217. package/docs/guides/migrate-from-media-chrome.md +4 -4
  218. package/docs/guides/migrate-from-mux-player.md +9 -9
  219. package/docs/guides/migrate-from-plyr.md +8 -8
  220. package/docs/guides/migrate-from-video-js-8.md +8 -9
  221. package/docs/guides/migrate-from-vidstack.md +8 -8
  222. package/docs/guides/mux-data.md +22 -0
  223. package/docs/guides/presets.md +1 -1
  224. package/docs/guides/self-hosting.md +5 -5
  225. package/docs/guides/skins.md +16 -1
  226. package/docs/guides/ui-components.md +1 -1
  227. package/docs/llms.txt +10 -5
  228. package/docs/reference/api/feature-playback-rate.md +54 -3
  229. package/docs/reference/api/feature-playback.md +5 -1
  230. package/docs/reference/api/html-create-player.md +2 -2
  231. package/docs/reference/api/llms.txt +1 -1
  232. package/docs/reference/api/media-capabilities.md +1 -1
  233. package/docs/reference/api/player-store.md +6 -3
  234. package/docs/reference/api/preset-audio.md +13 -5
  235. package/docs/reference/api/preset-background.md +2 -2
  236. package/docs/reference/api/preset-live-audio.md +13 -5
  237. package/docs/reference/api/preset-live-video.md +13 -5
  238. package/docs/reference/api/preset-video.md +13 -5
  239. package/docs/reference/api/resolve-adapter-type.md +4 -1
  240. package/docs/reference/api/ui-element.md +2 -2
  241. package/docs/reference/components/alert-dialog.md +21 -16
  242. package/docs/reference/components/audio-compat-skin.md +8 -2
  243. package/docs/reference/components/audio-neutral-skin.md +2 -2
  244. package/docs/reference/components/audio-scaffold-skin.md +2 -2
  245. package/docs/reference/components/audio-skin.md +2 -2
  246. package/docs/reference/components/audio-track-radio-group.md +2 -2
  247. package/docs/reference/components/background-video-skin.md +1 -1
  248. package/docs/reference/components/background-video.md +1 -1
  249. package/docs/reference/components/buffering-indicator.md +2 -2
  250. package/docs/reference/components/captions-radio-group.md +2 -2
  251. package/docs/reference/components/cloudflare-video.md +1 -1
  252. package/docs/reference/components/dailymotion-video.md +192 -0
  253. package/docs/reference/components/dash-video.md +2 -1
  254. package/docs/reference/components/dialog.md +49 -22
  255. package/docs/reference/components/error-dialog.md +13 -10
  256. package/docs/reference/components/gesture.md +2 -2
  257. package/docs/reference/components/google-analytics.md +51 -0
  258. package/docs/reference/components/google-cast.md +1 -1
  259. package/docs/reference/components/hls-audio.md +1 -1
  260. package/docs/reference/components/hls-background-video.md +4 -1
  261. package/docs/reference/components/hls-video.md +1 -1
  262. package/docs/reference/components/hlsjs-video.md +3 -1
  263. package/docs/reference/components/hotkey.md +2 -2
  264. package/docs/reference/components/live-audio-compat-skin.md +8 -2
  265. package/docs/reference/components/live-audio-neutral-skin.md +2 -2
  266. package/docs/reference/components/live-audio-scaffold-skin.md +2 -2
  267. package/docs/reference/components/live-audio-skin.md +2 -2
  268. package/docs/reference/components/live-video-compat-skin.md +8 -2
  269. package/docs/reference/components/live-video-neutral-skin.md +2 -2
  270. package/docs/reference/components/live-video-scaffold-skin.md +2 -2
  271. package/docs/reference/components/live-video-skin.md +2 -2
  272. package/docs/reference/components/llms.txt +9 -5
  273. package/docs/reference/components/mixcloud-audio.md +203 -0
  274. package/docs/reference/components/mux-audio.md +3 -1
  275. package/docs/reference/components/mux-background-video.md +1 -1
  276. package/docs/reference/components/mux-data.md +20 -2
  277. package/docs/reference/components/mux-video.md +3 -1
  278. package/docs/reference/components/native-hls-video.md +2 -1
  279. package/docs/reference/components/play-button.md +7 -5
  280. package/docs/reference/components/playback-rate-button.md +26 -7
  281. package/docs/reference/components/playback-rate-radio-group.md +7 -4
  282. package/docs/reference/components/player.md +3 -3
  283. package/docs/reference/components/playerjs-video.md +1 -1
  284. package/docs/reference/components/quality-radio-group.md +2 -2
  285. package/docs/reference/components/shaka-video.md +2 -1
  286. package/docs/reference/components/soundcloud-audio.md +227 -0
  287. package/docs/reference/components/spotify-audio.md +2 -2
  288. package/docs/reference/components/tiktok-video.md +2 -2
  289. package/docs/reference/components/twitch-video.md +2 -3
  290. package/docs/reference/components/video-compat-skin.md +8 -2
  291. package/docs/reference/components/video-neutral-skin.md +2 -2
  292. package/docs/reference/components/video-scaffold-skin.md +2 -2
  293. package/docs/reference/components/video-skin.md +2 -2
  294. package/docs/reference/components/vimeo-video.md +2 -1
  295. package/docs/reference/components/wistia-video.md +1 -1
  296. package/docs/reference/components/youtube-video.md +2 -1
  297. package/package.json +60 -40
@@ -2,7 +2,7 @@
2
2
 
3
3
  Playback speed state and actions for the player store
4
4
 
5
- Controls speed of playback.
5
+ Controls speed of playback. `playbackRateAvailability` is `unsupported` when the media has no playback rate, such as an embed whose provider takes no speed command.
6
6
 
7
7
  ## Import
8
8
 
@@ -14,23 +14,74 @@ The `audioFeatures` and `videoFeatures` [feature bundles](../../guides/presets.m
14
14
 
15
15
  ## API Reference
16
16
 
17
+ ### Configuration
18
+
19
+ Attributes and matching properties the player element accepts. They exist only while this feature is selected.
20
+
21
+ | Prop | Type | Default | Description |
22
+ | --- | --- | --- | --- |
23
+ | `defaultPlaybackRates` (attribute `default-playback-rates`) | `undefined \| null \| readonly number[] \| string` | `[0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]` | Rates the player's controls offer, in the order they cycle through them, unless a control sets its own `rates`. HTML takes a space-separated list, such as `default-playback-rates="0.5 1 1.5 2"`. Missing or empty input restores the defaults. Rates outside the media's range are left out, so YouTube, which plays up to `2`, may offer fewer. |
24
+
17
25
  ### State
18
26
 
19
27
  | Property | Type | Description |
20
28
  | --- | --- | --- |
21
- | `playbackRates` | `readonly number[]` | Available playback rates. |
22
29
  | `playbackRate` | `number` | Current playback rate. |
30
+ | `playbackRateAvailability` | `'available' \| 'unavailable' \| 'unsupported'` | Whether the media can change its playback rate. `unsupported` when the attached media has no `playbackRate` at all, such as an embed whose provider takes no speed command. |
31
+ | `playbackRates` | `readonly number[]` | The default rates that fit the media's range. Set them through the player, not through the store. They are listed even when the media cannot change its rate, so check `playbackRateAvailability` before offering them. |
23
32
 
24
33
  ### Actions
25
34
 
26
35
  | Action | Type | Description |
27
36
  | --- | --- | --- |
28
- | `setPlaybackRate` | `(rate: number) => void` | Set the playback rate. |
37
+ | `setPlaybackRate` | `(rate: number) => void` | Set the playback rate, clamped to the rates the media accepts. |
38
+
39
+ ### Playback rates
40
+
41
+ The player offers `0.5` through `2` in steps of `0.25` unless you set your own list. The [playback rate button](../components/playback-rate-button.md), the [playback rate radio group](../components/playback-rate-radio-group.md), and the `speedUp` and `speedDown` [hotkeys](../../guides/keyboard-shortcuts.md) use this list unless you give one of them its own.
42
+
43
+ Set the `default-playback-rates` attribute on [`<video-player>`](../components/player.md) to a space-separated list:
44
+
45
+ ```html
46
+ <video-player default-playback-rates="0.5 1 1.25 1.5 2">
47
+ <media-container>
48
+ <video src="/video.mp4"></video>
49
+ </media-container>
50
+ </video-player>
51
+ ```
52
+
53
+ The `defaultPlaybackRates` property also takes an array, such as `player.defaultPlaybackRates = [1, 2]`. Removing the attribute restores the defaults.
54
+
55
+ The button cycles through the rates in the order you list them, and the menu shows them in that order. `speedUp` and `speedDown` move to the next faster or slower rate whatever the order, and do nothing at the fastest or slowest rate. The player ignores values that aren’t positive numbers, and repeated rates. If nothing usable is left, it falls back to the defaults.
56
+
57
+ ### Rates for one control
58
+
59
+ To give one control a different list, set `rates` on it. The rest of the player keeps the default list. The control offers these rates as given, even ones outside the media’s range, which play at the nearest end of the range.
60
+
61
+ ```html
62
+ <media-playback-rate-button rates="1 1.5 2"></media-playback-rate-button>
63
+ ```
64
+
65
+ To make the speed hotkeys change speed in fixed steps instead, give `speedUp` and `speedDown` a `value`. A `value` of `0.1` moves from `1` to `1.1`, then `1.2`, and so on.
66
+
67
+ ### Rates outside the list
68
+
69
+ The media owns the current rate, so it can be one the menu doesn’t offer, such as `1.1` set through the media API or a stepped hotkey. The menu then shows that rate as an extra item, slotted before the next faster rate. Skins set it in italics, and its accessible name is “Custom, 1.1×”. The item goes away once the rate is back on the list. Normal speed (`1`) is added the same way when your list leaves it out, but isn’t marked custom.
70
+
71
+ ### Media range
72
+
73
+ Each media accepts rates within a range. Browsers play `0.0625` through `16`, YouTube `0.25` through `2`, and Vimeo up to `2`. The player leaves out any `defaultPlaybackRates` outside that range and keeps the rest in your order. If none are left, it offers the defaults within the range and warns in development. `setPlaybackRate` clamps a rate outside the range to the nearest end, and warns in development. That includes `0`, which would stop the picture while the player still reports playback; call `pause()` instead.
74
+
75
+ `playbackRates` lists rates even for a media that can’t change its rate, so check `playbackRateAvailability` before offering them.
76
+
77
+ YouTube rounds rates down to a step of `0.05`, so asking for `1.13` plays at `1.1`.
29
78
 
30
79
  ### Selector
31
80
 
32
81
  Pass `selectPlaybackRate` to [`PlayerController`](./player-controller.md) to subscribe to playback rate state. Returns `undefined` if the playback rate feature is not configured.
33
82
 
83
+ Check `playbackRateAvailability` before showing a playback rate control.
84
+
34
85
  **rate-display.ts**
35
86
 
36
87
  ```ts
@@ -4,6 +4,8 @@ Play/pause state and actions for the player store
4
4
 
5
5
  Controls play/pause state and tracks whether playback has started or is stalled.
6
6
 
7
+ When the media has `autoplay`, `autoplaying` is true from the moment a source loads until playback starts. It also turns false when the autoplay is refused: browsers don’t announce that, so it shows as the media being able to play through but staying paused, and embeds report it with a `pause` or `error` event. Treat it as playback about to begin: the play button shows pause and the buffering indicator shows while it’s true, and `pause()` cancels it.
8
+
7
9
  ## Import
8
10
 
9
11
  ```ts
@@ -22,13 +24,15 @@ The `audioFeatures`, `liveAudioFeatures`, `liveVideoFeatures`, and `videoFeature
22
24
  | `ended` | `boolean` | Whether playback has reached the end. |
23
25
  | `started` | `boolean` | Whether playback has started (played or seeked). |
24
26
  | `waiting` | `boolean` | Whether playback is stalled waiting for data. |
27
+ | `autoplay` | `boolean` | Whether the media starts playing on its own once it can. |
28
+ | `autoplaying` | `boolean` | Whether the media is trying to autoplay: `autoplay` is set, and playback hasn't started yet. Clears when playback starts, when `pause()` cancels it, and when the autoplay is refused. Browsers don't announce a refusal, so it shows as the media being able to play through but staying paused; embeds report one with a `pause` or `error` event. Controls treat it as playback that's about to begin. |
25
29
 
26
30
  ### Actions
27
31
 
28
32
  | Action | Type | Description |
29
33
  | --- | --- | --- |
30
34
  | `play` | `() => Promise<void>` | Start playback. Updates `paused` immediately when the media starts. |
31
- | `pause` | `() => void` | Pause playback. Updates `paused` immediately. |
35
+ | `pause` | `() => void` | Pause playback. Updates `paused` immediately, and cancels a pending autoplay. |
32
36
 
33
37
  ### Selector
34
38
 
@@ -175,7 +175,7 @@ Creates a typed HTML player class and bound controller.
175
175
 
176
176
  | Parameter | Type | Default | Description |
177
177
  | --- | --- | --- | --- |
178
- | `config` (required) | `{ features: [PlayerFeature<MediaPlaybackState>, PlayerFeature<MediaPlaybackRateState>, PlayerFeature<MediaQualityState>, PlayerFeature<MediaAudioTrackState>, PlayerFeature<MediaVolumeState>, PlayerFeature<MediaTimeState>, PlayerFeature<MediaSourceState>, PlayerFeature<MediaBufferState>, PlayerFeature<MediaFullscreenState>, PlayerFeature<MediaPictureInPictureState>, PlayerFeature<MediaRemotePlaybackState>, PlayerFeature<MediaControlsState>, PlayerFeature<MediaTextTrackState>, PlayerFeature<MediaErrorState>, typeof metadataFeature] }` | — | Player configuration with features. |
178
+ | `config` (required) | `{ features: [PlayerFeature<MediaPlaybackState>, typeof playbackRateFeature, PlayerFeature<MediaQualityState>, PlayerFeature<MediaAudioTrackState>, PlayerFeature<MediaVolumeState>, PlayerFeature<MediaTimeState>, PlayerFeature<MediaSourceState>, PlayerFeature<MediaBufferState>, PlayerFeature<MediaFullscreenState>, PlayerFeature<MediaPictureInPictureState>, PlayerFeature<MediaRemotePlaybackState>, PlayerFeature<MediaControlsState>, PlayerFeature<MediaTextTrackState>, PlayerFeature<MediaErrorState>, typeof metadataFeature] }` | — | Player configuration with features. |
179
179
 
180
180
  #### Return Value
181
181
 
@@ -195,7 +195,7 @@ Creates a typed HTML audio player class and bound controller.
195
195
 
196
196
  | Parameter | Type | Default | Description |
197
197
  | --- | --- | --- | --- |
198
- | `config` (required) | `{ features: [PlayerFeature<MediaPlaybackState>, PlayerFeature<MediaPlaybackRateState>, PlayerFeature<MediaVolumeState>, PlayerFeature<MediaTimeState>, PlayerFeature<MediaSourceState>, PlayerFeature<MediaBufferState>, PlayerFeature<MediaErrorState>, typeof metadataFeature] }` | — | Player configuration with features. |
198
+ | `config` (required) | `{ features: [PlayerFeature<MediaPlaybackState>, typeof playbackRateFeature, PlayerFeature<MediaVolumeState>, PlayerFeature<MediaTimeState>, PlayerFeature<MediaSourceState>, PlayerFeature<MediaBufferState>, PlayerFeature<MediaErrorState>, typeof metadataFeature] }` | — | Player configuration with features. |
199
199
 
200
200
  #### Return Value
201
201
 
@@ -1,6 +1,6 @@
1
1
  # Video.js v10 — HTML API
2
2
 
3
- > API reference for the player factory, presets, store controllers, features, translation tools, and utilities. Bundled with `@videojs/html` v10.2.0. Links are relative paths to files in this directory.
3
+ > API reference for the player factory, presets, store controllers, features, translation tools, and utilities. Bundled with `@videojs/html` v10.3.0. Links are relative paths to files in this directory.
4
4
 
5
5
  ## Player
6
6
 
@@ -38,7 +38,7 @@ Each `isMedia*Capable` guard accepts any value and returns `false` for `null`, `
38
38
 
39
39
  A guard checks that a few members of a capability are present, then narrows to every member of that capability’s contract. The table lists both.
40
40
 
41
- Some media, such as embeds, can’t provide buffered ranges, text tracks, or remote playback, and report a shared empty placeholder in their place. `isMediaBufferCapable`, `isMediaTextTrackCapable`, and `isMediaRemotePlaybackCapable` return `false` for that placeholder.
41
+ Some media can’t provide buffered ranges, text tracks, or remote playback, and report a shared empty placeholder in their place. `isMediaBufferCapable`, `isMediaTextTrackCapable`, and `isMediaRemotePlaybackCapable` return `false` for that placeholder. Media that can provide buffered ranges but has none yet, such as an embed before it loads, reports an empty range that is not the placeholder, so `isMediaBufferCapable` returns `true`.
42
42
 
43
43
  A guard describes what the media object supports, not its current state. `isMediaErrorCapable` returns `true` while `error` is `null`, and `isMediaVolumeCapable` returns `true` on platforms that ignore volume changes. For current state and availability, such as `volumeAvailability` from the [volume feature](./feature-volume.md), read the player’s [features](../../guides/features.md) instead.
44
44
 
@@ -31,8 +31,10 @@ Each feature links to the same entry on its reference page.
31
31
  | `ended` | `boolean` | [`playbackFeature`](./feature-playback.md#playback-state-ended) | Whether playback has reached the end. |
32
32
  | `started` | `boolean` | [`playbackFeature`](./feature-playback.md#playback-state-started) | Whether playback has started (played or seeked). |
33
33
  | `waiting` | `boolean` | [`playbackFeature`](./feature-playback.md#playback-state-waiting) | Whether playback is stalled waiting for data. |
34
+ | `autoplay` | `boolean` | [`playbackFeature`](./feature-playback.md#playback-state-autoplay) | Whether the media starts playing on its own once it can. |
35
+ | `autoplaying` | `boolean` | [`playbackFeature`](./feature-playback.md#playback-state-autoplaying) | Whether the media is trying to autoplay: `autoplay` is set, and playback hasn't started yet. Clears when playback starts, when `pause()` cancels it, and when the autoplay is refused. Browsers don't announce a refusal, so it shows as the media being able to play through but staying paused; embeds report one with a `pause` or `error` event. Controls treat it as playback that's about to begin. |
34
36
  | `play` | `() => Promise<void>` | [`playbackFeature`](./feature-playback.md#playback-action-play) | Start playback. Updates `paused` immediately when the media starts. |
35
- | `pause` | `() => void` | [`playbackFeature`](./feature-playback.md#playback-action-pause) | Pause playback. Updates `paused` immediately. |
37
+ | `pause` | `() => void` | [`playbackFeature`](./feature-playback.md#playback-action-pause) | Pause playback. Updates `paused` immediately, and cancels a pending autoplay. |
36
38
  | `currentTime` | `number` | [`timeFeature`](./feature-time.md#time-state-currentTime) | Current playback position in seconds. |
37
39
  | `duration` | `number` | [`timeFeature`](./feature-time.md#time-state-duration) | Total duration in seconds (0 if unknown). |
38
40
  | `seeking` | `boolean` | [`timeFeature`](./feature-time.md#time-state-seeking) | Whether a seek operation is in progress. |
@@ -59,9 +61,10 @@ Each feature links to the same entry on its reference page.
59
61
  | `thumbnailsTrack` | `{ cues: MediaTextCue[]; src: string \| null; crossOrigin: 'anonymous' \| 'use-credentials' \| null } \| null` | [`textTrackFeature`](./feature-text-tracks.md#textTrack-state-thumbnailsTrack) | The first thumbnails track, or `null` when there is none. |
60
62
  | `toggleSubtitles` | `(forceShow?: boolean) => boolean` | [`textTrackFeature`](./feature-text-tracks.md#textTrack-action-toggleSubtitles) | Toggle captions/subtitles visibility. Showing enables one caption/subtitle track. A track already showing stays selected. Otherwise, selection prefers the last track shown, then a track matching the browser language, then the first available track. Returns whether a track is showing. |
61
63
  | `selectSubtitlesTrack` | `(id: string \| null) => void` | [`textTrackFeature`](./feature-text-tracks.md#textTrack-action-selectSubtitlesTrack) | Show the captions/subtitles track with `id`, or turn captions/subtitles off with `null`. |
62
- | `playbackRates` | `readonly number[]` | [`playbackRateFeature`](./feature-playback-rate.md#playbackRate-state-playbackRates) | Available playback rates. |
63
64
  | `playbackRate` | `number` | [`playbackRateFeature`](./feature-playback-rate.md#playbackRate-state-playbackRate) | Current playback rate. |
64
- | `setPlaybackRate` | `(rate: number) => void` | [`playbackRateFeature`](./feature-playback-rate.md#playbackRate-action-setPlaybackRate) | Set the playback rate. |
65
+ | `playbackRateAvailability` | `'available' \| 'unavailable' \| 'unsupported'` | [`playbackRateFeature`](./feature-playback-rate.md#playbackRate-state-playbackRateAvailability) | Whether the media can change its playback rate. `unsupported` when the attached media has no `playbackRate` at all, such as an embed whose provider takes no speed command. |
66
+ | `playbackRates` | `readonly number[]` | [`playbackRateFeature`](./feature-playback-rate.md#playbackRate-state-playbackRates) | The default rates that fit the media's range. Set them through the player, not through the store. They are listed even when the media cannot change its rate, so check `playbackRateAvailability` before offering them. |
67
+ | `setPlaybackRate` | `(rate: number) => void` | [`playbackRateFeature`](./feature-playback-rate.md#playbackRate-action-setPlaybackRate) | Set the playback rate, clamped to the rates the media accepts. |
65
68
  | `isPictureInPicture` | `boolean` | [`pipFeature`](./feature-pip.md#pip-state-isPictureInPicture) | Whether picture-in-picture mode is currently active. |
66
69
  | `pictureInPictureAvailability` | `'available' \| 'unavailable' \| 'unsupported'` | [`pipFeature`](./feature-pip.md#pip-state-pictureInPictureAvailability) | Whether picture-in-picture can be requested on this platform. |
67
70
  | `requestPictureInPicture` | `() => Promise<void>` | [`pipFeature`](./feature-pip.md#pip-action-requestPictureInPicture) | Enter picture-in-picture mode, exiting fullscreen first. Rejects before metadata is loaded. |
@@ -2,7 +2,7 @@
2
2
 
3
3
  The audio-only preset — a player, feature bundle, skins, and media for on-demand audio
4
4
 
5
- `@videojs/html/audio` is the preset for on-demand audio. It bundles the `<audio-player>` element, the `audioFeatures` bundle it is configured with, and two skins, and plays through the browser’s native `<audio>`. See [Presets](../../guides/presets.md) for how presets fit together and how to customize one.
5
+ `@videojs/html/audio` is the preset for on-demand audio. It bundles the `<audio-player>` element, the `audioFeatures` bundle it is configured with, and four skins, and plays through the browser’s native `<audio>`. See [Presets](../../guides/presets.md) for how presets fit together and how to customize one.
6
6
 
7
7
  ## Import
8
8
 
@@ -11,13 +11,13 @@ import '@videojs/html/audio/player';
11
11
  import '@videojs/html/audio/skin';
12
12
  ```
13
13
 
14
- Import `@videojs/html/audio/neutral-skin` instead for the neutral skin. Or load one [CDN](../../guides/cdn.md) bundle that registers the player and a skin together:
14
+ Import `@videojs/html/audio/neutral-skin`, `compat-skin`, or `scaffold-skin` instead for another skin. Or load one [CDN](../../guides/cdn.md) bundle that registers the player and a skin together:
15
15
 
16
16
  ```html
17
- <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.2.0/audio.js"></script>
17
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.3.0/audio.js"></script>
18
18
  ```
19
19
 
20
- `audio-neutral.js` registers the neutral skin instead, and `audio-player.js` registers `<audio-player>` alone.
20
+ `audio-neutral.js`, `audio-compat.js`, and `audio-scaffold.js` register the other skins instead, and `audio-player.js` registers `<audio-player>` alone.
21
21
 
22
22
  ## Usage
23
23
 
@@ -44,7 +44,7 @@ Import `@videojs/html/audio/neutral-skin` instead for the neutral skin. Or load
44
44
  | --- | --- | --- |
45
45
  | `content-title` | `contentTitle` | The title to display. Takes precedence over the title the media reports. |
46
46
  | `poster` | `poster` | The poster to display. Takes precedence over the poster the media reports. |
47
- | `keep-alive` | — | Keeps the player and its store alive when the element leaves the DOM. Call `destroy()` when you’re done with it. |
47
+ | `keep-alive` | — | Keeps the player, its store, and the UI elements inside it alive when the element leaves the DOM. Call `destroy()` when you’re done with it. |
48
48
 
49
49
  `content-title` and `poster` come from the [metadata feature](./feature-metadata.md#player-inputs). The element’s read-only `store` property returns its player store.
50
50
 
@@ -88,6 +88,10 @@ customElements.define('my-audio-player', PlayerElement);
88
88
 
89
89
  - [AudioSkin](../components/audio-skin.md) — the default skin, with the modern, frosted look.
90
90
  - [NeutralAudioSkin](../components/audio-neutral-skin.md) — the visually lighter variant, closer to a classic control bar.
91
+ - [CompatAudioSkin](../components/audio-compat-skin.md) — the plain, unbranded variant that avoids newer visual effects, so it looks consistent across browsers.
92
+ - [ScaffoldAudioSkin](../components/audio-scaffold-skin.md) — the minimally styled variant of Compat, a foundation for your own design.
93
+
94
+ See [Choose a skin](../../guides/skins.md#choose-a-skin) to compare them.
91
95
 
92
96
  ## Media
93
97
 
@@ -104,6 +108,8 @@ The preset root, `@videojs/html/audio`, has no side effects. Importing it never
104
108
  | `audioFeatures` | The [feature bundle](#feature-bundle). |
105
109
  | `AudioSkinElement` | The default [skin](#skins) element class. |
106
110
  | `NeutralAudioSkinElement` | The neutral [skin](#skins) element class. |
111
+ | `CompatAudioSkinElement` | The compat [skin](#skins) element class. |
112
+ | `ScaffoldAudioSkinElement` | The scaffold [skin](#skins) element class. |
107
113
 
108
114
  Registration entry points are side-effect-only:
109
115
 
@@ -112,5 +118,7 @@ Registration entry points are side-effect-only:
112
118
  | `@videojs/html/audio/player` | `<audio-player>` |
113
119
  | `@videojs/html/audio/skin` | `<audio-skin>`, `<media-container>`, and the UI elements the skin composes |
114
120
  | `@videojs/html/audio/neutral-skin` | `<audio-neutral-skin>`, `<media-container>`, and the UI elements the neutral skin composes |
121
+ | `@videojs/html/audio/compat-skin` | `<audio-compat-skin>`, `<media-container>`, and the UI elements the compat skin composes |
122
+ | `@videojs/html/audio/scaffold-skin` | `<audio-scaffold-skin>`, `<media-container>`, and the UI elements the scaffold skin composes |
115
123
  | `@videojs/html/audio/ui` | `<media-container>` and the UI elements of the default skin, without the skin, for a layout you write yourself |
116
124
  | `@videojs/html/audio/neutral-ui` | `<media-container>` and the UI elements of the neutral skin, without the skin |
@@ -15,7 +15,7 @@ import '@videojs/html/background/video';
15
15
  Or load the [CDN](../../guides/cdn.md) bundle that registers all three:
16
16
 
17
17
  ```html
18
- <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.2.0/background.js"></script>
18
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.3.0/background.js"></script>
19
19
  ```
20
20
 
21
21
  Unlike the other presets, the background preset has one bundle and no player-only bundle.
@@ -44,7 +44,7 @@ Unlike the other presets, the background preset has one bundle and no player-onl
44
44
 
45
45
  | Attribute | Property | Description |
46
46
  | --- | --- | --- |
47
- | `keep-alive` | — | Keeps the player and its store alive when the element leaves the DOM. Call `destroy()` when you’re done with it. |
47
+ | `keep-alive` | — | Keeps the player, its store, and the UI elements inside it alive when the element leaves the DOM. Call `destroy()` when you’re done with it. |
48
48
 
49
49
  The bundle has no feature that takes player inputs, so the element has no player-input attributes such as `content-title` or `poster`; `keep-alive` is the only attribute it reads. Its read-only `store` property returns its player store.
50
50
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  The live audio preset — a player, feature bundle, skins, and media for live audio streams
4
4
 
5
- `@videojs/html/live-audio` is the preset for live audio streams. It bundles the `<live-audio-player>` element, the `liveAudioFeatures` bundle it is configured with, and two skins that swap the time slider and time displays for a Live button, and plays through the browser’s native `<audio>`. See [Presets](../../guides/presets.md) for how presets fit together and [Live streams](../../guides/live-streams.md) for playing a live source.
5
+ `@videojs/html/live-audio` is the preset for live audio streams. It bundles the `<live-audio-player>` element, the `liveAudioFeatures` bundle it is configured with, and four skins that swap the time slider and time displays for a Live button, and plays through the browser’s native `<audio>`. See [Presets](../../guides/presets.md) for how presets fit together and [Live streams](../../guides/live-streams.md) for playing a live source.
6
6
 
7
7
  ## Import
8
8
 
@@ -11,13 +11,13 @@ import '@videojs/html/live-audio/player';
11
11
  import '@videojs/html/live-audio/skin';
12
12
  ```
13
13
 
14
- Import `@videojs/html/live-audio/neutral-skin` instead for the neutral skin. Or load one [CDN](../../guides/cdn.md) bundle that registers the player and a skin together:
14
+ Import `@videojs/html/live-audio/neutral-skin`, `compat-skin`, or `scaffold-skin` instead for another skin. Or load one [CDN](../../guides/cdn.md) bundle that registers the player and a skin together:
15
15
 
16
16
  ```html
17
- <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.2.0/live-audio.js"></script>
17
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.3.0/live-audio.js"></script>
18
18
  ```
19
19
 
20
- `live-audio-neutral.js` registers the neutral skin instead, and `live-audio-player.js` registers `<live-audio-player>` alone.
20
+ `live-audio-neutral.js`, `live-audio-compat.js`, and `live-audio-scaffold.js` register the other skins instead, and `live-audio-player.js` registers `<live-audio-player>` alone.
21
21
 
22
22
  ## Usage
23
23
 
@@ -47,7 +47,7 @@ Live streams are usually HLS, so this example plays through an HLS media compone
47
47
  | --- | --- | --- |
48
48
  | `content-title` | `contentTitle` | The title to display. Takes precedence over the title the media reports. |
49
49
  | `poster` | `poster` | The poster to display. Takes precedence over the poster the media reports. |
50
- | `keep-alive` | — | Keeps the player and its store alive when the element leaves the DOM. Call `destroy()` when you’re done with it. |
50
+ | `keep-alive` | — | Keeps the player, its store, and the UI elements inside it alive when the element leaves the DOM. Call `destroy()` when you’re done with it. |
51
51
 
52
52
  `content-title` and `poster` come from the [metadata feature](./feature-metadata.md#player-inputs). The element’s read-only `store` property returns its player store.
53
53
 
@@ -91,6 +91,10 @@ customElements.define('my-live-audio-player', PlayerElement);
91
91
 
92
92
  - [LiveAudioSkin](../components/live-audio-skin.md) — the default skin, which swaps the time controls for a Live button.
93
93
  - [NeutralLiveAudioSkin](../components/live-audio-neutral-skin.md) — the visually lighter variant, closer to a classic control bar.
94
+ - [CompatLiveAudioSkin](../components/live-audio-compat-skin.md) — the plain, unbranded variant that avoids newer visual effects, so it looks consistent across browsers.
95
+ - [ScaffoldLiveAudioSkin](../components/live-audio-scaffold-skin.md) — the minimally styled variant of Compat, a foundation for your own design.
96
+
97
+ See [Choose a skin](../../guides/skins.md#choose-a-skin) to compare them.
94
98
 
95
99
  ## Media
96
100
 
@@ -107,6 +111,8 @@ The preset root, `@videojs/html/live-audio`, has no side effects. Importing it n
107
111
  | `liveAudioFeatures` | The [feature bundle](#feature-bundle). |
108
112
  | `LiveAudioSkinElement` | The default [skin](#skins) element class. |
109
113
  | `NeutralLiveAudioSkinElement` | The neutral [skin](#skins) element class. |
114
+ | `CompatLiveAudioSkinElement` | The compat [skin](#skins) element class. |
115
+ | `ScaffoldLiveAudioSkinElement` | The scaffold [skin](#skins) element class. |
110
116
 
111
117
  Registration entry points are side-effect-only:
112
118
 
@@ -115,5 +121,7 @@ Registration entry points are side-effect-only:
115
121
  | `@videojs/html/live-audio/player` | `<live-audio-player>` |
116
122
  | `@videojs/html/live-audio/skin` | `<live-audio-skin>`, `<media-container>`, and the UI elements the skin composes |
117
123
  | `@videojs/html/live-audio/neutral-skin` | `<live-audio-neutral-skin>`, `<media-container>`, and the UI elements the neutral skin composes |
124
+ | `@videojs/html/live-audio/compat-skin` | `<live-audio-compat-skin>`, `<media-container>`, and the UI elements the compat skin composes |
125
+ | `@videojs/html/live-audio/scaffold-skin` | `<live-audio-scaffold-skin>`, `<media-container>`, and the UI elements the scaffold skin composes |
118
126
  | `@videojs/html/live-audio/ui` | `<media-container>` and the UI elements of the default skin, without the skin, for a layout you write yourself |
119
127
  | `@videojs/html/live-audio/neutral-ui` | `<media-container>` and the UI elements of the neutral skin, without the skin |
@@ -2,7 +2,7 @@
2
2
 
3
3
  The live video preset — a player, feature bundle, skins, and media for live video streams
4
4
 
5
- `@videojs/html/live-video` is the preset for live video streams. It bundles the `<live-video-player>` element, the `liveVideoFeatures` bundle it is configured with, and two skins that swap the time slider and time displays for a Live button, and plays through the browser’s native `<video>`. See [Presets](../../guides/presets.md) for how presets fit together and [Live streams](../../guides/live-streams.md) for playing a live source.
5
+ `@videojs/html/live-video` is the preset for live video streams. It bundles the `<live-video-player>` element, the `liveVideoFeatures` bundle it is configured with, and four skins that swap the time slider and time displays for a Live button, and plays through the browser’s native `<video>`. See [Presets](../../guides/presets.md) for how presets fit together and [Live streams](../../guides/live-streams.md) for playing a live source.
6
6
 
7
7
  ## Import
8
8
 
@@ -11,13 +11,13 @@ import '@videojs/html/live-video/player';
11
11
  import '@videojs/html/live-video/skin';
12
12
  ```
13
13
 
14
- Import `@videojs/html/live-video/neutral-skin` instead for the neutral skin. Or load one [CDN](../../guides/cdn.md) bundle that registers the player and a skin together:
14
+ Import `@videojs/html/live-video/neutral-skin`, `compat-skin`, or `scaffold-skin` instead for another skin. Or load one [CDN](../../guides/cdn.md) bundle that registers the player and a skin together:
15
15
 
16
16
  ```html
17
- <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.2.0/live-video.js"></script>
17
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.3.0/live-video.js"></script>
18
18
  ```
19
19
 
20
- `live-video-neutral.js` registers the neutral skin instead, and `live-video-player.js` registers `<live-video-player>` alone.
20
+ `live-video-neutral.js`, `live-video-compat.js`, and `live-video-scaffold.js` register the other skins instead, and `live-video-player.js` registers `<live-video-player>` alone.
21
21
 
22
22
  ## Usage
23
23
 
@@ -47,7 +47,7 @@ Live streams are usually HLS, so this example plays through an HLS media compone
47
47
  | --- | --- | --- |
48
48
  | `content-title` | `contentTitle` | The title to display. Takes precedence over the title the media reports. |
49
49
  | `poster` | `poster` | The poster to display. Takes precedence over the poster the media reports. |
50
- | `keep-alive` | — | Keeps the player and its store alive when the element leaves the DOM. Call `destroy()` when you’re done with it. |
50
+ | `keep-alive` | — | Keeps the player, its store, and the UI elements inside it alive when the element leaves the DOM. Call `destroy()` when you’re done with it. |
51
51
 
52
52
  `content-title` and `poster` come from the [metadata feature](./feature-metadata.md#player-inputs). The element’s read-only `store` property returns its player store.
53
53
 
@@ -96,6 +96,10 @@ customElements.define('my-live-video-player', PlayerElement);
96
96
 
97
97
  - [LiveVideoSkin](../components/live-video-skin.md) — the default skin, which swaps the time controls for a Live button.
98
98
  - [NeutralLiveVideoSkin](../components/live-video-neutral-skin.md) — the visually lighter variant, closer to a classic control bar.
99
+ - [CompatLiveVideoSkin](../components/live-video-compat-skin.md) — the plain, unbranded variant that avoids newer visual effects, so it looks consistent across browsers.
100
+ - [ScaffoldLiveVideoSkin](../components/live-video-scaffold-skin.md) — the minimally styled variant of Compat, a foundation for your own design.
101
+
102
+ See [Choose a skin](../../guides/skins.md#choose-a-skin) to compare them.
99
103
 
100
104
  ## Media
101
105
 
@@ -112,6 +116,8 @@ The preset root, `@videojs/html/live-video`, has no side effects. Importing it n
112
116
  | `liveVideoFeatures` | The [feature bundle](#feature-bundle). |
113
117
  | `LiveVideoSkinElement` | The default [skin](#skins) element class. |
114
118
  | `NeutralLiveVideoSkinElement` | The neutral [skin](#skins) element class. |
119
+ | `CompatLiveVideoSkinElement` | The compat [skin](#skins) element class. |
120
+ | `ScaffoldLiveVideoSkinElement` | The scaffold [skin](#skins) element class. |
115
121
 
116
122
  Registration entry points are side-effect-only:
117
123
 
@@ -120,5 +126,7 @@ Registration entry points are side-effect-only:
120
126
  | `@videojs/html/live-video/player` | `<live-video-player>` |
121
127
  | `@videojs/html/live-video/skin` | `<live-video-skin>`, `<media-container>`, and the UI elements the skin composes |
122
128
  | `@videojs/html/live-video/neutral-skin` | `<live-video-neutral-skin>`, `<media-container>`, and the UI elements the neutral skin composes |
129
+ | `@videojs/html/live-video/compat-skin` | `<live-video-compat-skin>`, `<media-container>`, and the UI elements the compat skin composes |
130
+ | `@videojs/html/live-video/scaffold-skin` | `<live-video-scaffold-skin>`, `<media-container>`, and the UI elements the scaffold skin composes |
123
131
  | `@videojs/html/live-video/ui` | `<media-container>` and the UI elements of the default skin, without the skin, for a layout you write yourself |
124
132
  | `@videojs/html/live-video/neutral-ui` | `<media-container>` and the UI elements of the neutral skin, without the skin |
@@ -2,7 +2,7 @@
2
2
 
3
3
  The general-purpose video preset — a player, feature bundle, skins, and media for on-demand video
4
4
 
5
- `@videojs/html/video` is the general-purpose preset for on-demand video. It bundles the `<video-player>` element, the `videoFeatures` bundle it is configured with, and two skins, and plays through the browser’s native `<video>`. See [Presets](../../guides/presets.md) for how presets fit together and how to customize one.
5
+ `@videojs/html/video` is the general-purpose preset for on-demand video. It bundles the `<video-player>` element, the `videoFeatures` bundle it is configured with, and four skins, and plays through the browser’s native `<video>`. See [Presets](../../guides/presets.md) for how presets fit together and how to customize one.
6
6
 
7
7
  ## Import
8
8
 
@@ -11,13 +11,13 @@ import '@videojs/html/video/player';
11
11
  import '@videojs/html/video/skin';
12
12
  ```
13
13
 
14
- Import `@videojs/html/video/neutral-skin` instead for the neutral skin. Or load one [CDN](../../guides/cdn.md) bundle that registers the player and a skin together:
14
+ Import `@videojs/html/video/neutral-skin`, `compat-skin`, or `scaffold-skin` instead for another skin. Or load one [CDN](../../guides/cdn.md) bundle that registers the player and a skin together:
15
15
 
16
16
  ```html
17
- <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.2.0/video.js"></script>
17
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.3.0/video.js"></script>
18
18
  ```
19
19
 
20
- `video-neutral.js` registers the neutral skin instead, and `video-player.js` registers `<video-player>` alone.
20
+ `video-neutral.js`, `video-compat.js`, and `video-scaffold.js` register the other skins instead, and `video-player.js` registers `<video-player>` alone.
21
21
 
22
22
  ## Usage
23
23
 
@@ -44,7 +44,7 @@ Import `@videojs/html/video/neutral-skin` instead for the neutral skin. Or load
44
44
  | --- | --- | --- |
45
45
  | `content-title` | `contentTitle` | The title to display. Takes precedence over the title the media reports. |
46
46
  | `poster` | `poster` | The poster to display. Takes precedence over the poster the media reports. |
47
- | `keep-alive` | — | Keeps the player and its store alive when the element leaves the DOM. Call `destroy()` when you’re done with it. |
47
+ | `keep-alive` | — | Keeps the player, its store, and the UI elements inside it alive when the element leaves the DOM. Call `destroy()` when you’re done with it. |
48
48
 
49
49
  `content-title` and `poster` come from the [metadata feature](./feature-metadata.md#player-inputs). The element’s read-only `store` property returns its player store.
50
50
 
@@ -95,6 +95,10 @@ customElements.define('my-video-player', PlayerElement);
95
95
 
96
96
  - [VideoSkin](../components/video-skin.md) — the default skin, with the modern, frosted look.
97
97
  - [NeutralVideoSkin](../components/video-neutral-skin.md) — the visually lighter variant, closer to a classic control bar.
98
+ - [CompatVideoSkin](../components/video-compat-skin.md) — the plain, unbranded variant that avoids newer visual effects, so it looks consistent across browsers.
99
+ - [ScaffoldVideoSkin](../components/video-scaffold-skin.md) — the minimally styled variant of Compat, a foundation for your own design.
100
+
101
+ See [Choose a skin](../../guides/skins.md#choose-a-skin) to compare them.
98
102
 
99
103
  ## Media
100
104
 
@@ -111,6 +115,8 @@ The preset root, `@videojs/html/video`, has no side effects. Importing it never
111
115
  | `videoFeatures` | The [feature bundle](#feature-bundle). |
112
116
  | `VideoSkinElement` | The default [skin](#skins) element class. |
113
117
  | `NeutralVideoSkinElement` | The neutral [skin](#skins) element class. |
118
+ | `CompatVideoSkinElement` | The compat [skin](#skins) element class. |
119
+ | `ScaffoldVideoSkinElement` | The scaffold [skin](#skins) element class. |
114
120
 
115
121
  Registration entry points are side-effect-only:
116
122
 
@@ -119,5 +125,7 @@ Registration entry points are side-effect-only:
119
125
  | `@videojs/html/video/player` | `<video-player>` |
120
126
  | `@videojs/html/video/skin` | `<video-skin>`, `<media-container>`, and the UI elements the skin composes |
121
127
  | `@videojs/html/video/neutral-skin` | `<video-neutral-skin>`, `<media-container>`, and the UI elements the neutral skin composes |
128
+ | `@videojs/html/video/compat-skin` | `<video-compat-skin>`, `<media-container>`, and the UI elements the compat skin composes |
129
+ | `@videojs/html/video/scaffold-skin` | `<video-scaffold-skin>`, `<media-container>`, and the UI elements the scaffold skin composes |
122
130
  | `@videojs/html/video/ui` | `<media-container>` and the UI elements of the default skin, without the skin, for a layout you write yourself |
123
131
  | `@videojs/html/video/neutral-ui` | `<media-container>` and the UI elements of the neutral skin, without the skin |
@@ -47,8 +47,11 @@ Each media module you import adds its engine to your bundle, so import the rarel
47
47
  | `mux` | `stream.mux.com` stream URLs, with or without `.m3u8` | `<mux-video>` or `<mux-audio>` |
48
48
  | `cloudflare` | `cloudflarestream.com` and `videodelivery.net` URLs | `<cloudflare-video>` |
49
49
  | `spotify` | `open.spotify.com` URLs and `spotify:` URIs | `<spotify-audio>` |
50
+ | `soundcloud` | `soundcloud.com` track and set URLs, `api.soundcloud.com` tracks and playlists, and `w.soundcloud.com/player/` embed URLs | `<soundcloud-audio>` |
51
+ | `mixcloud` | `mixcloud.com` show URLs and Mixcloud widget embed URLs | `<mixcloud-audio>` |
50
52
  | `tiktok` | `tiktok.com` video URLs | `<tiktok-video>` |
51
53
  | `twitch` | `twitch.tv` video and channel URLs | `<twitch-video>` |
54
+ | `dailymotion` | `dailymotion.com` video and embed URLs, `dai.ly` short links, and `geo.dailymotion.com` player embed URLs | `<dailymotion-video>` |
52
55
  | `hls` | `.m3u8` files and HLS MIME types | `<hls-video>`, `<hlsjs-video>`, or `<native-hls-video>` |
53
56
  | `dash` | `.mpd` files and `application/dash+xml` | `<dash-video>` or `<shaka-video>` |
54
57
  | `video` | `.mp4`, `.webm`, `.mov`, and `.ogv` files, and `video/*` MIME types | `<video>` |
@@ -95,4 +98,4 @@ A bare id returns `null`. An 11-character YouTube id and a 10-character Wistia i
95
98
 
96
99
  | Type |
97
100
  | --- |
98
- | `'youtube' \| 'vimeo' \| 'wistia' \| 'mux' \| 'cloudflare' \| 'spotify' \| 'tiktok' \| 'twitch' \| 'hls' \| 'dash' \| 'video' \| 'audio' \| null` |
101
+ | `'youtube' \| 'vimeo' \| 'wistia' \| 'mux' \| 'cloudflare' \| 'spotify' \| 'soundcloud' \| 'mixcloud' \| 'tiktok' \| 'twitch' \| 'dailymotion' \| 'hls' \| 'dash' \| 'video' \| 'audio' \| null` |
@@ -165,7 +165,7 @@ class ClockController implements ReactiveController {
165
165
 
166
166
  ## Destruction
167
167
 
168
- When the element disconnects, it waits two animation frames and then destroys itself if it is still disconnected. Moving the element within the document, or a framework reordering it, therefore keeps it alive. Destruction calls `hostDestroyed()` on every controller. A destroyed element stops updating and ignores later connections.
168
+ When the element disconnects, it waits two animation frames and then destroys itself if it is still disconnected. Moving the element within the document, or a framework reordering it, therefore keeps it alive. Destruction first destroys the UI elements inside the element, including those in its shadow root, then calls `hostDestroyed()` on every controller. A destroyed element stops updating and ignores later connections.
169
169
 
170
170
  | Member | Description |
171
171
  | --- | --- |
@@ -173,7 +173,7 @@ When the element disconnects, it waits two animation frames and then destroys it
173
173
  | `destroyed` | `true` after destruction. |
174
174
  | `destroyCallback()` | Runs once on destruction. Override it, calling `super.destroyCallback()`, to release resources the element owns. |
175
175
 
176
- Add the `keep-alive` attribute to skip automatic destruction, for example when you detach an element and insert it again later. Call `destroy()` yourself when you are done with it.
176
+ Add the `keep-alive` attribute to the element or one of its ancestors to skip automatic destruction, for example when you detach an element and insert it again later. Destroying an ancestor still destroys it. Call `destroy()` yourself when you are done with it.
177
177
 
178
178
  Release listeners and observers that the element starts on connection in `disconnectedCallback()`, calling `super.disconnectedCallback()`, because an element can connect and disconnect many times before it is destroyed.
179
179
 
@@ -45,6 +45,7 @@ Use the open and transition data attributes to style visibility and animations:
45
45
  | `data-open` | Present while the dialog is open, including its closing transition |
46
46
  | `data-starting-style` | Present at the start of the opening transition |
47
47
  | `data-ending-style` | Present during the closing transition |
48
+ | `data-scope` | `player` inside a player, `document` outside one |
48
49
 
49
50
  ```css
50
51
  media-dialog-backdrop:not([data-open]),
@@ -62,7 +63,7 @@ media-dialog-popup[data-ending-style] {
62
63
 
63
64
  ## Accessibility
64
65
 
65
- The dialog uses `role="alertdialog"` and `aria-modal="true"`. The title and description receive generated IDs that are connected with `aria-labelledby` and `aria-describedby`. Focus moves into the dialog when it opens, stays within it while open, and returns to the previously focused element when it closes. Content outside the dialog is inert while it is open. Pressing Escape closes the dialog.
66
+ The dialog uses `role="alertdialog"`, plus `aria-modal="true"` outside a player. Like [Dialog](./dialog.md), it is confined to its player when rendered inside one and modal for the whole page otherwise. The title and description receive generated IDs that are connected with `aria-labelledby` and `aria-describedby`. Focus moves into the dialog when it opens, stays within it while open, and returns to the previously focused element when it closes. Content outside the dialog, within its player or the page, is inert while it is open. Pressing Escape closes the dialog.
66
67
 
67
68
  ## Examples
68
69
 
@@ -217,6 +218,7 @@ State is reflected as data attributes for CSS styling.
217
218
  | `status` | `'idle' \| 'starting' \| 'ending'` | Current phase of the transition lifecycle. |
218
219
  | `titleId` | `string \| undefined` | Element ID of the dialog title, used for `aria-labelledby`. |
219
220
  | `descriptionId` | `string \| undefined` | Element ID of the dialog description, used for `aria-describedby`. |
221
+ | `scope` | `'player' \| 'document'` | `player` when the dialog is rendered inside a player and confined to it, otherwise `document`. |
220
222
 
221
223
  #### Events
222
224
 
@@ -231,11 +233,12 @@ Presentational backdrop that reflects its owning dialog's state.
231
233
 
232
234
  #### Data attributes
233
235
 
234
- | Attribute | Description |
235
- | --- | --- |
236
- | `data-open` | Present when the dialog is open. |
237
- | `data-starting-style` | Present during the open transition. |
238
- | `data-ending-style` | Present during the close transition. |
236
+ | Attribute | Type | Description |
237
+ | --- | --- | --- |
238
+ | `data-open` | — | Present when the dialog is open. |
239
+ | `data-starting-style` | — | Present during the open transition. |
240
+ | `data-ending-style` | — | Present during the close transition. |
241
+ | `data-scope` | `'player' \| 'document'` | `player` when the dialog is confined to its player, otherwise `document`. |
239
242
 
240
243
  ### media-dialog-close
241
244
 
@@ -243,11 +246,12 @@ Button that closes its owning dialog; the element itself takes `role="button"` a
243
246
 
244
247
  #### Data attributes
245
248
 
246
- | Attribute | Description |
247
- | --- | --- |
248
- | `data-open` | Present when the dialog is open. |
249
- | `data-starting-style` | Present during the open transition. |
250
- | `data-ending-style` | Present during the close transition. |
249
+ | Attribute | Type | Description |
250
+ | --- | --- | --- |
251
+ | `data-open` | — | Present when the dialog is open. |
252
+ | `data-starting-style` | — | Present during the open transition. |
253
+ | `data-ending-style` | — | Present during the close transition. |
254
+ | `data-scope` | `'player' \| 'document'` | `player` when the dialog is confined to its player, otherwise `document`. |
251
255
 
252
256
  ### media-dialog-description
253
257
 
@@ -259,11 +263,12 @@ Semantic popup that owns focus management and dialog transition completion.
259
263
 
260
264
  #### Data attributes
261
265
 
262
- | Attribute | Description |
263
- | --- | --- |
264
- | `data-open` | Present when the dialog is open. |
265
- | `data-starting-style` | Present during the open transition. |
266
- | `data-ending-style` | Present during the close transition. |
266
+ | Attribute | Type | Description |
267
+ | --- | --- | --- |
268
+ | `data-open` | — | Present when the dialog is open. |
269
+ | `data-starting-style` | — | Present during the open transition. |
270
+ | `data-ending-style` | — | Present during the close transition. |
271
+ | `data-scope` | `'player' \| 'document'` | `player` when the dialog is confined to its player, otherwise `document`. |
267
272
 
268
273
  ### media-dialog-title
269
274
 
@@ -1,8 +1,8 @@
1
1
  # audio-compat-skin
2
2
 
3
- An audio skin designed for broader browser compatibility
3
+ The audio preset's plain, unbranded skin, a polished step above native controls
4
4
 
5
- The Compat skin of the audio preset provides basic controls and plain surfaces, with broader browser compatibility as its design goal. Its time slider supports chapter segments and thumbnail previews. See [Customize skins](../../guides/customize-skins.md) to install and edit its source.
5
+ The Compat skin of the audio preset: the same core controls with plain, unbranded surfaces that avoid newer visual effects such as backdrop blur. Its time slider supports chapter segments and thumbnail previews, and it adds captions and AirPlay buttons that the default audio skin leaves out. The preset also provides [AudioSkin](./audio-skin.md), [NeutralAudioSkin](./audio-neutral-skin.md), and [ScaffoldAudioSkin](./audio-scaffold-skin.md). See [Skins](../../guides/skins.md#choose-a-skin) to choose between them and [Customize skins](../../guides/customize-skins.md) to install and edit its source.
6
6
 
7
7
  ## Import
8
8
 
@@ -10,6 +10,12 @@ The Compat skin of the audio preset provides basic controls and plain surfaces,
10
10
  import '@videojs/html/audio/compat-skin';
11
11
  ```
12
12
 
13
+ The import registers the skin and every UI element it composes. The [CDN](../../guides/cdn.md) player bundle registers this skin together with its player:
14
+
15
+ ```html
16
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.3.0/audio-compat.js"></script>
17
+ ```
18
+
13
19
  ## Anatomy
14
20
 
15
21
  The skin goes between the player and the media component. It renders its controls around the media.