@vplayer/core 0.3.0 → 0.4.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.
package/dist/index.d.ts CHANGED
@@ -23,5 +23,5 @@ export type { MediaSessionController } from './media-session';
23
23
  export { BaseMediaEngine, NativeVideoEngine, HlsMediaEngine, DashMediaEngine } from './media-engine';
24
24
  export type { MediaEngine, MediaEngineDimensions, MediaEngineError, MediaEngineEvent, MediaEngineEventHandler, HlsMediaEngineOptions, DashMediaEngineOptions, } from './media-engine';
25
25
  export { createMediaStore, getInitialMediaState, selectMedia, selectAudio, selectPreferences, selectUI, selectPlugins, selectThumbnails, selectError, } from './state/slices';
26
- export type { PlayerOptions, TransformThumbnailVTT, MediaState, ResumeState, MediaRemote, PlayerLabels, PlayerInstance, PlayerSystems, PlayerError, PlaybackStatus, } from './types';
26
+ export type { PlayerOptions, MediaSessionMetadataOptions, TransformThumbnailVTT, MediaState, ResumeState, MediaRemote, PlayerLabels, PlayerInstance, PlayerSystems, PlayerError, PlaybackStatus, } from './types';
27
27
  export type { ControlRegistration, SettingRegistration, LayerRegistration, ContextMenuItem, ContextMenuRegistration, PlayerPlugin, PluginAPI, RemoteRef, PlayerContextRef, FlipState, AspectRatioState, SettingItem, } from './plugin-api';
package/dist/index.js CHANGED
@@ -205,70 +205,72 @@ function _(e, t, n) {
205
205
  } catch {}
206
206
  }
