ts-video-player 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cdn.min.js +50 -50
- package/dist/{chunk-24n6adw2.js → chunk-hvjcmbfn.js} +685 -103
- package/dist/core/i18n.d.ts +24 -0
- package/dist/elements/index.js +2 -2
- package/dist/elements/utils.d.ts +16 -2
- package/dist/index.js +28 -419
- package/dist/player.d.ts +6 -0
- package/dist/providers/vimeo.d.ts +6 -0
- package/package.json +1 -1
- package/src/core/i18n.ts +173 -1
- package/src/elements/media-airplay-button.ts +2 -2
- package/src/elements/media-fullscreen-button.ts +3 -3
- package/src/elements/media-live-button.ts +2 -2
- package/src/elements/media-mute-button.ts +3 -3
- package/src/elements/media-pip-button.ts +3 -2
- package/src/elements/media-play-button.ts +3 -3
- package/src/elements/media-playback-rate-button.ts +3 -3
- package/src/elements/media-progress-bar.ts +3 -3
- package/src/elements/media-remote-playback-button.ts +2 -2
- package/src/elements/media-seek-button.ts +2 -3
- package/src/elements/media-settings-menu.ts +14 -14
- package/src/elements/media-time-display.ts +2 -2
- package/src/elements/media-volume-slider.ts +2 -2
- package/src/elements/utils.ts +40 -6
- package/src/player.ts +30 -13
- package/src/providers/vimeo.ts +15 -3
|
@@ -1026,8 +1026,9 @@ class VimeoProvider2 extends BaseProvider2 {
|
|
|
1026
1026
|
return;
|
|
1027
1027
|
}
|
|
1028
1028
|
if (this.player) {
|
|
1029
|
-
await this.player.
|
|
1030
|
-
this.
|
|
1029
|
+
await this.player.loadVideo(parseInt(parsed.videoId, 10));
|
|
1030
|
+
await this.announceLoaded();
|
|
1031
|
+
return;
|
|
1031
1032
|
}
|
|
1032
1033
|
const playerOptions = {
|
|
1033
1034
|
id: parseInt(parsed.videoId, 10),
|
|
@@ -1051,6 +1052,11 @@ class VimeoProvider2 extends BaseProvider2 {
|
|
|
1051
1052
|
this.iframe.style.cssText = "position:absolute;inset:0;width:100%;height:100%;border:0";
|
|
1052
1053
|
}
|
|
1053
1054
|
this.attachVimeoEvents();
|
|
1055
|
+
await this.announceLoaded();
|
|
1056
|
+
}
|
|
1057
|
+
async announceLoaded() {
|
|
1058
|
+
if (!this.player)
|
|
1059
|
+
return;
|
|
1054
1060
|
this.events.emit("loadedmetadata");
|
|
1055
1061
|
this.events.emit("canplay");
|
|
1056
1062
|
this._duration = await this.player.getDuration();
|
|
@@ -2042,6 +2048,630 @@ function embedCover(state, dismissed) {
|
|
|
2042
2048
|
return { show: true, image: youtubeId ? `https://i.ytimg.com/vi/${youtubeId}/hqdefault.jpg` : "" };
|
|
2043
2049
|
}
|
|
2044
2050
|
|
|
2051
|
+
// src/core/i18n.ts
|
|
2052
|
+
var englishStrings2 = {
|
|
2053
|
+
play: "Play",
|
|
2054
|
+
pause: "Pause",
|
|
2055
|
+
replay: "Replay",
|
|
2056
|
+
mute: "Mute",
|
|
2057
|
+
unmute: "Unmute",
|
|
2058
|
+
volume: "Volume",
|
|
2059
|
+
seekBackward: "Seek backward {seconds} seconds",
|
|
2060
|
+
seekForward: "Seek forward {seconds} seconds",
|
|
2061
|
+
seekTo: "Seek to {time}",
|
|
2062
|
+
duration: "Duration",
|
|
2063
|
+
currentTime: "Current time",
|
|
2064
|
+
played: "Played",
|
|
2065
|
+
buffered: "Buffered",
|
|
2066
|
+
enterFullscreen: "Enter fullscreen",
|
|
2067
|
+
exitFullscreen: "Exit fullscreen",
|
|
2068
|
+
enterPiP: "Enter picture-in-picture",
|
|
2069
|
+
exitPiP: "Exit picture-in-picture",
|
|
2070
|
+
enableCaptions: "Enable captions",
|
|
2071
|
+
disableCaptions: "Disable captions",
|
|
2072
|
+
captions: "Captions",
|
|
2073
|
+
captionsOff: "Off",
|
|
2074
|
+
settings: "Settings",
|
|
2075
|
+
quality: "Quality",
|
|
2076
|
+
auto: "Auto",
|
|
2077
|
+
speed: "Speed",
|
|
2078
|
+
normal: "Normal",
|
|
2079
|
+
loop: "Loop",
|
|
2080
|
+
loopEnabled: "Loop enabled",
|
|
2081
|
+
loopDisabled: "Loop disabled",
|
|
2082
|
+
audioBoost: "Audio boost",
|
|
2083
|
+
audioTrack: "Audio track",
|
|
2084
|
+
live: "LIVE",
|
|
2085
|
+
liveEdge: "At live edge",
|
|
2086
|
+
seekToLive: "Seek to live edge",
|
|
2087
|
+
behindLive: "{seconds}s behind",
|
|
2088
|
+
networkError: "A network error occurred",
|
|
2089
|
+
mediaError: "The media could not be loaded",
|
|
2090
|
+
unknownError: "An unknown error occurred",
|
|
2091
|
+
loading: "Loading",
|
|
2092
|
+
buffering: "Buffering",
|
|
2093
|
+
chapters: "Chapters",
|
|
2094
|
+
airPlay: "AirPlay",
|
|
2095
|
+
googleCast: "Cast",
|
|
2096
|
+
casting: "Casting to {device}",
|
|
2097
|
+
download: "Download",
|
|
2098
|
+
share: "Share",
|
|
2099
|
+
close: "Close",
|
|
2100
|
+
menu: "Menu",
|
|
2101
|
+
back: "Back",
|
|
2102
|
+
seek: "Seek",
|
|
2103
|
+
playbackRate: "Playback speed {rate}x",
|
|
2104
|
+
airPlayPlay: "Play on AirPlay",
|
|
2105
|
+
remotePlayback: "Play on another device",
|
|
2106
|
+
videoPlayer: "Video player",
|
|
2107
|
+
videoRole: "video player",
|
|
2108
|
+
playTitle: "Play {title}",
|
|
2109
|
+
audio: "Audio",
|
|
2110
|
+
defaultTrack: "Default",
|
|
2111
|
+
playing: "Playing",
|
|
2112
|
+
paused: "Paused",
|
|
2113
|
+
muted: "Muted",
|
|
2114
|
+
volumeLevel: "Volume {percent}%",
|
|
2115
|
+
ended: "Playback ended",
|
|
2116
|
+
enteredFullscreen: "Entered fullscreen",
|
|
2117
|
+
exitedFullscreen: "Exited fullscreen",
|
|
2118
|
+
errorMessage: "Error: {message}",
|
|
2119
|
+
timeOf: "{current} of {duration}",
|
|
2120
|
+
hourOne: "{n} hour",
|
|
2121
|
+
hourOther: "{n} hours",
|
|
2122
|
+
minuteOne: "{n} minute",
|
|
2123
|
+
minuteOther: "{n} minutes",
|
|
2124
|
+
secondOne: "{n} second",
|
|
2125
|
+
secondOther: "{n} seconds"
|
|
2126
|
+
};
|
|
2127
|
+
var spanishStrings2 = {
|
|
2128
|
+
play: "Reproducir",
|
|
2129
|
+
pause: "Pausar",
|
|
2130
|
+
replay: "Repetir",
|
|
2131
|
+
mute: "Silenciar",
|
|
2132
|
+
unmute: "Activar sonido",
|
|
2133
|
+
volume: "Volumen",
|
|
2134
|
+
seekBackward: "Retroceder {seconds} segundos",
|
|
2135
|
+
seekForward: "Avanzar {seconds} segundos",
|
|
2136
|
+
seekTo: "Ir a {time}",
|
|
2137
|
+
duration: "Duración",
|
|
2138
|
+
currentTime: "Tiempo actual",
|
|
2139
|
+
played: "Reproducido",
|
|
2140
|
+
buffered: "Almacenado",
|
|
2141
|
+
enterFullscreen: "Pantalla completa",
|
|
2142
|
+
exitFullscreen: "Salir de pantalla completa",
|
|
2143
|
+
enterPiP: "Imagen en imagen",
|
|
2144
|
+
exitPiP: "Salir de imagen en imagen",
|
|
2145
|
+
enableCaptions: "Activar subtítulos",
|
|
2146
|
+
disableCaptions: "Desactivar subtítulos",
|
|
2147
|
+
captions: "Subtítulos",
|
|
2148
|
+
captionsOff: "Desactivados",
|
|
2149
|
+
settings: "Ajustes",
|
|
2150
|
+
quality: "Calidad",
|
|
2151
|
+
auto: "Automático",
|
|
2152
|
+
speed: "Velocidad",
|
|
2153
|
+
normal: "Normal",
|
|
2154
|
+
loop: "Bucle",
|
|
2155
|
+
loopEnabled: "Bucle activado",
|
|
2156
|
+
loopDisabled: "Bucle desactivado",
|
|
2157
|
+
audioBoost: "Aumento de audio",
|
|
2158
|
+
audioTrack: "Pista de audio",
|
|
2159
|
+
live: "EN VIVO",
|
|
2160
|
+
liveEdge: "En vivo",
|
|
2161
|
+
seekToLive: "Ir al directo",
|
|
2162
|
+
behindLive: "{seconds}s de retraso",
|
|
2163
|
+
networkError: "Error de red",
|
|
2164
|
+
mediaError: "No se pudo cargar el medio",
|
|
2165
|
+
unknownError: "Error desconocido",
|
|
2166
|
+
loading: "Cargando",
|
|
2167
|
+
buffering: "Almacenando",
|
|
2168
|
+
chapters: "Capítulos",
|
|
2169
|
+
airPlay: "AirPlay",
|
|
2170
|
+
googleCast: "Enviar",
|
|
2171
|
+
casting: "Enviando a {device}",
|
|
2172
|
+
download: "Descargar",
|
|
2173
|
+
share: "Compartir",
|
|
2174
|
+
close: "Cerrar",
|
|
2175
|
+
menu: "Menú",
|
|
2176
|
+
back: "Volver",
|
|
2177
|
+
seek: "Buscar",
|
|
2178
|
+
playbackRate: "Velocidad de reproducción {rate}x",
|
|
2179
|
+
airPlayPlay: "Reproducir con AirPlay",
|
|
2180
|
+
remotePlayback: "Reproducir en otro dispositivo",
|
|
2181
|
+
videoPlayer: "Reproductor de vídeo",
|
|
2182
|
+
videoRole: "reproductor de vídeo",
|
|
2183
|
+
playTitle: "Reproducir {title}",
|
|
2184
|
+
audio: "Audio",
|
|
2185
|
+
defaultTrack: "Predeterminado",
|
|
2186
|
+
playing: "Reproduciendo",
|
|
2187
|
+
paused: "En pausa",
|
|
2188
|
+
muted: "Silenciado",
|
|
2189
|
+
volumeLevel: "Volumen {percent}%",
|
|
2190
|
+
ended: "Reproducción finalizada",
|
|
2191
|
+
enteredFullscreen: "Pantalla completa activada",
|
|
2192
|
+
exitedFullscreen: "Pantalla completa desactivada",
|
|
2193
|
+
errorMessage: "Error: {message}",
|
|
2194
|
+
timeOf: "{current} de {duration}",
|
|
2195
|
+
hourOne: "{n} hora",
|
|
2196
|
+
hourOther: "{n} horas",
|
|
2197
|
+
minuteOne: "{n} minuto",
|
|
2198
|
+
minuteOther: "{n} minutos",
|
|
2199
|
+
secondOne: "{n} segundo",
|
|
2200
|
+
secondOther: "{n} segundos"
|
|
2201
|
+
};
|
|
2202
|
+
var frenchStrings2 = {
|
|
2203
|
+
play: "Lecture",
|
|
2204
|
+
pause: "Pause",
|
|
2205
|
+
replay: "Relire",
|
|
2206
|
+
mute: "Muet",
|
|
2207
|
+
unmute: "Son activé",
|
|
2208
|
+
volume: "Volume",
|
|
2209
|
+
seekBackward: "Reculer de {seconds} secondes",
|
|
2210
|
+
seekForward: "Avancer de {seconds} secondes",
|
|
2211
|
+
seekTo: "Aller à {time}",
|
|
2212
|
+
duration: "Durée",
|
|
2213
|
+
currentTime: "Temps actuel",
|
|
2214
|
+
played: "Joué",
|
|
2215
|
+
buffered: "Mis en mémoire tampon",
|
|
2216
|
+
enterFullscreen: "Plein écran",
|
|
2217
|
+
exitFullscreen: "Quitter le plein écran",
|
|
2218
|
+
enterPiP: "Image dans l'image",
|
|
2219
|
+
exitPiP: "Quitter l'image dans l'image",
|
|
2220
|
+
enableCaptions: "Activer les sous-titres",
|
|
2221
|
+
disableCaptions: "Désactiver les sous-titres",
|
|
2222
|
+
captions: "Sous-titres",
|
|
2223
|
+
captionsOff: "Désactivés",
|
|
2224
|
+
settings: "Paramètres",
|
|
2225
|
+
quality: "Qualité",
|
|
2226
|
+
auto: "Auto",
|
|
2227
|
+
speed: "Vitesse",
|
|
2228
|
+
normal: "Normal",
|
|
2229
|
+
loop: "Boucle",
|
|
2230
|
+
loopEnabled: "Boucle activée",
|
|
2231
|
+
loopDisabled: "Boucle désactivée",
|
|
2232
|
+
audioBoost: "Amplification audio",
|
|
2233
|
+
audioTrack: "Piste audio",
|
|
2234
|
+
live: "EN DIRECT",
|
|
2235
|
+
liveEdge: "En direct",
|
|
2236
|
+
seekToLive: "Aller au direct",
|
|
2237
|
+
behindLive: "{seconds}s de retard",
|
|
2238
|
+
networkError: "Erreur réseau",
|
|
2239
|
+
mediaError: "Le média n'a pas pu être chargé",
|
|
2240
|
+
unknownError: "Erreur inconnue",
|
|
2241
|
+
loading: "Chargement",
|
|
2242
|
+
buffering: "Mise en mémoire tampon",
|
|
2243
|
+
chapters: "Chapitres",
|
|
2244
|
+
airPlay: "AirPlay",
|
|
2245
|
+
googleCast: "Caster",
|
|
2246
|
+
casting: "Diffusion sur {device}",
|
|
2247
|
+
download: "Télécharger",
|
|
2248
|
+
share: "Partager",
|
|
2249
|
+
close: "Fermer",
|
|
2250
|
+
menu: "Menu",
|
|
2251
|
+
back: "Retour",
|
|
2252
|
+
seek: "Rechercher",
|
|
2253
|
+
playbackRate: "Vitesse de lecture {rate}x",
|
|
2254
|
+
airPlayPlay: "Lire avec AirPlay",
|
|
2255
|
+
remotePlayback: "Lire sur un autre appareil",
|
|
2256
|
+
videoPlayer: "Lecteur vidéo",
|
|
2257
|
+
videoRole: "lecteur vidéo",
|
|
2258
|
+
playTitle: "Lire {title}",
|
|
2259
|
+
audio: "Audio",
|
|
2260
|
+
defaultTrack: "Par défaut",
|
|
2261
|
+
playing: "Lecture",
|
|
2262
|
+
paused: "En pause",
|
|
2263
|
+
muted: "Son coupé",
|
|
2264
|
+
volumeLevel: "Volume {percent} %",
|
|
2265
|
+
ended: "Lecture terminée",
|
|
2266
|
+
enteredFullscreen: "Plein écran activé",
|
|
2267
|
+
exitedFullscreen: "Plein écran désactivé",
|
|
2268
|
+
errorMessage: "Erreur : {message}",
|
|
2269
|
+
timeOf: "{current} sur {duration}",
|
|
2270
|
+
hourOne: "{n} heure",
|
|
2271
|
+
hourOther: "{n} heures",
|
|
2272
|
+
minuteOne: "{n} minute",
|
|
2273
|
+
minuteOther: "{n} minutes",
|
|
2274
|
+
secondOne: "{n} seconde",
|
|
2275
|
+
secondOther: "{n} secondes"
|
|
2276
|
+
};
|
|
2277
|
+
var germanStrings2 = {
|
|
2278
|
+
play: "Abspielen",
|
|
2279
|
+
pause: "Pause",
|
|
2280
|
+
replay: "Wiederholen",
|
|
2281
|
+
mute: "Stumm",
|
|
2282
|
+
unmute: "Ton an",
|
|
2283
|
+
volume: "Lautstärke",
|
|
2284
|
+
seekBackward: "{seconds} Sekunden zurück",
|
|
2285
|
+
seekForward: "{seconds} Sekunden vor",
|
|
2286
|
+
seekTo: "Zu {time} springen",
|
|
2287
|
+
duration: "Dauer",
|
|
2288
|
+
currentTime: "Aktuelle Zeit",
|
|
2289
|
+
played: "Abgespielt",
|
|
2290
|
+
buffered: "Gepuffert",
|
|
2291
|
+
enterFullscreen: "Vollbild",
|
|
2292
|
+
exitFullscreen: "Vollbild beenden",
|
|
2293
|
+
enterPiP: "Bild-in-Bild",
|
|
2294
|
+
exitPiP: "Bild-in-Bild beenden",
|
|
2295
|
+
enableCaptions: "Untertitel aktivieren",
|
|
2296
|
+
disableCaptions: "Untertitel deaktivieren",
|
|
2297
|
+
captions: "Untertitel",
|
|
2298
|
+
captionsOff: "Aus",
|
|
2299
|
+
settings: "Einstellungen",
|
|
2300
|
+
quality: "Qualität",
|
|
2301
|
+
auto: "Auto",
|
|
2302
|
+
speed: "Geschwindigkeit",
|
|
2303
|
+
normal: "Normal",
|
|
2304
|
+
loop: "Schleife",
|
|
2305
|
+
loopEnabled: "Schleife aktiviert",
|
|
2306
|
+
loopDisabled: "Schleife deaktiviert",
|
|
2307
|
+
audioBoost: "Audio-Verstärkung",
|
|
2308
|
+
audioTrack: "Audiospur",
|
|
2309
|
+
live: "LIVE",
|
|
2310
|
+
liveEdge: "Am Live-Punkt",
|
|
2311
|
+
seekToLive: "Zum Live-Punkt",
|
|
2312
|
+
behindLive: "{seconds}s hinter Live",
|
|
2313
|
+
networkError: "Netzwerkfehler",
|
|
2314
|
+
mediaError: "Medium konnte nicht geladen werden",
|
|
2315
|
+
unknownError: "Unbekannter Fehler",
|
|
2316
|
+
loading: "Wird geladen",
|
|
2317
|
+
buffering: "Puffern",
|
|
2318
|
+
chapters: "Kapitel",
|
|
2319
|
+
airPlay: "AirPlay",
|
|
2320
|
+
googleCast: "Streamen",
|
|
2321
|
+
casting: "Streame zu {device}",
|
|
2322
|
+
download: "Herunterladen",
|
|
2323
|
+
share: "Teilen",
|
|
2324
|
+
close: "Schließen",
|
|
2325
|
+
menu: "Menü",
|
|
2326
|
+
back: "Zurück",
|
|
2327
|
+
seek: "Spulen",
|
|
2328
|
+
playbackRate: "Wiedergabegeschwindigkeit {rate}x",
|
|
2329
|
+
airPlayPlay: "Über AirPlay abspielen",
|
|
2330
|
+
remotePlayback: "Auf einem anderen Gerät abspielen",
|
|
2331
|
+
videoPlayer: "Videoplayer",
|
|
2332
|
+
videoRole: "Videoplayer",
|
|
2333
|
+
playTitle: "{title} abspielen",
|
|
2334
|
+
audio: "Audio",
|
|
2335
|
+
defaultTrack: "Standard",
|
|
2336
|
+
playing: "Wird abgespielt",
|
|
2337
|
+
paused: "Pausiert",
|
|
2338
|
+
muted: "Stumm",
|
|
2339
|
+
volumeLevel: "Lautstärke {percent} %",
|
|
2340
|
+
ended: "Wiedergabe beendet",
|
|
2341
|
+
enteredFullscreen: "Vollbild an",
|
|
2342
|
+
exitedFullscreen: "Vollbild aus",
|
|
2343
|
+
errorMessage: "Fehler: {message}",
|
|
2344
|
+
timeOf: "{current} von {duration}",
|
|
2345
|
+
hourOne: "{n} Stunde",
|
|
2346
|
+
hourOther: "{n} Stunden",
|
|
2347
|
+
minuteOne: "{n} Minute",
|
|
2348
|
+
minuteOther: "{n} Minuten",
|
|
2349
|
+
secondOne: "{n} Sekunde",
|
|
2350
|
+
secondOther: "{n} Sekunden"
|
|
2351
|
+
};
|
|
2352
|
+
var japaneseStrings2 = {
|
|
2353
|
+
play: "再生",
|
|
2354
|
+
pause: "一時停止",
|
|
2355
|
+
replay: "リプレイ",
|
|
2356
|
+
mute: "ミュート",
|
|
2357
|
+
unmute: "ミュート解除",
|
|
2358
|
+
volume: "音量",
|
|
2359
|
+
seekBackward: "{seconds}秒戻る",
|
|
2360
|
+
seekForward: "{seconds}秒進む",
|
|
2361
|
+
seekTo: "{time}にシーク",
|
|
2362
|
+
duration: "長さ",
|
|
2363
|
+
currentTime: "現在の時間",
|
|
2364
|
+
played: "再生済み",
|
|
2365
|
+
buffered: "バッファ済み",
|
|
2366
|
+
enterFullscreen: "フルスクリーン",
|
|
2367
|
+
exitFullscreen: "フルスクリーン終了",
|
|
2368
|
+
enterPiP: "ピクチャーインピクチャー",
|
|
2369
|
+
exitPiP: "ピクチャーインピクチャー終了",
|
|
2370
|
+
enableCaptions: "字幕を有効化",
|
|
2371
|
+
disableCaptions: "字幕を無効化",
|
|
2372
|
+
captions: "字幕",
|
|
2373
|
+
captionsOff: "オフ",
|
|
2374
|
+
settings: "設定",
|
|
2375
|
+
quality: "画質",
|
|
2376
|
+
auto: "自動",
|
|
2377
|
+
speed: "再生速度",
|
|
2378
|
+
normal: "通常",
|
|
2379
|
+
loop: "ループ",
|
|
2380
|
+
loopEnabled: "ループ有効",
|
|
2381
|
+
loopDisabled: "ループ無効",
|
|
2382
|
+
audioBoost: "オーディオブースト",
|
|
2383
|
+
audioTrack: "オーディオトラック",
|
|
2384
|
+
live: "ライブ",
|
|
2385
|
+
liveEdge: "ライブ中",
|
|
2386
|
+
seekToLive: "ライブに移動",
|
|
2387
|
+
behindLive: "{seconds}秒遅れ",
|
|
2388
|
+
networkError: "ネットワークエラー",
|
|
2389
|
+
mediaError: "メディアを読み込めません",
|
|
2390
|
+
unknownError: "不明なエラー",
|
|
2391
|
+
loading: "読み込み中",
|
|
2392
|
+
buffering: "バッファリング",
|
|
2393
|
+
chapters: "チャプター",
|
|
2394
|
+
airPlay: "AirPlay",
|
|
2395
|
+
googleCast: "キャスト",
|
|
2396
|
+
casting: "{device}にキャスト中",
|
|
2397
|
+
download: "ダウンロード",
|
|
2398
|
+
share: "共有",
|
|
2399
|
+
close: "閉じる",
|
|
2400
|
+
menu: "メニュー",
|
|
2401
|
+
back: "戻る",
|
|
2402
|
+
seek: "シーク",
|
|
2403
|
+
playbackRate: "再生速度 {rate}x",
|
|
2404
|
+
airPlayPlay: "AirPlayで再生",
|
|
2405
|
+
remotePlayback: "別のデバイスで再生",
|
|
2406
|
+
videoPlayer: "動画プレーヤー",
|
|
2407
|
+
videoRole: "動画プレーヤー",
|
|
2408
|
+
playTitle: "{title}を再生",
|
|
2409
|
+
audio: "音声",
|
|
2410
|
+
defaultTrack: "デフォルト",
|
|
2411
|
+
playing: "再生中",
|
|
2412
|
+
paused: "一時停止中",
|
|
2413
|
+
muted: "ミュート",
|
|
2414
|
+
volumeLevel: "音量 {percent}%",
|
|
2415
|
+
ended: "再生終了",
|
|
2416
|
+
enteredFullscreen: "全画面表示",
|
|
2417
|
+
exitedFullscreen: "全画面表示を終了",
|
|
2418
|
+
errorMessage: "エラー: {message}",
|
|
2419
|
+
timeOf: "{current} / {duration}",
|
|
2420
|
+
hourOne: "{n}時間",
|
|
2421
|
+
hourOther: "{n}時間",
|
|
2422
|
+
minuteOne: "{n}分",
|
|
2423
|
+
minuteOther: "{n}分",
|
|
2424
|
+
secondOne: "{n}秒",
|
|
2425
|
+
secondOther: "{n}秒"
|
|
2426
|
+
};
|
|
2427
|
+
var chineseStrings2 = {
|
|
2428
|
+
play: "播放",
|
|
2429
|
+
pause: "暂停",
|
|
2430
|
+
replay: "重播",
|
|
2431
|
+
mute: "静音",
|
|
2432
|
+
unmute: "取消静音",
|
|
2433
|
+
volume: "音量",
|
|
2434
|
+
seekBackward: "后退{seconds}秒",
|
|
2435
|
+
seekForward: "前进{seconds}秒",
|
|
2436
|
+
seekTo: "跳转到{time}",
|
|
2437
|
+
duration: "时长",
|
|
2438
|
+
currentTime: "当前时间",
|
|
2439
|
+
played: "已播放",
|
|
2440
|
+
buffered: "已缓冲",
|
|
2441
|
+
enterFullscreen: "全屏",
|
|
2442
|
+
exitFullscreen: "退出全屏",
|
|
2443
|
+
enterPiP: "画中画",
|
|
2444
|
+
exitPiP: "退出画中画",
|
|
2445
|
+
enableCaptions: "开启字幕",
|
|
2446
|
+
disableCaptions: "关闭字幕",
|
|
2447
|
+
captions: "字幕",
|
|
2448
|
+
captionsOff: "关闭",
|
|
2449
|
+
settings: "设置",
|
|
2450
|
+
quality: "画质",
|
|
2451
|
+
auto: "自动",
|
|
2452
|
+
speed: "播放速度",
|
|
2453
|
+
normal: "正常",
|
|
2454
|
+
loop: "循环",
|
|
2455
|
+
loopEnabled: "循环已开启",
|
|
2456
|
+
loopDisabled: "循环已关闭",
|
|
2457
|
+
audioBoost: "音频增强",
|
|
2458
|
+
audioTrack: "音轨",
|
|
2459
|
+
live: "直播",
|
|
2460
|
+
liveEdge: "直播中",
|
|
2461
|
+
seekToLive: "跳转到直播",
|
|
2462
|
+
behindLive: "落后{seconds}秒",
|
|
2463
|
+
networkError: "网络错误",
|
|
2464
|
+
mediaError: "无法加载媒体",
|
|
2465
|
+
unknownError: "未知错误",
|
|
2466
|
+
loading: "加载中",
|
|
2467
|
+
buffering: "缓冲中",
|
|
2468
|
+
chapters: "章节",
|
|
2469
|
+
airPlay: "AirPlay",
|
|
2470
|
+
googleCast: "投射",
|
|
2471
|
+
casting: "正在投射到{device}",
|
|
2472
|
+
download: "下载",
|
|
2473
|
+
share: "分享",
|
|
2474
|
+
close: "关闭",
|
|
2475
|
+
menu: "菜单",
|
|
2476
|
+
back: "返回",
|
|
2477
|
+
seek: "跳转",
|
|
2478
|
+
playbackRate: "播放速度 {rate}x",
|
|
2479
|
+
airPlayPlay: "通过 AirPlay 播放",
|
|
2480
|
+
remotePlayback: "在其他设备上播放",
|
|
2481
|
+
videoPlayer: "视频播放器",
|
|
2482
|
+
videoRole: "视频播放器",
|
|
2483
|
+
playTitle: "播放{title}",
|
|
2484
|
+
audio: "音频",
|
|
2485
|
+
defaultTrack: "默认",
|
|
2486
|
+
playing: "正在播放",
|
|
2487
|
+
paused: "已暂停",
|
|
2488
|
+
muted: "已静音",
|
|
2489
|
+
volumeLevel: "音量 {percent}%",
|
|
2490
|
+
ended: "播放结束",
|
|
2491
|
+
enteredFullscreen: "已进入全屏",
|
|
2492
|
+
exitedFullscreen: "已退出全屏",
|
|
2493
|
+
errorMessage: "错误:{message}",
|
|
2494
|
+
timeOf: "{current} / {duration}",
|
|
2495
|
+
hourOne: "{n}小时",
|
|
2496
|
+
hourOther: "{n}小时",
|
|
2497
|
+
minuteOne: "{n}分钟",
|
|
2498
|
+
minuteOther: "{n}分钟",
|
|
2499
|
+
secondOne: "{n}秒",
|
|
2500
|
+
secondOther: "{n}秒"
|
|
2501
|
+
};
|
|
2502
|
+
var defaultTranslations2 = {
|
|
2503
|
+
en: englishStrings2,
|
|
2504
|
+
es: spanishStrings2,
|
|
2505
|
+
fr: frenchStrings2,
|
|
2506
|
+
de: germanStrings2,
|
|
2507
|
+
ja: japaneseStrings2,
|
|
2508
|
+
zh: chineseStrings2
|
|
2509
|
+
};
|
|
2510
|
+
|
|
2511
|
+
class I18n2 {
|
|
2512
|
+
language;
|
|
2513
|
+
fallbackLanguage;
|
|
2514
|
+
translations;
|
|
2515
|
+
interpolationPattern;
|
|
2516
|
+
constructor(config = {}) {
|
|
2517
|
+
this.translations = { ...defaultTranslations2 };
|
|
2518
|
+
this.language = config.language || this.detectLanguage() || "en";
|
|
2519
|
+
this.fallbackLanguage = config.fallbackLanguage || "en";
|
|
2520
|
+
if (config.translations) {
|
|
2521
|
+
for (const [lang, strings] of Object.entries(config.translations)) {
|
|
2522
|
+
if (strings) {
|
|
2523
|
+
this.translations[lang] = { ...this.translations[lang], ...strings };
|
|
2524
|
+
}
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2527
|
+
this.interpolationPattern = config.interpolationPattern || /\{(\w+)\}/g;
|
|
2528
|
+
}
|
|
2529
|
+
detectLanguage() {
|
|
2530
|
+
if (typeof navigator === "undefined")
|
|
2531
|
+
return null;
|
|
2532
|
+
const lang = navigator.language || navigator.userLanguage;
|
|
2533
|
+
if (!lang)
|
|
2534
|
+
return null;
|
|
2535
|
+
if (this.translations[lang]) {
|
|
2536
|
+
return lang;
|
|
2537
|
+
}
|
|
2538
|
+
const baseLang = lang.split("-")[0];
|
|
2539
|
+
if (this.translations[baseLang]) {
|
|
2540
|
+
return baseLang;
|
|
2541
|
+
}
|
|
2542
|
+
return null;
|
|
2543
|
+
}
|
|
2544
|
+
getLanguage() {
|
|
2545
|
+
return this.language;
|
|
2546
|
+
}
|
|
2547
|
+
setLanguage(language) {
|
|
2548
|
+
this.language = language;
|
|
2549
|
+
}
|
|
2550
|
+
t(key, params) {
|
|
2551
|
+
let str = this.translations[this.language]?.[key];
|
|
2552
|
+
if (!str) {
|
|
2553
|
+
str = this.translations[this.fallbackLanguage]?.[key];
|
|
2554
|
+
}
|
|
2555
|
+
if (!str) {
|
|
2556
|
+
return key;
|
|
2557
|
+
}
|
|
2558
|
+
if (params) {
|
|
2559
|
+
str = str.replace(this.interpolationPattern, (match, paramKey) => {
|
|
2560
|
+
const value = params[paramKey];
|
|
2561
|
+
return value !== undefined ? String(value) : match;
|
|
2562
|
+
});
|
|
2563
|
+
}
|
|
2564
|
+
return str;
|
|
2565
|
+
}
|
|
2566
|
+
addTranslations(language, strings) {
|
|
2567
|
+
this.translations[language] = {
|
|
2568
|
+
...this.translations[language],
|
|
2569
|
+
...strings
|
|
2570
|
+
};
|
|
2571
|
+
}
|
|
2572
|
+
getTranslations(language) {
|
|
2573
|
+
return this.translations[language];
|
|
2574
|
+
}
|
|
2575
|
+
getAvailableLanguages() {
|
|
2576
|
+
return Object.keys(this.translations);
|
|
2577
|
+
}
|
|
2578
|
+
hasLanguage(language) {
|
|
2579
|
+
return language in this.translations;
|
|
2580
|
+
}
|
|
2581
|
+
}
|
|
2582
|
+
var globalI18n = null;
|
|
2583
|
+
function createI18n2(config) {
|
|
2584
|
+
return new I18n2(config);
|
|
2585
|
+
}
|
|
2586
|
+
function getI18n2(config) {
|
|
2587
|
+
if (!globalI18n) {
|
|
2588
|
+
globalI18n = createI18n2(config);
|
|
2589
|
+
}
|
|
2590
|
+
return globalI18n;
|
|
2591
|
+
}
|
|
2592
|
+
function setI18n2(i18n) {
|
|
2593
|
+
globalI18n = i18n;
|
|
2594
|
+
}
|
|
2595
|
+
function t2(key, params) {
|
|
2596
|
+
return getI18n2().t(key, params);
|
|
2597
|
+
}
|
|
2598
|
+
|
|
2599
|
+
// src/elements/utils.ts
|
|
2600
|
+
function languageOf(el) {
|
|
2601
|
+
let node = el;
|
|
2602
|
+
while (node) {
|
|
2603
|
+
const tagged = node.closest?.("[lang]")?.getAttribute("lang");
|
|
2604
|
+
if (tagged)
|
|
2605
|
+
return tagged.toLowerCase();
|
|
2606
|
+
const root = node.getRootNode?.();
|
|
2607
|
+
node = root && root.host ? root.host : null;
|
|
2608
|
+
}
|
|
2609
|
+
if (typeof navigator !== "undefined" && navigator.language)
|
|
2610
|
+
return navigator.language.toLowerCase();
|
|
2611
|
+
return "en";
|
|
2612
|
+
}
|
|
2613
|
+
function label(el, key, params) {
|
|
2614
|
+
const lang = languageOf(el);
|
|
2615
|
+
const i18n = getI18n2();
|
|
2616
|
+
const text = i18n.getTranslations(lang)?.[key] || i18n.getTranslations(lang.split("-")[0])?.[key] || englishStrings2[key] || key;
|
|
2617
|
+
return params ? text.replace(/\{(\w+)\}/g, (match, name) => params[name] !== undefined ? String(params[name]) : match) : text;
|
|
2618
|
+
}
|
|
2619
|
+
function formatTime2(seconds, guide = 0) {
|
|
2620
|
+
if (!isFinite(seconds) || isNaN(seconds))
|
|
2621
|
+
return "0:00";
|
|
2622
|
+
const s = Math.floor(seconds);
|
|
2623
|
+
const h = Math.floor(s / 3600);
|
|
2624
|
+
const m = Math.floor(s % 3600 / 60);
|
|
2625
|
+
const sec = s % 60;
|
|
2626
|
+
const showHours = h > 0 || guide >= 3600;
|
|
2627
|
+
if (showHours) {
|
|
2628
|
+
return `${h}:${m.toString().padStart(2, "0")}:${sec.toString().padStart(2, "0")}`;
|
|
2629
|
+
}
|
|
2630
|
+
return `${m}:${sec.toString().padStart(2, "0")}`;
|
|
2631
|
+
}
|
|
2632
|
+
function formatTimePhrase2(seconds, el) {
|
|
2633
|
+
const say = (n, one, other) => label(el, n === 1 ? one : other, { n });
|
|
2634
|
+
if (!isFinite(seconds) || isNaN(seconds))
|
|
2635
|
+
return say(0, "secondOne", "secondOther");
|
|
2636
|
+
const s = Math.floor(seconds);
|
|
2637
|
+
const h = Math.floor(s / 3600);
|
|
2638
|
+
const m = Math.floor(s % 3600 / 60);
|
|
2639
|
+
const sec = s % 60;
|
|
2640
|
+
const parts = [];
|
|
2641
|
+
if (h > 0)
|
|
2642
|
+
parts.push(say(h, "hourOne", "hourOther"));
|
|
2643
|
+
if (m > 0)
|
|
2644
|
+
parts.push(say(m, "minuteOne", "minuteOther"));
|
|
2645
|
+
if (sec > 0 || parts.length === 0)
|
|
2646
|
+
parts.push(say(sec, "secondOne", "secondOther"));
|
|
2647
|
+
return parts.join(", ");
|
|
2648
|
+
}
|
|
2649
|
+
function toISODuration2(seconds) {
|
|
2650
|
+
if (!isFinite(seconds) || isNaN(seconds))
|
|
2651
|
+
return "PT0S";
|
|
2652
|
+
const s = Math.floor(seconds);
|
|
2653
|
+
const h = Math.floor(s / 3600);
|
|
2654
|
+
const m = Math.floor(s % 3600 / 60);
|
|
2655
|
+
const sec = s % 60;
|
|
2656
|
+
let result = "PT";
|
|
2657
|
+
if (h > 0)
|
|
2658
|
+
result += `${h}H`;
|
|
2659
|
+
if (m > 0)
|
|
2660
|
+
result += `${m}M`;
|
|
2661
|
+
if (sec > 0 || result === "PT")
|
|
2662
|
+
result += `${sec}S`;
|
|
2663
|
+
return result;
|
|
2664
|
+
}
|
|
2665
|
+
function resolvePlayer2(el) {
|
|
2666
|
+
const forId = el.getAttribute("for");
|
|
2667
|
+
if (forId) {
|
|
2668
|
+
const target = document.getElementById(forId);
|
|
2669
|
+
return target?.player ?? null;
|
|
2670
|
+
}
|
|
2671
|
+
const host = el.closest("video-player");
|
|
2672
|
+
return host?.player ?? null;
|
|
2673
|
+
}
|
|
2674
|
+
|
|
2045
2675
|
// src/player.ts
|
|
2046
2676
|
class Player2 {
|
|
2047
2677
|
_el;
|
|
@@ -2098,8 +2728,8 @@ class Player2 {
|
|
|
2098
2728
|
this._el.classList.add("ts-video-player");
|
|
2099
2729
|
this._el.setAttribute("tabindex", "0");
|
|
2100
2730
|
this._el.setAttribute("role", "region");
|
|
2101
|
-
this._el.setAttribute("aria-roledescription",
|
|
2102
|
-
this._el.setAttribute("aria-label", this._options.title ||
|
|
2731
|
+
this._el.setAttribute("aria-roledescription", label(this._el, "videoRole"));
|
|
2732
|
+
this._el.setAttribute("aria-label", this._options.title || label(this._el, "videoPlayer"));
|
|
2103
2733
|
this._el.setAttribute("aria-keyshortcuts", "Space K M F I C ArrowLeft ArrowRight J L ArrowUp ArrowDown Home End 0 1 2 3 4 5 6 7 8 9");
|
|
2104
2734
|
const mediaContainer = document.createElement("div");
|
|
2105
2735
|
mediaContainer.className = "ts-video-player__container";
|
|
@@ -2123,7 +2753,7 @@ class Player2 {
|
|
|
2123
2753
|
const cover = document.createElement("button");
|
|
2124
2754
|
cover.type = "button";
|
|
2125
2755
|
cover.className = "ts-video-player__cover";
|
|
2126
|
-
cover.setAttribute("aria-label",
|
|
2756
|
+
cover.setAttribute("aria-label", this._options.title ? label(this._el, "playTitle", { title: this._options.title }) : label(this._el, "play"));
|
|
2127
2757
|
cover.hidden = true;
|
|
2128
2758
|
cover.style.cssText = "position:absolute;inset:0;z-index:2;display:none;align-items:center;justify-content:center;width:100%;height:100%;margin:0;padding:0;border:0;border-radius:inherit;background:#000 center/cover no-repeat;cursor:pointer;-webkit-tap-highlight-color:transparent";
|
|
2129
2759
|
const button = document.createElement("span");
|
|
@@ -2348,7 +2978,7 @@ class Player2 {
|
|
|
2348
2978
|
return;
|
|
2349
2979
|
}
|
|
2350
2980
|
this._coverDismissed = false;
|
|
2351
|
-
this._playRequested =
|
|
2981
|
+
this._playRequested = !!this._options.autoplay;
|
|
2352
2982
|
this._store.batch({
|
|
2353
2983
|
sources,
|
|
2354
2984
|
src: sources[0],
|
|
@@ -2408,7 +3038,7 @@ class Player2 {
|
|
|
2408
3038
|
});
|
|
2409
3039
|
if (this._playRequested) {
|
|
2410
3040
|
this._playRequested = false;
|
|
2411
|
-
this.
|
|
3041
|
+
this.startRequestedPlay(this._provider);
|
|
2412
3042
|
}
|
|
2413
3043
|
return;
|
|
2414
3044
|
} catch (error) {
|
|
@@ -2455,12 +3085,12 @@ class Player2 {
|
|
|
2455
3085
|
provider.on("play", () => {
|
|
2456
3086
|
this._store.batch({ paused: false, ended: false });
|
|
2457
3087
|
this._events.emit("play");
|
|
2458
|
-
this.announce("
|
|
3088
|
+
this.announce(label(this._el, "playing"));
|
|
2459
3089
|
});
|
|
2460
3090
|
provider.on("pause", () => {
|
|
2461
3091
|
this._store.set("paused", true);
|
|
2462
3092
|
this._events.emit("pause");
|
|
2463
|
-
this.announce("
|
|
3093
|
+
this.announce(label(this._el, "paused"));
|
|
2464
3094
|
});
|
|
2465
3095
|
provider.on("playing", () => {
|
|
2466
3096
|
this._store.batch({ playing: true, started: true, waiting: false, playbackState: "playing" });
|
|
@@ -2490,9 +3120,9 @@ class Player2 {
|
|
|
2490
3120
|
this._store.batch({ volume, muted });
|
|
2491
3121
|
this._events.emit("volumechange", volume, muted);
|
|
2492
3122
|
if (muted) {
|
|
2493
|
-
this.announce("
|
|
3123
|
+
this.announce(label(this._el, "muted"));
|
|
2494
3124
|
} else {
|
|
2495
|
-
this.announce(
|
|
3125
|
+
this.announce(label(this._el, "volumeLevel", { percent: Math.round(volume * 100) }));
|
|
2496
3126
|
}
|
|
2497
3127
|
});
|
|
2498
3128
|
provider.on("ratechange", (rate) => {
|
|
@@ -2509,7 +3139,7 @@ class Player2 {
|
|
|
2509
3139
|
provider.on("ended", () => {
|
|
2510
3140
|
this._store.batch({ ended: true, playing: false, playbackState: "ended" });
|
|
2511
3141
|
this._events.emit("ended");
|
|
2512
|
-
this.announce("
|
|
3142
|
+
this.announce(label(this._el, "ended"));
|
|
2513
3143
|
if (this.state.loop) {
|
|
2514
3144
|
this.seekTo(0);
|
|
2515
3145
|
this.play();
|
|
@@ -2518,7 +3148,7 @@ class Player2 {
|
|
|
2518
3148
|
provider.on("error", (error) => {
|
|
2519
3149
|
this._store.batch({ loadingState: "error", error });
|
|
2520
3150
|
this._events.emit("error", error);
|
|
2521
|
-
this.announce(
|
|
3151
|
+
this.announce(label(this._el, "errorMessage", { message: error.message }));
|
|
2522
3152
|
});
|
|
2523
3153
|
provider.on("statechange", (state) => {
|
|
2524
3154
|
this._store.batch(state);
|
|
@@ -2531,7 +3161,7 @@ class Player2 {
|
|
|
2531
3161
|
provider.on("fullscreenchange", (fullscreen) => {
|
|
2532
3162
|
this._store.set("fullscreen", fullscreen);
|
|
2533
3163
|
this._events.emit("fullscreenchange", fullscreen);
|
|
2534
|
-
this.announce(fullscreen ? "
|
|
3164
|
+
this.announce(label(this._el, fullscreen ? "enteredFullscreen" : "exitedFullscreen"));
|
|
2535
3165
|
});
|
|
2536
3166
|
provider.on("pipchange", (pip) => {
|
|
2537
3167
|
this._store.set("pictureInPicture", pip);
|
|
@@ -2547,6 +3177,14 @@ class Player2 {
|
|
|
2547
3177
|
this._events.emit("availabilitychange", feature, availability);
|
|
2548
3178
|
});
|
|
2549
3179
|
}
|
|
3180
|
+
async startRequestedPlay(provider) {
|
|
3181
|
+
await provider.play().catch(() => {});
|
|
3182
|
+
if (this._provider !== provider || this.state.error?.code !== 1 || this.state.muted)
|
|
3183
|
+
return;
|
|
3184
|
+
this._store.set("error", null);
|
|
3185
|
+
this.setMuted(true);
|
|
3186
|
+
await provider.play().catch(() => {});
|
|
3187
|
+
}
|
|
2550
3188
|
async play() {
|
|
2551
3189
|
if (!this._provider) {
|
|
2552
3190
|
this._playRequested = true;
|
|
@@ -2871,62 +3509,6 @@ class VideoPlayerElement2 extends HTMLElementBase {
|
|
|
2871
3509
|
}
|
|
2872
3510
|
}
|
|
2873
3511
|
}
|
|
2874
|
-
// src/elements/utils.ts
|
|
2875
|
-
function formatTime2(seconds, guide = 0) {
|
|
2876
|
-
if (!isFinite(seconds) || isNaN(seconds))
|
|
2877
|
-
return "0:00";
|
|
2878
|
-
const s = Math.floor(seconds);
|
|
2879
|
-
const h = Math.floor(s / 3600);
|
|
2880
|
-
const m = Math.floor(s % 3600 / 60);
|
|
2881
|
-
const sec = s % 60;
|
|
2882
|
-
const showHours = h > 0 || guide >= 3600;
|
|
2883
|
-
if (showHours) {
|
|
2884
|
-
return `${h}:${m.toString().padStart(2, "0")}:${sec.toString().padStart(2, "0")}`;
|
|
2885
|
-
}
|
|
2886
|
-
return `${m}:${sec.toString().padStart(2, "0")}`;
|
|
2887
|
-
}
|
|
2888
|
-
function formatTimePhrase2(seconds) {
|
|
2889
|
-
if (!isFinite(seconds) || isNaN(seconds))
|
|
2890
|
-
return "0 seconds";
|
|
2891
|
-
const s = Math.floor(seconds);
|
|
2892
|
-
const h = Math.floor(s / 3600);
|
|
2893
|
-
const m = Math.floor(s % 3600 / 60);
|
|
2894
|
-
const sec = s % 60;
|
|
2895
|
-
const parts = [];
|
|
2896
|
-
if (h > 0)
|
|
2897
|
-
parts.push(`${h} ${h === 1 ? "hour" : "hours"}`);
|
|
2898
|
-
if (m > 0)
|
|
2899
|
-
parts.push(`${m} ${m === 1 ? "minute" : "minutes"}`);
|
|
2900
|
-
if (sec > 0 || parts.length === 0)
|
|
2901
|
-
parts.push(`${sec} ${sec === 1 ? "second" : "seconds"}`);
|
|
2902
|
-
return parts.join(", ");
|
|
2903
|
-
}
|
|
2904
|
-
function toISODuration2(seconds) {
|
|
2905
|
-
if (!isFinite(seconds) || isNaN(seconds))
|
|
2906
|
-
return "PT0S";
|
|
2907
|
-
const s = Math.floor(seconds);
|
|
2908
|
-
const h = Math.floor(s / 3600);
|
|
2909
|
-
const m = Math.floor(s % 3600 / 60);
|
|
2910
|
-
const sec = s % 60;
|
|
2911
|
-
let result = "PT";
|
|
2912
|
-
if (h > 0)
|
|
2913
|
-
result += `${h}H`;
|
|
2914
|
-
if (m > 0)
|
|
2915
|
-
result += `${m}M`;
|
|
2916
|
-
if (sec > 0 || result === "PT")
|
|
2917
|
-
result += `${sec}S`;
|
|
2918
|
-
return result;
|
|
2919
|
-
}
|
|
2920
|
-
function resolvePlayer2(el) {
|
|
2921
|
-
const forId = el.getAttribute("for");
|
|
2922
|
-
if (forId) {
|
|
2923
|
-
const target = document.getElementById(forId);
|
|
2924
|
-
return target?.player ?? null;
|
|
2925
|
-
}
|
|
2926
|
-
const host = el.closest("video-player");
|
|
2927
|
-
return host?.player ?? null;
|
|
2928
|
-
}
|
|
2929
|
-
|
|
2930
3512
|
// src/elements/video-skin.ts
|
|
2931
3513
|
class VideoSkin2 extends HTMLElementBase {
|
|
2932
3514
|
_cleanups = [];
|
|
@@ -3062,7 +3644,7 @@ class MediaPlayButton2 extends HTMLElementBase {
|
|
|
3062
3644
|
}
|
|
3063
3645
|
button:hover { opacity: 0.8; }
|
|
3064
3646
|
</style>
|
|
3065
|
-
<button part="button" type="button" aria-label="
|
|
3647
|
+
<button part="button" type="button" aria-label="${label(this, "play")}">
|
|
3066
3648
|
<svg viewBox="0 0 24 24" width="24" height="24" fill="currentColor" part="icon">
|
|
3067
3649
|
<path d="${PLAY_ICON}"/>
|
|
3068
3650
|
</svg>
|
|
@@ -3088,7 +3670,7 @@ class MediaPlayButton2 extends HTMLElementBase {
|
|
|
3088
3670
|
btn.addEventListener("click", this._onClick);
|
|
3089
3671
|
const unsub = player.subscribe("paused", (state) => {
|
|
3090
3672
|
const paused = state.paused;
|
|
3091
|
-
btn.setAttribute("aria-label", paused ? "
|
|
3673
|
+
btn.setAttribute("aria-label", label(this, paused ? "play" : "pause"));
|
|
3092
3674
|
btn.setAttribute("aria-pressed", String(!paused));
|
|
3093
3675
|
const path = this.shadowRoot.querySelector("path");
|
|
3094
3676
|
path.setAttribute("d", paused ? PLAY_ICON : PAUSE_ICON);
|
|
@@ -3123,7 +3705,7 @@ class MediaMuteButton2 extends HTMLElementBase {
|
|
|
3123
3705
|
}
|
|
3124
3706
|
button:hover { opacity: 0.8; }
|
|
3125
3707
|
</style>
|
|
3126
|
-
<button part="button" type="button" aria-label="
|
|
3708
|
+
<button part="button" type="button" aria-label="${label(this, "mute")}">
|
|
3127
3709
|
<svg viewBox="0 0 24 24" width="24" height="24" fill="currentColor" part="icon">
|
|
3128
3710
|
<path d="${ICON_HIGH}"/>
|
|
3129
3711
|
</svg>
|
|
@@ -3144,7 +3726,7 @@ class MediaMuteButton2 extends HTMLElementBase {
|
|
|
3144
3726
|
btn.addEventListener("click", () => player.toggleMute());
|
|
3145
3727
|
const unsub = player.subscribe((state) => {
|
|
3146
3728
|
const icon = getVolumeIcon(state.muted, state.volume);
|
|
3147
|
-
btn.setAttribute("aria-label", state.muted ? "
|
|
3729
|
+
btn.setAttribute("aria-label", label(this, state.muted ? "unmute" : "mute"));
|
|
3148
3730
|
const path = this.shadowRoot.querySelector("path");
|
|
3149
3731
|
path.setAttribute("d", icon);
|
|
3150
3732
|
});
|
|
@@ -3172,7 +3754,7 @@ class MediaFullscreenButton2 extends HTMLElementBase {
|
|
|
3172
3754
|
button:hover { opacity: 0.8; }
|
|
3173
3755
|
button:disabled { opacity: 0.4; cursor: not-allowed; }
|
|
3174
3756
|
</style>
|
|
3175
|
-
<button part="button" type="button" aria-label="
|
|
3757
|
+
<button part="button" type="button" aria-label="${label(this, "enterFullscreen")}">
|
|
3176
3758
|
<svg viewBox="0 0 24 24" width="24" height="24" fill="currentColor" part="icon">
|
|
3177
3759
|
<path d="${ENTER_FS}"/>
|
|
3178
3760
|
</svg>
|
|
@@ -3200,7 +3782,7 @@ class MediaFullscreenButton2 extends HTMLElementBase {
|
|
|
3200
3782
|
}
|
|
3201
3783
|
btn.disabled = avail !== "available";
|
|
3202
3784
|
const fs = state.fullscreen;
|
|
3203
|
-
btn.setAttribute("aria-label", fs ? "
|
|
3785
|
+
btn.setAttribute("aria-label", label(this, fs ? "exitFullscreen" : "enterFullscreen"));
|
|
3204
3786
|
const path = this.shadowRoot.querySelector("path");
|
|
3205
3787
|
path.setAttribute("d", fs ? EXIT_FS : ENTER_FS);
|
|
3206
3788
|
});
|
|
@@ -3227,7 +3809,7 @@ class MediaPipButton2 extends HTMLElementBase {
|
|
|
3227
3809
|
button:hover { opacity: 0.8; }
|
|
3228
3810
|
button:disabled { opacity: 0.4; cursor: not-allowed; }
|
|
3229
3811
|
</style>
|
|
3230
|
-
<button part="button" type="button" aria-label="
|
|
3812
|
+
<button part="button" type="button" aria-label="${label(this, "enterPiP")}">
|
|
3231
3813
|
<svg viewBox="0 0 24 24" width="24" height="24" fill="currentColor" part="icon">
|
|
3232
3814
|
<path d="${PIP_ICON}"/>
|
|
3233
3815
|
</svg>
|
|
@@ -3254,6 +3836,7 @@ class MediaPipButton2 extends HTMLElementBase {
|
|
|
3254
3836
|
this.removeAttribute("hidden");
|
|
3255
3837
|
}
|
|
3256
3838
|
btn.disabled = avail !== "available";
|
|
3839
|
+
btn.setAttribute("aria-label", label(this, state.pictureInPicture ? "exitPiP" : "enterPiP"));
|
|
3257
3840
|
});
|
|
3258
3841
|
this._cleanup = unsub;
|
|
3259
3842
|
}
|
|
@@ -3284,7 +3867,7 @@ class MediaTimeDisplay2 extends HTMLElementBase {
|
|
|
3284
3867
|
time { color: inherit; }
|
|
3285
3868
|
.separator { margin: 0 2px; }
|
|
3286
3869
|
</style>
|
|
3287
|
-
<time part="time" datetime="PT0S" aria-valuetext="0
|
|
3870
|
+
<time part="time" datetime="PT0S" aria-valuetext="${formatTimePhrase2(0, this)}">0:00</time>
|
|
3288
3871
|
`;
|
|
3289
3872
|
}
|
|
3290
3873
|
this.addEventListener("click", this.handleClick);
|
|
@@ -3330,7 +3913,7 @@ class MediaTimeDisplay2 extends HTMLElementBase {
|
|
|
3330
3913
|
timeEl.textContent = formatTime2(seconds, state.duration);
|
|
3331
3914
|
}
|
|
3332
3915
|
timeEl.setAttribute("datetime", toISODuration2(seconds));
|
|
3333
|
-
timeEl.setAttribute("aria-valuetext", formatTimePhrase2(seconds));
|
|
3916
|
+
timeEl.setAttribute("aria-valuetext", formatTimePhrase2(seconds, this));
|
|
3334
3917
|
}
|
|
3335
3918
|
}
|
|
3336
3919
|
// src/elements/media-time-group.ts
|
|
@@ -3488,7 +4071,7 @@ class MediaProgressBar2 extends HTMLElementBase {
|
|
|
3488
4071
|
</style>
|
|
3489
4072
|
<div class="container" part="container" role="slider"
|
|
3490
4073
|
aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"
|
|
3491
|
-
aria-label="
|
|
4074
|
+
aria-label="${label(this, "seek")}" tabindex="0">
|
|
3492
4075
|
<div class="tooltip" part="tooltip">0:00</div>
|
|
3493
4076
|
<div class="track" part="track">
|
|
3494
4077
|
<div class="waveform" part="waveform" aria-hidden="true"></div>
|
|
@@ -3594,7 +4177,7 @@ class MediaProgressBar2 extends HTMLElementBase {
|
|
|
3594
4177
|
fill.style.width = `${percent}%`;
|
|
3595
4178
|
thumb.style.left = `${percent}%`;
|
|
3596
4179
|
container.setAttribute("aria-valuenow", String(Math.round(percent)));
|
|
3597
|
-
container.setAttribute("aria-valuetext",
|
|
4180
|
+
container.setAttribute("aria-valuetext", label(this, "timeOf", { current: formatTimePhrase2(state.currentTime, this), duration: formatTimePhrase2(duration, this) }));
|
|
3598
4181
|
const bufferedPct = (state.bufferedAmount || 0) * 100;
|
|
3599
4182
|
buffered.style.width = `${bufferedPct}%`;
|
|
3600
4183
|
});
|
|
@@ -3636,7 +4219,7 @@ class MediaVolumeSlider2 extends HTMLElementBase {
|
|
|
3636
4219
|
</style>
|
|
3637
4220
|
<div class="container" part="container" role="slider"
|
|
3638
4221
|
aria-valuemin="0" aria-valuemax="100" aria-valuenow="100"
|
|
3639
|
-
aria-label="
|
|
4222
|
+
aria-label="${label(this, "volume")}" tabindex="0">
|
|
3640
4223
|
<div class="track" part="track">
|
|
3641
4224
|
<div class="fill" part="fill"></div>
|
|
3642
4225
|
<div class="thumb" part="thumb"></div>
|
|
@@ -3831,7 +4414,7 @@ class MediaSettingsMenu2 extends HTMLElementBase {
|
|
|
3831
4414
|
.back { font-weight: bold; border-bottom: 1px solid rgba(255,255,255,0.2); }
|
|
3832
4415
|
</style>
|
|
3833
4416
|
<button class="trigger" part="trigger" type="button"
|
|
3834
|
-
aria-label="
|
|
4417
|
+
aria-label="${label(this, "settings")}" aria-haspopup="true" aria-expanded="false">
|
|
3835
4418
|
<svg viewBox="0 0 24 24" width="24" height="24" fill="currentColor" part="icon">
|
|
3836
4419
|
<path d="${GEAR_ICON}"/>
|
|
3837
4420
|
</svg>
|
|
@@ -3943,35 +4526,35 @@ class MediaSettingsMenu2 extends HTMLElementBase {
|
|
|
3943
4526
|
}
|
|
3944
4527
|
renderMain(menu, player) {
|
|
3945
4528
|
const state = player.state;
|
|
3946
|
-
this.addItem(menu,
|
|
4529
|
+
this.addItem(menu, `${label(this, "speed")}: ${state.playbackRate}x`, () => {
|
|
3947
4530
|
this._currentPanel = "speed";
|
|
3948
4531
|
this.renderPanel();
|
|
3949
4532
|
});
|
|
3950
4533
|
if (state.qualities.length > 0) {
|
|
3951
4534
|
const current = state.qualities.find((q) => q.selected);
|
|
3952
|
-
const
|
|
3953
|
-
this.addItem(menu,
|
|
4535
|
+
const label2 = state.autoQuality ? label(this, "auto") : current ? `${current.height}p` : label(this, "auto");
|
|
4536
|
+
this.addItem(menu, `${label(this, "quality")}: ${label2}`, () => {
|
|
3954
4537
|
this._currentPanel = "quality";
|
|
3955
4538
|
this.renderPanel();
|
|
3956
4539
|
});
|
|
3957
4540
|
}
|
|
3958
4541
|
if (state.textTracks.length > 0) {
|
|
3959
4542
|
const showing = state.textTracks.find((t) => t.mode === "showing");
|
|
3960
|
-
this.addItem(menu,
|
|
4543
|
+
this.addItem(menu, `${label(this, "captions")}: ${showing?.label || label(this, "captionsOff")}`, () => {
|
|
3961
4544
|
this._currentPanel = "captions";
|
|
3962
4545
|
this.renderPanel();
|
|
3963
4546
|
});
|
|
3964
4547
|
}
|
|
3965
4548
|
if (state.audioTracks.length > 1) {
|
|
3966
4549
|
const selected = state.audioTracks.find((track) => track.selected);
|
|
3967
|
-
this.addItem(menu,
|
|
4550
|
+
this.addItem(menu, `${label(this, "audio")}: ${selected?.label || label(this, "defaultTrack")}`, () => {
|
|
3968
4551
|
this._currentPanel = "audio";
|
|
3969
4552
|
this.renderPanel();
|
|
3970
4553
|
});
|
|
3971
4554
|
}
|
|
3972
4555
|
}
|
|
3973
4556
|
renderSpeed(menu, player) {
|
|
3974
|
-
this.addItem(menu, "
|
|
4557
|
+
this.addItem(menu, label(this, "back"), () => {
|
|
3975
4558
|
this._currentPanel = "main";
|
|
3976
4559
|
this.renderPanel();
|
|
3977
4560
|
}, false, true);
|
|
@@ -3984,11 +4567,11 @@ class MediaSettingsMenu2 extends HTMLElementBase {
|
|
|
3984
4567
|
}
|
|
3985
4568
|
}
|
|
3986
4569
|
renderQuality(menu, player) {
|
|
3987
|
-
this.addItem(menu, "
|
|
4570
|
+
this.addItem(menu, label(this, "back"), () => {
|
|
3988
4571
|
this._currentPanel = "main";
|
|
3989
4572
|
this.renderPanel();
|
|
3990
4573
|
}, false, true);
|
|
3991
|
-
this.addItem(menu, "
|
|
4574
|
+
this.addItem(menu, label(this, "auto"), () => {
|
|
3992
4575
|
player.setQuality("auto");
|
|
3993
4576
|
this.close();
|
|
3994
4577
|
}, player.state.autoQuality);
|
|
@@ -4000,12 +4583,12 @@ class MediaSettingsMenu2 extends HTMLElementBase {
|
|
|
4000
4583
|
}
|
|
4001
4584
|
}
|
|
4002
4585
|
renderCaptions(menu, player) {
|
|
4003
|
-
this.addItem(menu, "
|
|
4586
|
+
this.addItem(menu, label(this, "back"), () => {
|
|
4004
4587
|
this._currentPanel = "main";
|
|
4005
4588
|
this.renderPanel();
|
|
4006
4589
|
}, false, true);
|
|
4007
4590
|
const anyShowing = player.state.textTracks.some((t) => t.mode === "showing");
|
|
4008
|
-
this.addItem(menu, "
|
|
4591
|
+
this.addItem(menu, label(this, "captionsOff"), () => {
|
|
4009
4592
|
for (const t of player.state.textTracks) {
|
|
4010
4593
|
if (t.mode === "showing")
|
|
4011
4594
|
player.setTextTrack(t.id, "disabled");
|
|
@@ -4022,12 +4605,12 @@ class MediaSettingsMenu2 extends HTMLElementBase {
|
|
|
4022
4605
|
}
|
|
4023
4606
|
}
|
|
4024
4607
|
renderAudio(menu, player) {
|
|
4025
|
-
this.addItem(menu, "
|
|
4608
|
+
this.addItem(menu, label(this, "back"), () => {
|
|
4026
4609
|
this._currentPanel = "main";
|
|
4027
4610
|
this.renderPanel();
|
|
4028
4611
|
}, false, true);
|
|
4029
4612
|
for (const track of player.state.audioTracks) {
|
|
4030
|
-
this.addItem(menu, track.label || track.language ||
|
|
4613
|
+
this.addItem(menu, track.label || track.language || label(this, "audioTrack"), () => {
|
|
4031
4614
|
player.setAudioTrack(track.id);
|
|
4032
4615
|
this.close();
|
|
4033
4616
|
}, track.selected);
|
|
@@ -4079,9 +4662,8 @@ class MediaSeekButton2 extends HTMLElementBase {
|
|
|
4079
4662
|
return;
|
|
4080
4663
|
const seconds = Number.parseFloat(this.getAttribute("seconds") ?? "10");
|
|
4081
4664
|
const offset = Number.isFinite(seconds) && seconds !== 0 ? seconds : 10;
|
|
4082
|
-
const label = offset > 0 ? `Forward ${offset} seconds` : `Back ${Math.abs(offset)} seconds`;
|
|
4083
4665
|
button.textContent = offset > 0 ? `+${offset}` : String(offset);
|
|
4084
|
-
button.setAttribute("aria-label", label);
|
|
4666
|
+
button.setAttribute("aria-label", label(this, offset > 0 ? "seekForward" : "seekBackward", { seconds: Math.abs(offset) }));
|
|
4085
4667
|
this.onClick = () => player.seekBy(offset);
|
|
4086
4668
|
button.addEventListener("click", this.onClick);
|
|
4087
4669
|
this.cleanup = player.subscribe((state) => {
|
|
@@ -4105,7 +4687,7 @@ class MediaPlaybackRateButton2 extends HTMLElementBase {
|
|
|
4105
4687
|
button:hover { opacity: .8; }
|
|
4106
4688
|
button:focus-visible { outline: 2px solid currentColor; outline-offset: -2px; }
|
|
4107
4689
|
</style>
|
|
4108
|
-
<button part="button" type="button" aria-label="
|
|
4690
|
+
<button part="button" type="button" aria-label="${label(this, "speed")}"></button>
|
|
4109
4691
|
`;
|
|
4110
4692
|
}
|
|
4111
4693
|
queueMicrotask(() => this.attach());
|
|
@@ -4135,7 +4717,7 @@ class MediaPlaybackRateButton2 extends HTMLElementBase {
|
|
|
4135
4717
|
button.addEventListener("click", this.onClick);
|
|
4136
4718
|
this.cleanup = player.subscribe("playbackRate", (state) => {
|
|
4137
4719
|
button.textContent = `${state.playbackRate}x`;
|
|
4138
|
-
button.setAttribute("aria-label",
|
|
4720
|
+
button.setAttribute("aria-label", label(this, "playbackRate", { rate: state.playbackRate }));
|
|
4139
4721
|
});
|
|
4140
4722
|
}
|
|
4141
4723
|
}
|
|
@@ -4155,7 +4737,7 @@ class MediaAirplayButton2 extends HTMLElementBase {
|
|
|
4155
4737
|
button:hover { opacity: 0.8; }
|
|
4156
4738
|
:host([connected]) button { color: var(--media-airplay-active-color, #38bdf8); }
|
|
4157
4739
|
</style>
|
|
4158
|
-
<button part="button" type="button" aria-label="
|
|
4740
|
+
<button part="button" type="button" aria-label="${label(this, "airPlayPlay")}">
|
|
4159
4741
|
<svg viewBox="0 0 24 24" width="24" height="24" fill="currentColor" part="icon"><path d="${AIRPLAY_ICON}"/></svg>
|
|
4160
4742
|
</button>
|
|
4161
4743
|
`;
|
|
@@ -4214,7 +4796,7 @@ class MediaLiveButton2 extends HTMLElementBase {
|
|
|
4214
4796
|
i { width: 8px; height: 8px; border-radius: 9999px; background: #ef4444; }
|
|
4215
4797
|
:host(:not([at-live-edge])) button { opacity: 0.72; }
|
|
4216
4798
|
</style>
|
|
4217
|
-
<button part="button" type="button" aria-label="
|
|
4799
|
+
<button part="button" type="button" aria-label="${label(this, "seekToLive")}"><i aria-hidden="true"></i><span>${label(this, "live")}</span></button>
|
|
4218
4800
|
`;
|
|
4219
4801
|
}
|
|
4220
4802
|
queueMicrotask(() => this.attach());
|
|
@@ -4310,7 +4892,7 @@ class MediaRemotePlaybackButton2 extends HTMLElementBase {
|
|
|
4310
4892
|
button:hover { opacity: 0.8; }
|
|
4311
4893
|
:host([connected]) button { color: var(--media-remote-active-color, #38bdf8); }
|
|
4312
4894
|
</style>
|
|
4313
|
-
<button part="button" type="button" aria-label="
|
|
4895
|
+
<button part="button" type="button" aria-label="${label(this, "remotePlayback")}">
|
|
4314
4896
|
<svg viewBox="0 0 24 24" width="24" height="24" fill="currentColor" part="icon"><path d="${REMOTE_ICON}"/></svg>
|
|
4315
4897
|
</button>
|
|
4316
4898
|
`;
|
|
@@ -4413,4 +4995,4 @@ function registerElements2() {
|
|
|
4413
4995
|
}
|
|
4414
4996
|
}
|
|
4415
4997
|
|
|
4416
|
-
export { isMediaSessionSupported2, createMediaSession2, updateMetadata2, isOrientationLockSupported2, lockOrientation2, unlockOrientation2, BaseProvider2, isHTML5Source2, HTML5Provider2, html5Loader2, extractYouTubeId2, isYouTubeSource2, YouTubeProvider2, youtubeLoader2, extractVimeoId2, extractVimeoHash2, isVimeoSource2, VimeoProvider2, vimeoLoader2, isHLSSource2, isNativeHLSSupported2, HLSProvider2, hlsLoader2, isDASHSource2, DASHProvider2, dashLoader2, defaultLoaders2, findLoader2, detectMediaType2, getPreconnectHints2,
|
|
4998
|
+
export { isMediaSessionSupported2, createMediaSession2, updateMetadata2, isOrientationLockSupported2, lockOrientation2, unlockOrientation2, BaseProvider2, isHTML5Source2, HTML5Provider2, html5Loader2, extractYouTubeId2, isYouTubeSource2, YouTubeProvider2, youtubeLoader2, extractVimeoId2, extractVimeoHash2, isVimeoSource2, VimeoProvider2, vimeoLoader2, isHLSSource2, isNativeHLSSupported2, HLSProvider2, hlsLoader2, isDASHSource2, DASHProvider2, dashLoader2, defaultLoaders2, findLoader2, detectMediaType2, getPreconnectHints2, englishStrings2, spanishStrings2, frenchStrings2, germanStrings2, japaneseStrings2, chineseStrings2, defaultTranslations2, I18n2, createI18n2, getI18n2, setI18n2, t2, formatTime2, formatTimePhrase2, toISODuration2, resolvePlayer2, Player2, createPlayer2, getPlayer2, VideoPlayerElement2, VideoSkin2, MediaPlayButton2, MediaMuteButton2, MediaFullscreenButton2, MediaPipButton2, MediaTimeDisplay2, MediaTimeGroup2, MediaTimeSeparator2, MediaPreviewTime2, MediaProgressBar2, MediaVolumeSlider2, computePosition2, applyPosition2, MediaSettingsMenu2, MediaSeekButton2, MediaPlaybackRateButton2, MediaAirplayButton2, MediaLiveButton2, MediaErrorDisplay2, MediaRemotePlaybackButton2, registerElements2 };
|