207
207
  function v() {
208
- let e = null, t, n, r = !1, i = NaN, a = NaN, o = NaN;
209
- function s() {
210
- let r = g();
211
- r && e && r.metadata === e && (r.metadata = null), e = null, t = void 0, n = void 0;
208
+ let e = null, t, n, r, i, a = !1, o = NaN, s = NaN, c = NaN;
209
+ function l() {
210
+ let a = g();
211
+ a && e && a.metadata === e && (a.metadata = null), e = null, t = void 0, n = void 0, r = void 0, i = void 0;
212
212
  }
213
- function c(e) {
213
+ function u(e) {
214
214
  let t = g();
215
- !t || r || (_(t, "play", () => e.play()), _(t, "pause", () => e.pause()), _(t, "seekbackward", (t) => {
215
+ !t || a || (_(t, "play", () => e.play()), _(t, "pause", () => e.pause()), _(t, "seekbackward", (t) => {
216
216
  e.skip(-(t.seekOffset ?? p));
217
217
  }), _(t, "seekforward", (t) => {
218
218
  e.skip(t.seekOffset ?? p);
219
219
  }), _(t, "seekto", (t) => {
220
220
  typeof t.seekTime == "number" && e.seek(t.seekTime);
221
- }), r = !0);
222
- }
223
- function l(r, i) {
224
- let a = g();
225
- if (!a || typeof MediaMetadata > "u") return;
226
- let o = r?.trim() || void 0;
227
- if (!o) {
228
- s();
221
+ }), a = !0);
222
+ }
223
+ function d(a, o, s) {
224
+ let c = g();
225
+ if (!c || typeof MediaMetadata > "u") return;
226
+ let u = a?.trim() || void 0, d = o?.artwork ?? s, f = o?.artist?.trim() || void 0, p = o?.album?.trim() || void 0;
227
+ if (!u) {
228
+ l();
229
229
  return;
230
230
  }
231
- if (e && a.metadata === e && t === o && n === i) return;
232
- let c = new MediaMetadata({
233
- title: o,
234
- artwork: i ? [{ src: i }] : []
231
+ if (e && c.metadata === e && t === u && n === d && r === f && i === p) return;
232
+ let m = new MediaMetadata({
233
+ title: u,
234
+ ...f ? { artist: f } : {},
235
+ ...p ? { album: p } : {},
236
+ artwork: d ? [{ src: d }] : []
235
237
  });
236
- a.metadata = c, e = c, t = o, n = i;
238
+ c.metadata = m, e = m, t = u, n = d, r = f, i = p;
237
239
  }
238
- function u(e) {
240
+ function v(e) {
239
241
  let t = g();
240
242
  t && (t.playbackState = e);
241
243
  }
242
- function d(e, t, n, r = !1) {
243
- let s = g();
244
- if (!(!s || typeof s.setPositionState != "function") && !(!f(e) || !Number.isFinite(t) || t < 0) && !(!r && Number.isFinite(i) && Math.abs(t - i) < m && e === a && n === o)) try {
245
- s.setPositionState({
244
+ function y(e, t, n, r = !1) {
245
+ let i = g();
246
+ if (!(!i || typeof i.setPositionState != "function") && !(!f(e) || !Number.isFinite(t) || t < 0) && !(!r && Number.isFinite(o) && Math.abs(t - o) < m && e === s && n === c)) try {
247
+ i.setPositionState({
246
248
  duration: e,
247
249
  playbackRate: n,
248
250
  position: Math.min(t, e)
249
- }), i = t, a = e, o = n;
251
+ }), o = t, s = e, c = n;
250
252
  } catch {}
251
253
  }
252
- function v() {
254
+ function b() {
253
255
  let e = g();
254
256
  if (e) {
255
- if (r) {
257
+ if (a) {
256
258
  for (let t of h) _(e, t, null);
257
- r = !1;
259
+ a = !1;
258
260
  }
259
261
  e.playbackState = "none";
260
262
  }
261
- s(), i = NaN, a = NaN, o = NaN;
263
+ l(), o = NaN, s = NaN, c = NaN;
262
264
  }
263
265
  return {
264
- setup: c,
265
- syncMetadata: l,
266
- setPlaybackState: u,
267
- syncPosition: d,
266
+ setup: u,
267
+ syncMetadata: d,
268
+ setPlaybackState: v,
269
+ syncPosition: y,
268
270
  get hasMetadata() {
269
271
  return e !== null;
270
272
  },
271
- teardown: v
273
+ teardown: b
272
274
  };
273
275
  }
274
276
  //#endregion
@@ -867,15 +869,15 @@ var U = (e) => ({
867
869
  layers: e.layers,
868
870
  contextMenuItems: e.contextMenuItems,
869
871
  contextMenuEnabled: e.contextMenuEnabled
870
- }), se = (e) => ({ thumbnailCues: e.thumbnailCues }), q = (e) => e.error, J = [
872
+ }), se = (e) => ({ thumbnailCues: e.thumbnailCues }), ce = (e) => e.error, q = [
871
873
  "default",
872
874
  "16:9",
873
875
  "4:3",
874
876
  "21:9",
875
877
  "cover",
876
878
  "fill"
877
- ], ce = 5e3, le = 2;
878
- function ue(e) {
879
+ ], le = 5e3, ue = 2;
880
+ function de(e) {
879
881
  try {
880
882
  let t = new URL(e, typeof document > "u" ? void 0 : document.baseURI);
881
883
  return t.search = "", t.hash = "", t.href;
@@ -883,11 +885,11 @@ function ue(e) {
883
885
  return e.split(/[?#]/, 1)[0] ?? e;
884
886
  }
885
887
  }
886
- var de = {
888
+ var fe = {
887
889
  "16:9": "16 / 9",
888
890
  "4:3": "4 / 3",
889
891
  "21:9": "21 / 9"
890
- }, fe = {
892
+ }, pe = {
891
893
  default: "default",
892
894
  "16:9": "16-9",
893
895
  "4:3": "4-3",
@@ -895,27 +897,27 @@ var de = {
895
897
  cover: "cover",
896
898
  fill: "fill"
897
899
  };
898
- function pe(e) {
899
- e.classList.remove("vplayer--media-default", "vplayer--media-16-9", "vplayer--media-4-3", "vplayer--media-21-9", "vplayer--media-cover", "vplayer--media-fill");
900
- }
901
900
  function me(e) {
902
- return typeof e == "string" && e in fe ? e : "default";
901
+ e.classList.remove("vplayer--media-default", "vplayer--media-16-9", "vplayer--media-4-3", "vplayer--media-21-9", "vplayer--media-cover", "vplayer--media-fill");
903
902
  }
904
903
  function he(e) {
904
+ return typeof e == "string" && e in pe ? e : "default";
905
+ }
906
+ function ge(e) {
905
907
  return e === "cover" ? "cover" : e === "fill" ? "fill" : "contain";
906
908
  }
907
- function Y(e) {
909
+ function J(e) {
908
910
  return {
909
911
  ...e,
910
912
  id: e.id ?? `${e.local ? "local" : "track"}:${e.src ?? e.label}:${e.lang}`
911
913
  };
912
914
  }
913
- function ge(e) {
915
+ function Y(e) {
914
916
  let r = ae(), i = { ...e }, o = new t(), s = new b(), c = new a(i.lang);
915
917
  i.translations && c.addTranslations(i.lang ?? "en", i.translations);
916
918
  let l = new n(), u = i.reconnectMax ?? 3, p = i.reconnectSleep ?? 1500, m = null, h = null, g = null, _ = 0, y = NaN, S = null, C = 0, w = null, T = null, E = null, D = v(), A = new ee(), j = 0, M = !1, N = null, P = [], F = !1;
917
919
  function I(e) {
918
- let t = e.playbackProgress?.id ?? (e.playbackProgress?.normalizeUrl === !1 ? e.src : ue(e.src));
920
+ let t = e.playbackProgress?.id ?? (e.playbackProgress?.normalizeUrl === !1 ? e.src : de(e.src));
919
921
  return {
920
922
  generation: j,
921
923
  id: t,
@@ -953,7 +955,7 @@ function ge(e) {
953
955
  }));
954
956
  }
955
957
  function ie(e) {
956
- !r.state.isPlaying || Date.now() - _ < ce || Number.isFinite(y) && Math.abs(e.currentTime - y) < le || V(L, e);
958
+ !r.state.isPlaying || Date.now() - _ < le || Number.isFinite(y) && Math.abs(e.currentTime - y) < ue || V(L, e);
957
959
  }
958
960
  function H() {
959
961
  j++, L = I(i), M = !1, _ = 0, y = NaN, r.setState((e) => ({
@@ -996,7 +998,7 @@ function ge(e) {
996
998
  r.setState((t) => {
997
999
  let n = new Map(t.subtitleTracks.map((e) => [e.id, e]));
998
1000
  for (let t of e) {
999
- let e = Y(t);
1001
+ let e = J(t);
1000
1002
  n.set(e.id, e);
1001
1003
  }
1002
1004
  return {
@@ -1103,7 +1105,7 @@ function ge(e) {
1103
1105
  subtitleError: null
1104
1106
  })), (async () => {
1105
1107
  try {
1106
- let i = await t.fetch(e, n.signal), a = Y({
1108
+ let i = await t.fetch(e, n.signal), a = J({
1107
1109
  id: `provider:${t.id}:${e.id}`,
1108
1110
  lang: e.language,
1109
1111
  label: e.label,
@@ -1130,63 +1132,60 @@ function ge(e) {
1130
1132
  })();
1131
1133
  }
1132
1134
  i.subtitles?.length && W(i.subtitles), K();
1133
- function q() {
1134
- return i.mediaSessionArtwork ?? i.poster;
1135
- }
1136
- function ge() {
1135
+ function ce() {
1137
1136
  l.register({
1138
1137
  key: "Space",
1139
1138
  description: "Toggle play/pause",
1140
1139
  handler: (e) => {
1141
- e.preventDefault(), Z.togglePlay();
1140
+ e.preventDefault(), X.togglePlay();
1142
1141
  }
1143
1142
  }), l.register({
1144
1143
  key: "KeyK",
1145
1144
  description: "Toggle play/pause",
1146
1145
  handler: (e) => {
1147
- e.preventDefault(), Z.togglePlay();
1146
+ e.preventDefault(), X.togglePlay();
1148
1147
  }
1149
1148
  }), l.register({
1150
1149
  key: "KeyL",
1151
1150
  description: "Toggle loop",
1152
1151
  handler: (e) => {
1153
- e.preventDefault(), Z.toggleLoop();
1152
+ e.preventDefault(), X.toggleLoop();
1154
1153
  }
1155
1154
  }), l.register({
1156
1155
  key: "KeyI",
1157
1156
  description: "Toggle info panel",
1158
1157
  handler: (e) => {
1159
- e.preventDefault(), Z.toggleInfoPanel();
1158
+ e.preventDefault(), X.toggleInfoPanel();
1160
1159
  }
1161
1160
  }), l.register({
1162
1161
  key: "KeyF",
1163
1162
  description: "Toggle fullscreen",
1164
1163
  handler: (e) => {
1165
- e.preventDefault(), Z.toggleFullscreen();
1164
+ e.preventDefault(), X.toggleFullscreen();
1166
1165
  }
1167
1166
  }), l.register({
1168
1167
  key: "KeyA",
1169
1168
  description: "Cycle aspect ratio",
1170
1169
  handler: (e) => {
1171
- e.preventDefault(), Z.cycleAspectRatio();
1170
+ e.preventDefault(), X.cycleAspectRatio();
1172
1171
  }
1173
1172
  }), l.register({
1174
1173
  key: "KeyM",
1175
1174
  description: "Toggle mute",
1176
1175
  handler: (e) => {
1177
- e.preventDefault(), Z.toggleMute();
1176
+ e.preventDefault(), X.toggleMute();
1178
1177
  }
1179
1178
  }), l.register({
1180
1179
  key: "ArrowLeft",
1181
1180
  description: "Seek backward 5s",
1182
1181
  handler: (e) => {
1183
- e.preventDefault(), Z.skip(-5);
1182
+ e.preventDefault(), X.skip(-5);
1184
1183
  }
1185
1184
  }), l.register({
1186
1185
  key: "ArrowRight",
1187
1186
  description: "Seek forward 5s",
1188
1187
  handler: (e) => {
1189
- e.preventDefault(), Z.skip(5);
1188
+ e.preventDefault(), X.skip(5);
1190
1189
  }
1191
1190
  }), l.register({
1192
1191
  key: "ArrowUp",
@@ -1194,7 +1193,7 @@ function ge(e) {
1194
1193
  handler: (e) => {
1195
1194
  e.preventDefault();
1196
1195
  let t = Math.min(1, r.state.volume + .1);
1197
- Z.setVolume(t);
1196
+ X.setVolume(t);
1198
1197
  }
1199
1198
  }), l.register({
1200
1199
  key: "ArrowDown",
@@ -1202,12 +1201,12 @@ function ge(e) {
1202
1201
  handler: (e) => {
1203
1202
  e.preventDefault();
1204
1203
  let t = Math.max(0, r.state.volume - .1);
1205
- Z.setVolume(t);
1204
+ X.setVolume(t);
1206
1205
  }
1207
1206
  });
1208
1207
  }
1209
- i.defaultHotkeys !== !1 && ge();
1210
- function X() {
1208
+ i.defaultHotkeys !== !1 && ce();
1209
+ function Y() {
1211
1210
  if (typeof document > "u") return;
1212
1211
  let e = document;
1213
1212
  r.setState((t) => ({
@@ -1216,7 +1215,7 @@ function ge(e) {
1216
1215
  capabilities: d(h?.element ?? void 0, m)
1217
1216
  }));
1218
1217
  }
1219
- let Z = {
1218
+ let X = {
1220
1219
  play: () => {
1221
1220
  h?.play();
1222
1221
  },
@@ -1279,7 +1278,7 @@ function ge(e) {
1279
1278
  toggleFullscreen: () => {
1280
1279
  if (!m || typeof document > "u") return;
1281
1280
  let e = m, t = document, n = !!(document.fullscreenElement || t.webkitFullscreenElement), r = () => {
1282
- m?.focus({ preventScroll: !0 }), X();
1281
+ m?.focus({ preventScroll: !0 }), Y();
1283
1282
  }, i = n ? typeof document.exitFullscreen == "function" ? document.exitFullscreen() : t.webkitExitFullscreen?.() : typeof m.requestFullscreen == "function" ? m.requestFullscreen() : e.webkitRequestFullscreen?.();
1284
1283
  Promise.resolve(i).then(r, r);
1285
1284
  },
@@ -1301,11 +1300,11 @@ function ge(e) {
1301
1300
  G(e);
1302
1301
  },
1303
1302
  addSubtitleTrack: (e) => {
1304
- let t = Y(e);
1303
+ let t = J(e);
1305
1304
  W([t]), G(t);
1306
1305
  },
1307
1306
  removeSubtitleTrack: (e) => {
1308
- r.state.activeSubtitle?.id === e && Z.setActiveSubtitle(null), r.setState((t) => ({
1307
+ r.state.activeSubtitle?.id === e && X.setActiveSubtitle(null), r.setState((t) => ({
1309
1308
  ...t,
1310
1309
  subtitleTracks: t.subtitleTracks.filter((t) => t.id !== e)
1311
1310
  }));
@@ -1368,17 +1367,17 @@ function ge(e) {
1368
1367
  }));
1369
1368
  },
1370
1369
  setAspectRatio: (e) => {
1371
- let t = me(e), n = h?.element;
1370
+ let t = he(e), n = h?.element;
1372
1371
  if (!n) return;
1373
- let i = de[t];
1374
- i ? n.style.setProperty("--vplayer-media-aspect-ratio", i) : n.style.removeProperty("--vplayer-media-aspect-ratio"), n.style.objectFit = he(t), n.style.setProperty("--vplayer-media-object-fit", he(t)), m && (pe(m), m.classList.add(`vplayer--media-${fe[t]}`)), r.setState((e) => ({
1372
+ let i = fe[t];
1373
+ i ? n.style.setProperty("--vplayer-media-aspect-ratio", i) : n.style.removeProperty("--vplayer-media-aspect-ratio"), n.style.objectFit = ge(t), n.style.setProperty("--vplayer-media-object-fit", ge(t)), m && (me(m), m.classList.add(`vplayer--media-${pe[t]}`)), r.setState((e) => ({
1375
1374
  ...e,
1376
1375
  aspectRatio: t
1377
1376
  }));
1378
1377
  },
1379
1378
  cycleAspectRatio: () => {
1380
- let e = r.state.aspectRatio, t = J[(J.indexOf(e) + 1) % J.length] ?? "default";
1381
- Z.setAspectRatio(t);
1379
+ let e = r.state.aspectRatio, t = q[(q.indexOf(e) + 1) % q.length] ?? "default";
1380
+ X.setAspectRatio(t);
1382
1381
  },
1383
1382
  toggleLoop: () => {
1384
1383
  let e = h;
@@ -1397,7 +1396,7 @@ function ge(e) {
1397
1396
  function _e(e) {
1398
1397
  return [
1399
1398
  e.on("play", () => {
1400
- D.syncMetadata(i.title, q()), D.setPlaybackState("playing"), r.setState((e) => ({
1399
+ D.syncMetadata(i.title, i.mediaSession, i.poster), D.setPlaybackState("playing"), r.setState((e) => ({
1401
1400
  ...e,
1402
1401
  status: "playing",
1403
1402
  isPlaying: !0,
@@ -1552,7 +1551,7 @@ function ge(e) {
1552
1551
  })
1553
1552
  ];
1554
1553
  }
1555
- let Q = null;
1554
+ let Z = null;
1556
1555
  function ve() {
1557
1556
  let e = s.get(x.CAPTION_SETTINGS);
1558
1557
  e && r.setState((t) => ({
@@ -1574,19 +1573,19 @@ function ge(e) {
1574
1573
  playbackRate: n ?? r.playbackRate,
1575
1574
  isLooping: a ?? r.isLooping,
1576
1575
  flip: o ?? r.flip,
1577
- aspectRatio: me(c)
1578
- })), ve(), Q = r.subscribe(() => {
1576
+ aspectRatio: he(c)
1577
+ })), ve(), Z = r.subscribe(() => {
1579
1578
  let e = r.state;
1580
1579
  e.volume !== 1 && s.set(x.VOLUME, e.volume), e.isMuted && s.set(x.MUTED, !0), e.playbackRate !== 1 && s.set(x.PLAYBACK_RATE, e.playbackRate), e.isLooping ? s.set(x.LOOP, !0) : s.remove(x.LOOP), e.flip === "normal" ? s.remove(x.FLIP) : s.set(x.FLIP, e.flip), e.aspectRatio === "default" ? s.remove(x.ASPECT_RATIO) : s.set(x.ASPECT_RATIO, e.aspectRatio), s.set(x.CAPTION_SETTINGS, e.captionSettings);
1581
1580
  });
1582
1581
  }
1583
1582
  function be() {
1584
- if (Q) {
1585
- let e = Q;
1586
- typeof e == "function" ? e() : e.unsubscribe(), Q = null;
1583
+ if (Z) {
1584
+ let e = Z;
1585
+ typeof e == "function" ? e() : e.unsubscribe(), Z = null;
1587
1586
  }
1588
1587
  }
1589
- function $(e) {
1588
+ function Q(e) {
1590
1589
  if (w?.abort(), w = null, !e) {
1591
1590
  r.setState((e) => ({
1592
1591
  ...e,
@@ -1611,7 +1610,7 @@ function ge(e) {
1611
1610
  return {
1612
1611
  name: e,
1613
1612
  store: r,
1614
- remote: Z,
1613
+ remote: X,
1615
1614
  events: o,
1616
1615
  storage: s,
1617
1616
  hotkeys: l,
@@ -1690,15 +1689,15 @@ function ge(e) {
1690
1689
  }
1691
1690
  };
1692
1691
  }
1693
- let Se = [];
1694
- function Ce(e = !0) {
1692
+ let $ = [];
1693
+ function Se(e = !0) {
1695
1694
  S !== null && (clearTimeout(S), S = null), C = 0;
1696
- for (let e of Se) e();
1697
- Se = [], h && (e && V(L, h), h.pause(), h.destroy(), h = null, Ee.engine = null);
1695
+ for (let e of $) e();
1696
+ $ = [], h && (e && V(L, h), h.pause(), h.destroy(), h = null, Te.engine = null);
1698
1697
  }
1699
- function we(e) {
1698
+ function Ce(e) {
1700
1699
  let t = O(i), n = te(e, i);
1701
- h = n, Ee.engine = n, Se = _e(n), e.playsInline = !0, e.autoplay = !!i.autoPlay, e.preload = e.preload || "metadata", D.setPlaybackState("paused"), r.setState((n) => ({
1700
+ h = n, Te.engine = n, $ = _e(n), e.playsInline = !0, e.autoplay = !!i.autoPlay, e.preload = e.preload || "metadata", D.setPlaybackState("paused"), r.setState((n) => ({
1702
1701
  ...n,
1703
1702
  status: "loading",
1704
1703
  source: t,
@@ -1713,16 +1712,16 @@ function ge(e) {
1713
1712
  error: null
1714
1713
  })), i.autoPlay && n.play();
1715
1714
  }
1716
- function Te(e = !0) {
1715
+ function we(e = !0) {
1717
1716
  let t = h?.element;
1718
1717
  if (t) {
1719
- for (Ce(e), t.pause(), t.removeAttribute("src"); t.firstChild;) t.removeChild(t.firstChild);
1720
- t.load(), we(t);
1718
+ for (Se(e), t.pause(), t.removeAttribute("src"); t.firstChild;) t.removeChild(t.firstChild);
1719
+ t.load(), Ce(t);
1721
1720
  }
1722
1721
  }
1723
- let Ee = {
1722
+ let Te = {
1724
1723
  store: r,
1725
- remote: Z,
1724
+ remote: X,
1726
1725
  events: o,
1727
1726
  storage: s,
1728
1727
  i18n: c,
@@ -1733,7 +1732,7 @@ function ge(e) {
1733
1732
  ...i,
1734
1733
  ...e
1735
1734
  }, l = I(c), u = l.id !== L.id || l.store !== L.store;
1736
- if ((t || u) && V(L, h), i = c, (t || u) && H(), (r.state.isPlaying || D.hasMetadata) && D.syncMetadata(i.title, q()), r.setState((t) => {
1735
+ if ((t || u) && V(L, h), i = c, (t || u) && H(), (r.state.isPlaying || D.hasMetadata) && D.syncMetadata(i.title, i.mediaSession, i.poster), r.setState((t) => {
1737
1736
  let n = e.qualities ?? t.qualities;
1738
1737
  return {
1739
1738
  ...t,
@@ -1742,15 +1741,15 @@ function ge(e) {
1742
1741
  };
1743
1742
  }), e.subtitles && (W(e.subtitles), !r.state.activeSubtitle)) {
1744
1743
  let t = e.subtitles.find((e) => e.default) ?? null;
1745
- t && Z.setActiveSubtitle(Y(t));
1744
+ t && X.setActiveSubtitle(J(t));
1746
1745
  }
1747
- s && (E?.abort(), E = null, K()), (a || o) && $(i.thumbnails), t || n ? Te(!(t || u)) : u && h && f(h.duration) && U(h);
1746
+ s && (E?.abort(), E = null, K()), (a || o) && Q(i.thumbnails), t || n ? we(!(t || u)) : u && h && f(h.duration) && U(h);
1748
1747
  },
1749
1748
  setThumbnails(e) {
1750
1749
  i = {
1751
1750
  ...i,
1752
1751
  thumbnails: e
1753
- }, $(e);
1752
+ }, Q(e);
1754
1753
  },
1755
1754
  initPlugins(e) {
1756
1755
  let t = [];
@@ -1772,12 +1771,12 @@ function ge(e) {
1772
1771
  };
1773
1772
  },
1774
1773
  mount(e, t) {
1775
- h && this.unmount(), m = t, we(e), g = X, document.addEventListener("fullscreenchange", g), document.addEventListener("webkitfullscreenchange", g), N = () => V(), window.addEventListener("pagehide", N), D.setup(Z), $(i.thumbnails);
1774
+ h && this.unmount(), m = t, Ce(e), g = Y, document.addEventListener("fullscreenchange", g), document.addEventListener("webkitfullscreenchange", g), N = () => V(), window.addEventListener("pagehide", N), D.setup(X), Q(i.thumbnails);
1776
1775
  let n = r.state.subtitleTracks.find((e) => e.default);
1777
- n && Z.setActiveSubtitle(n), ve(), ye(), Z.setAspectRatio(r.state.aspectRatio);
1776
+ n && X.setActiveSubtitle(n), ve(), ye(), X.setAspectRatio(r.state.aspectRatio);
1778
1777
  },
1779
1778
  unmount() {
1780
- Ce(), H(), D.teardown(), m = null, w?.abort(), w = null, T?.abort(), T = null, E?.abort(), E = null, be(), S !== null && (clearTimeout(S), S = null), g &&= (document.removeEventListener("fullscreenchange", g), document.removeEventListener("webkitfullscreenchange", g), null), N &&= (window.removeEventListener("pagehide", N), null), r.setState((e) => ({
1779
+ Se(), H(), D.teardown(), m = null, w?.abort(), w = null, T?.abort(), T = null, E?.abort(), E = null, be(), S !== null && (clearTimeout(S), S = null), g &&= (document.removeEventListener("fullscreenchange", g), document.removeEventListener("webkitfullscreenchange", g), null), N &&= (window.removeEventListener("pagehide", N), null), r.setState((e) => ({
1781
1780
  ...e,
1782
1781
  activeSubtitle: null,
1783
1782
  subtitleTracks: e.subtitleTracks.filter((e) => !e.local),
@@ -1795,7 +1794,7 @@ function ge(e) {
1795
1794
  this.unmount(), o.clear();
1796
1795
  }
1797
1796
  };
1798
- return Ee;
1797
+ return Te;
1799
1798
  }
1800
1799
  //#endregion
1801
1800
  //#region src/gesture-engine.ts
@@ -1859,14 +1858,14 @@ function X(e, t) {
1859
1858
  }
1860
1859
  //#endregion
1861
1860
  //#region src/utils.ts
1862
- function Z(e) {
1861
+ function _e(e) {
1863
1862
  if (!Number.isFinite(e) || e < 0) return "0:00";
1864
1863
  let t = Math.floor(e / 3600), n = Math.floor(e % 3600 / 60), r = Math.floor(e % 60);
1865
1864
  return t > 0 ? `${t}:${String(n).padStart(2, "0")}:${String(r).padStart(2, "0")}` : `${n}:${String(r).padStart(2, "0")}`;
1866
1865
  }
1867
1866
  //#endregion
1868
1867
  //#region src/defaults.ts
1869
- var _e = {
1868
+ var Z = {
1870
1869
  play: "Play",
1871
1870
  pause: "Pause",
1872
1871
  replay: "Replay",
@@ -1943,4 +1942,4 @@ var _e = {
1943
1942
  loop: "Loop"
1944
1943
  };
1945
1944
  //#endregion
1946
- export { S as BaseMediaEngine, T as DashMediaEngine, t as EventBus, w as HlsMediaEngine, n as HotkeyRegistry, a as I18n, ee as LocalPlaybackProgressStore, C as NativeVideoEngine, x as STORAGE_KEYS, b as Storage, c as canUseFullscreen, o as canUseMSE, s as canUseNativeHLS, l as canUsePictureInPicture, u as canUseTextTracks, X as createGestureEngine, v as createMediaSessionController, ae as createMediaStore, ge as createPlayer, te as createResolvedMediaEngine, _e as defaultPlayerLabels, D as detectSourceKind, R as fetchSubtitles, re as fetchThumbnails, Z as formatTime, z as getActiveCue, H as getInitialMediaState, d as getMediaCapabilities, ie as getThumbnailAtTime, f as isFiniteDuration, F as parseSRT, L as parseSubtitles, B as parseThumbnailVTT, N as parseTimestamp, I as parseVTT, W as selectAudio, q as selectError, U as selectMedia, oe as selectPlugins, G as selectPreferences, se as selectThumbnails, K as selectUI, O as toPlayerSource };
1945
+ export { S as BaseMediaEngine, T as DashMediaEngine, t as EventBus, w as HlsMediaEngine, n as HotkeyRegistry, a as I18n, ee as LocalPlaybackProgressStore, C as NativeVideoEngine, x as STORAGE_KEYS, b as Storage, c as canUseFullscreen, o as canUseMSE, s as canUseNativeHLS, l as canUsePictureInPicture, u as canUseTextTracks, X as createGestureEngine, v as createMediaSessionController, ae as createMediaStore, Y as createPlayer, te as createResolvedMediaEngine, Z as defaultPlayerLabels, D as detectSourceKind, R as fetchSubtitles, re as fetchThumbnails, _e as formatTime, z as getActiveCue, H as getInitialMediaState, d as getMediaCapabilities, ie as getThumbnailAtTime, f as isFiniteDuration, F as parseSRT, L as parseSubtitles, B as parseThumbnailVTT, N as parseTimestamp, I as parseVTT, W as selectAudio, ce as selectError, U as selectMedia, oe as selectPlugins, G as selectPreferences, se as selectThumbnails, K as selectUI, O as toPlayerSource };
@@ -6,11 +6,11 @@
6
6
  * Metadata alone is not enough: without `playbackState` and action
7
7
  * handlers the OS entry goes stale and its buttons are dead.
8
8
  */
9
- import type { MediaRemote } from './types';
9
+ import type { MediaRemote, MediaSessionMetadataOptions } from './types';
10
10
  type SessionPlaybackState = 'playing' | 'paused';
11
11
  export interface MediaSessionController {
12
12
  setup(remote: MediaRemote): void;
13
- syncMetadata(title: string | undefined, poster: string | undefined): void;
13
+ syncMetadata(title: string | undefined, metadata?: MediaSessionMetadataOptions, poster?: string): void;
14
14
  setPlaybackState(state: SessionPlaybackState): void;
15
15
  syncPosition(duration: number, currentTime: number, playbackRate: number, force?: boolean): void;
16
16
  readonly hasMetadata: boolean;
package/dist/types.d.ts CHANGED
@@ -12,6 +12,15 @@ import type { MediaState, PlaybackStatus, ResumeState } from './state/slices';
12
12
  import type { Storage } from './storage';
13
13
  import type { CaptionSettings, SubtitleProvider, SubtitleProviderResult, SubtitleSearchQuery, SubtitleTrack } from './subtitle-parser';
14
14
  export type { MediaState, ResumeState };
15
+ /** OS media-control metadata overrides (Media Session → MPRIS). */
16
+ export interface MediaSessionMetadataOptions {
17
+ /** Overrides the artwork sent to OS controls; falls back to `poster`. */
18
+ artwork?: string;
19
+ /** Artist line shown under the title (e.g. studio or channel name). */
20
+ artist?: string;
21
+ /** Album line; rarely meaningful for video, supported for completeness. */
22
+ album?: string;
23
+ }
15
24
  export interface PlayerOptions {
16
25
  src: string;
17
26
  /** MIME/content type hint used by source provider selection. */
@@ -20,11 +29,11 @@ export interface PlayerOptions {
20
29
  title?: string;
21
30
  poster?: string;
22
31
  /**
23
- * Artwork URL for OS media controls (Media Session → MPRIS).
24
- * Falls back to `poster` when omitted — useful for serving a scaled-down
25
- * image when full-size posters are too big.
32
+ * OS media-control overrides (Media Session → MPRIS), e.g. a scaled-down
33
+ * artwork image when full-size posters are too big, or a studio name as
34
+ * the artist line. Artwork falls back to `poster` when omitted.
26
35
  */
27
- mediaSessionArtwork?: string;
36
+ mediaSession?: MediaSessionMetadataOptions;
28
37
  subtitles?: SubtitleTrack[];
29
38
  subtitleProviders?: SubtitleProvider[];
30
39
  qualities?: string[];
@@ -202,7 +211,7 @@ export interface PlayerInstance {
202
211
  hotkeys: HotkeyRegistry;
203
212
  /** The active media engine. Null before mount and after unmount. */
204
213
  engine: MediaEngine | null;
205
- updateOptions(opts: Partial<Pick<PlayerOptions, 'src' | 'type' | 'title' | 'poster' | 'mediaSessionArtwork' | 'autoPlay' | 'subtitles' | 'subtitleProviders' | 'qualities' | 'thumbnails' | 'transformThumbnailVTT' | 'playbackProgress'>>): void;
214
+ updateOptions(opts: Partial<Pick<PlayerOptions, 'src' | 'type' | 'title' | 'poster' | 'mediaSession' | 'autoPlay' | 'subtitles' | 'subtitleProviders' | 'qualities' | 'thumbnails' | 'transformThumbnailVTT' | 'playbackProgress'>>): void;
206
215
  setThumbnails(url?: string): void;
207
216
  initPlugins(plugins: PlayerPlugin[]): () => void;
208
217
  mount(videoEl: HTMLVideoElement, containerEl: HTMLDivElement): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vplayer/core",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",