@video-lab/vue 1.0.1 → 3.0.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.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("vue"),t=require("@video-lab/protocol"),n=require("@video-lab/player-ui"),r=require("@video-lab/player-core");function i(t,r){return(0,n.defineSentinelOverlays)(),(0,e.h)(t,r)}function a(e,t){return e[t]??t}function o(e,t,n){let r=`error.${t}`,i=a(e,r);return i===r?n:i}function s(i,a,o){let s=(0,e.shallowRef)(null),u=(0,e.shallowRef)(n.INITIAL_OVERLAY),d=(0,e.ref)(!1);function f(e){let r=(0,t.toErrorEvent)(e);u.value=(0,n.reduceOverlay)(u.value,r),l(r,o)}function p(e){let n=s.value;if(n){if(n.destroyed){f({playerError:(0,t.makePlayerError)(`E_PLAYER_DESTROYED`,t.PLAYER_DESTROYED_MESSAGE)});return}e(n)}}function m(){let e=i.value;if(e){u.value=n.INITIAL_OVERLAY;try{s.value=(0,r.createPlayer)({el:e,config:c(a),onEvent:e=>{u.value=(0,n.reduceOverlay)(u.value,e),l(e,o)}}),d.value=!0}catch(e){f(e)}}}function h(){s.value?.destroy(),s.value=null,d.value=!1}(0,e.onMounted)(m),(0,e.onBeforeUnmount)(h),(0,e.watch)(()=>JSON.stringify(a.source),()=>{u.value=(0,n.resetOverlayForNewSource)(u.value),p(e=>{e.load(a.source).catch(f)})}),(0,e.watch)(()=>a.muted,e=>{e!==void 0&&p(t=>t.setMuted(e))}),(0,e.watch)(()=>a.locale,e=>{e!==void 0&&p(t=>t.setLocale(e))},{deep:!0});function g(){h(),m()}function _(){u.value={...u.value,pauseImageVisible:!1,pauseImageDismissed:!0}}return{handle:s,overlay:u,isMounted:d,handleRetry:g,dismissPauseImage:_}}function c(e){let t={source:e.source};return e.preset!==void 0&&(t.preset=e.preset),e.autoplay!==void 0&&(t.autoplay=e.autoplay),e.muted!==void 0&&(t.muted=e.muted),e.loop!==void 0&&(t.loop=e.loop),e.playsinline!==void 0&&(t.playsinline=e.playsinline),e.playbackRate!==void 0&&(t.playbackRate=e.playbackRate),e.volume!==void 0&&(t.volume=e.volume),e.startTime!==void 0&&(t.startTime=e.startTime),e.preload!==void 0&&(t.preload=e.preload),e.controls!==void 0&&(t.controls=e.controls),e.interactive!==void 0&&(t.interactive=e.interactive),e.poster!==void 0&&(t.poster=e.poster),e.pauseImage!==void 0&&(t.pauseImage=e.pauseImage),e.locale!==void 0&&(t.locale=e.locale),e.danmaku!==void 0&&(t.danmaku=e.danmaku),e.debug!==void 0&&(t.debug=e.debug),t}function l(e,t){try{t(`playerEvent`,e)}catch{}switch(e.event){case`ready`:t(`ready`,e.payload);break;case`play`:t(`play`);break;case`pause`:t(`pause`);break;case`ended`:t(`ended`);break;case`timeupdate`:t(`timeUpdate`,e.payload);break;case`volumechange`:t(`volumeChange`,e.payload);break;case`seeking`:t(`seeking`,e.payload);break;case`seeked`:t(`seeked`,e.payload);break;case`waiting`:t(`waiting`);break;case`playing`:t(`playing`);break;case`qualitychange`:t(`qualityChange`,e.payload);break;case`subtitlechange`:t(`subtitleChange`,e.payload);break;case`error`:t(`error`,e.payload);break;case`autoplayblocked`:t(`autoplayBlocked`);break;case`reconnectstart`:t(`reconnectStart`,{attempt:e.payload.attempt,maxAttempts:e.payload.maxAttempts});break;case`reconnectsuccess`:t(`reconnectSuccess`);break;case`reconnectfailed`:t(`reconnectFailed`);break;case`compatwarning`:t(`compatWarning`,e.payload);break;case`stalled`:t(`stalled`,e.payload);break;case`playablechange`:t(`playableChange`,e.payload);break;case`bufferhealth`:t(`bufferHealth`,e.payload);break;case`contextchange`:t(`contextChange`,e.payload);break;case`sourceroute`:t(`sourceRoute`,e.payload);break;case`firstframe`:t(`firstFrame`,e.payload);break;case`framefreeze`:t(`frameFreeze`,e.payload);break;case`useraction`:t(`userAction`,e.payload);break;case`kernelhealth`:t(`kernelHealth`,e.payload);break;case`audiohealth`:t(`audioHealth`,e.payload);break;case`recovery`:break;default:break}}var u={ref:`container`,class:`sentinel-video__player`,style:{width:`100%`,height:`100%`}},d=(0,e.defineComponent)({__name:`VideoPlayer`,props:{source:{},autoplay:{type:Boolean,default:void 0},muted:{type:Boolean,default:void 0},loop:{type:Boolean,default:void 0},controls:{type:Boolean,default:void 0},interactive:{type:Boolean,default:void 0},playsinline:{type:Boolean,default:void 0},playbackRate:{},volume:{},startTime:{},preload:{},poster:{},pauseImage:{},preset:{},locale:{},danmaku:{},debug:{type:Boolean,default:void 0}},emits:`playerEvent.ready.play.pause.ended.timeUpdate.volumeChange.seeking.seeked.waiting.playing.qualityChange.subtitleChange.error.autoplayBlocked.reconnectStart.reconnectSuccess.reconnectFailed.compatWarning.stalled.playableChange.kernelHealth.audioHealth.bufferHealth.contextChange.sourceRoute.firstFrame.frameFreeze.userAction`.split(`.`),setup(n,{expose:r,emit:c}){let l=n,d=c,{handle:f,overlay:p,isMounted:m,handleRetry:h,dismissPauseImage:g}=s((0,e.useTemplateRef)(`container`),l,d),_=(0,e.computed)(()=>(0,t.resolveLocaleMessages)(l.locale).messages),v=(0,e.computed)(()=>typeof l.poster==`string`?l.poster:l.poster?.url),y=(0,e.computed)(()=>typeof l.pauseImage==`string`?l.pauseImage:l.pauseImage?.url),b=()=>[v.value?i(`sentinel-poster`,{visible:p.value.posterVisible,poster:l.poster}):null,y.value?i(`sentinel-pause`,{visible:p.value.pauseImageVisible,pauseImage:l.pauseImage,"close-label":a(_.value,`close`),"onSentinel-close":g}):null,i(`sentinel-loading`,{visible:p.value.loadingVisible,text:a(_.value,`loading`)}),p.value.error?i(`sentinel-error`,{visible:!0,code:p.value.error.code,message:o(_.value,p.value.error.code,p.value.error.message),retryable:p.value.error.retryable,"retry-label":a(_.value,`retry`),"onSentinel-retry":h}):null];return r({play:()=>f.value?.play()??Promise.resolve(),pause:()=>f.value?.pause(),seek:e=>f.value?.seek(e),setMuted:e=>f.value?.setMuted(e),setVolume:e=>f.value?.setVolume(e),setPlaybackRate:e=>f.value?.setPlaybackRate(e),enterFullscreen:()=>f.value?.enterFullscreen()??Promise.resolve(),exitFullscreen:()=>f.value?.exitFullscreen()??Promise.resolve(),setQuality:e=>f.value?.setQuality(e),setSubtitle:e=>f.value?.setSubtitle(e),setLocale:e=>f.value?.setLocale(e),pushDanmaku:e=>f.value?.pushDanmaku(e),setDanmakuEnabled:e=>f.value?.setDanmakuEnabled(e),clearDanmaku:()=>f.value?.clearDanmaku(),reconnect:e=>f.value?.reconnect(e),destroy:()=>f.value?.destroy(),getCurrentTime:()=>f.value?.getCurrentTime()??0,getDuration:()=>f.value?.getDuration()??0,getPlaybackContext:()=>f.value?.getPlaybackContext()??null,getPlayerHandle:()=>f.value}),(t,n)=>((0,e.openBlock)(),(0,e.createElementBlock)(`div`,{class:`sentinel-video`,style:(0,e.normalizeStyle)({position:`relative`,width:`100%`,height:`100%`,pointerEvents:l.interactive===!1?`none`:void 0})},[(0,e.createElementVNode)(`div`,u,null,512),(0,e.createVNode)(b),(0,e.unref)(m)?(0,e.createCommentVNode)(``,!0):(0,e.renderSlot)(t.$slots,`ssr-placeholder`,{key:0})],4))}});exports.VideoPlayer=d;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("vue"),t=require("@video-lab/protocol"),n=require("@video-lab/player-ui"),r=require("@video-lab/player-core");function i(t,r){return(0,n.defineSentinelOverlays)(),(0,e.h)(t,r)}function a(e,t){return e[t]??t}function o(e,t,n){let r=`error.${t}`,i=a(e,r);return i===r?n:i}function s(i,a,o){let s=(0,e.shallowRef)(null),u=(0,e.shallowRef)(n.INITIAL_OVERLAY),d=(0,e.ref)(!1);function f(e){let r=(0,t.toErrorEvent)(e);u.value=s.value?(0,n.reduceOverlay)(u.value,r):{...u.value,posterVisible:!1,loadingVisible:!1,error:r.payload,action:`replace-source`},l(r,o)}function p(e){let n=s.value;if(n){if(n.destroyed){f({playerError:(0,t.makePlayerError)(`E_PLAYER_DESTROYED`,t.PLAYER_DESTROYED_MESSAGE)});return}e(n)}}function m(){let e=i.value;if(e){u.value=n.INITIAL_OVERLAY;try{s.value=(0,r.createPlayer)({el:e,config:c(a),pageFullscreen:a.pageFullscreen,onEvent:e=>{u.value=(0,n.reduceOverlay)(u.value,e),l(e,o)},onDeliveredEvent:e=>{try{o(`deliveredPlayerEvent`,e)}catch{}}}),d.value=!0}catch(e){f(e)}}}function h(){s.value?.destroy(),s.value=null,d.value=!1}(0,e.onMounted)(m),(0,e.onBeforeUnmount)(h),(0,e.watch)(()=>JSON.stringify(a.source),()=>{u.value=(0,n.resetOverlayForNewSource)(u.value),p(e=>{e.load(a.source).catch(f)})}),(0,e.watch)(()=>a.muted,e=>{e!==void 0&&p(t=>t.setMuted(e))}),(0,e.watch)(()=>a.locale,e=>{e!==void 0&&p(t=>t.setLocale(e))},{deep:!0});function g(){let e=s.value;e&&(u.value.action===`play`?e.play():e.retry()).catch(()=>{})}function _(){u.value={...u.value,pauseImageVisible:!1,pauseImageDismissed:!0}}return{handle:s,overlay:u,isMounted:d,handleRetry:g,dismissPauseImage:_}}function c(e){let t={source:e.source};return e.preset!==void 0&&(t.preset=e.preset),e.autoplay!==void 0&&(t.autoplay=e.autoplay),e.muted!==void 0&&(t.muted=e.muted),e.loop!==void 0&&(t.loop=e.loop),e.playsinline!==void 0&&(t.playsinline=e.playsinline),e.playbackRate!==void 0&&(t.playbackRate=e.playbackRate),e.volume!==void 0&&(t.volume=e.volume),e.startTime!==void 0&&(t.startTime=e.startTime),e.preload!==void 0&&(t.preload=e.preload),e.controls!==void 0&&(t.controls=e.controls),e.showErrorOverlay!==void 0&&(t.showErrorOverlay=e.showErrorOverlay),e.showLoadingOverlay!==void 0&&(t.showLoadingOverlay=e.showLoadingOverlay),e.controlVisibility!==void 0&&(t.controlVisibility=e.controlVisibility),e.interactive!==void 0&&(t.interactive=e.interactive),e.poster!==void 0&&(t.poster=e.poster),e.pauseImage!==void 0&&(t.pauseImage=e.pauseImage),e.locale!==void 0&&(t.locale=e.locale),e.danmaku!==void 0&&(t.danmaku=e.danmaku),e.debug!==void 0&&(t.debug=e.debug),t}function l(e,t){try{t(`playerEvent`,e)}catch{}switch(e.event){case`ready`:t(`ready`,e.payload);break;case`play`:t(`play`);break;case`pause`:t(`pause`);break;case`ended`:t(`ended`);break;case`timeupdate`:t(`timeUpdate`,e.payload);break;case`volumechange`:t(`volumeChange`,e.payload);break;case`seeking`:t(`seeking`,e.payload);break;case`seeked`:t(`seeked`,e.payload);break;case`waiting`:t(`waiting`);break;case`playing`:t(`playing`);break;case`qualitychange`:t(`qualityChange`,e.payload);break;case`subtitlechange`:t(`subtitleChange`,e.payload);break;case`error`:t(`error`,e.payload);break;case`autoplayblocked`:t(`autoplayBlocked`);break;case`compatwarning`:t(`compatWarning`,e.payload);break;case`stalled`:t(`stalled`,e.payload);break;case`playablechange`:t(`playableChange`,e.payload);break;case`bufferhealth`:t(`bufferHealth`,e.payload);break;case`contextchange`:t(`contextChange`,e.payload);break;case`sourceroute`:t(`sourceRoute`,e.payload);break;case`firstframe`:t(`firstFrame`,e.payload);break;case`framefreeze`:t(`frameFreeze`,e.payload);break;case`pagefullscreenchange`:t(`pageFullscreenChange`,e.payload);break;case`useraction`:t(`userAction`,e.payload);break;case`kernelhealth`:t(`kernelHealth`,e.payload);break;case`audiohealth`:t(`audioHealth`,e.payload);break;case`recovery`:break;default:break}}var u=(0,e.defineComponent)({__name:`VideoPlayer`,props:{pageFullscreen:{},source:{},autoplay:{type:Boolean,default:void 0},muted:{type:Boolean,default:void 0},loop:{type:Boolean,default:void 0},controls:{type:Boolean,default:void 0},showErrorOverlay:{type:Boolean,default:void 0},showLoadingOverlay:{type:Boolean,default:void 0},controlVisibility:{},interactive:{type:Boolean,default:void 0},playsinline:{type:Boolean,default:void 0},playbackRate:{},volume:{},startTime:{},preload:{},poster:{},pauseImage:{},preset:{},locale:{},danmaku:{},debug:{type:Boolean,default:void 0}},emits:`playerEvent.deliveredPlayerEvent.ready.play.pause.ended.timeUpdate.volumeChange.seeking.seeked.waiting.playing.qualityChange.subtitleChange.error.autoplayBlocked.compatWarning.stalled.playableChange.kernelHealth.audioHealth.bufferHealth.contextChange.sourceRoute.firstFrame.frameFreeze.pageFullscreenChange.userAction`.split(`.`),setup(n,{expose:r,emit:c}){let l=n,u=c,d=l.showErrorOverlay!==!1,f=l.showLoadingOverlay!==!1,p=(0,e.shallowRef)(null),{handle:m,overlay:h,isMounted:g,handleRetry:_,dismissPauseImage:v}=s(p,l,u),y=(0,e.computed)(()=>(0,t.resolveLocaleMessages)(l.locale).messages),b=(0,e.computed)(()=>typeof l.poster==`string`?l.poster:l.poster?.url),x=(0,e.computed)(()=>typeof l.pauseImage==`string`?l.pauseImage:l.pauseImage?.url),S=()=>[b.value?i(`sentinel-poster`,{visible:h.value.posterVisible,poster:l.poster}):null,x.value?i(`sentinel-pause`,{visible:h.value.pauseImageVisible,pauseImage:l.pauseImage,"close-label":a(y.value,`close`),"onSentinel-close":v}):null,i(`sentinel-loading`,{visible:f&&h.value.loadingVisible,text:a(y.value,`loading`)}),d&&h.value.error?i(`sentinel-error`,{visible:!0,code:h.value.error.code,message:o(y.value,h.value.error.code,h.value.error.message),retryable:h.value.action===`retry`||h.value.action===`play`,"retry-label":a(y.value,h.value.action===`play`?`play`:`retry`),"onSentinel-retry":_}):null];return r({play:()=>m.value?.play()??Promise.resolve(),pause:()=>m.value?.pause(),seek:e=>m.value?.seek(e),setMuted:e=>m.value?.setMuted(e),setVolume:e=>m.value?.setVolume(e),setPlaybackRate:e=>m.value?.setPlaybackRate(e),setPageFullscreen:e=>m.value?.setPageFullscreen(e)??Promise.reject(Error(`播放器未就绪`)),enterFullscreen:()=>m.value?.enterFullscreen()??Promise.resolve(),exitFullscreen:()=>m.value?.exitFullscreen()??Promise.resolve(),setQuality:e=>m.value?.setQuality(e),setSubtitle:e=>m.value?.setSubtitle(e),setLocale:e=>m.value?.setLocale(e),pushDanmaku:e=>m.value?.pushDanmaku(e),setDanmakuEnabled:e=>m.value?.setDanmakuEnabled(e),clearDanmaku:()=>m.value?.clearDanmaku(),retry:()=>m.value?.retry()??Promise.resolve(),destroy:()=>m.value?.destroy(),getCurrentTime:()=>m.value?.getCurrentTime()??0,getDuration:()=>m.value?.getDuration()??0,getPlaybackContext:()=>m.value?.getPlaybackContext()??null,getPlayerHandle:()=>m.value}),(t,n)=>((0,e.openBlock)(),(0,e.createElementBlock)(`div`,{class:`sentinel-video`,style:(0,e.normalizeStyle)({position:`relative`,width:`100%`,height:`100%`,pointerEvents:l.interactive===!1?`none`:void 0})},[(0,e.createElementVNode)(`div`,{ref_key:`containerRef`,ref:p,class:`sentinel-video__player`,style:{width:`100%`,height:`100%`}},null,512),(0,e.createVNode)(S),(0,e.unref)(g)?(0,e.createCommentVNode)(``,!0):(0,e.renderSlot)(t.$slots,`ssr-placeholder`,{key:0})],4))}});exports.VideoPlayer=u;
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@
8
8
  * 只做技术,不含团队品牌 UI(ADR-021)。**开门的决策见 ADR-052**
9
9
  *(取代 ADR-002「Vue 只做 iframe 不做 inline」—— 那条的唯一论据在 #120 之后已不成立)。
10
10
  */
11
+ export type { PageFullscreenAdapter, PageFullscreenState } from '@video-lab/protocol';
11
12
  export type { DanmakuConfig, DanmakuItem, MediaSource, PlayerError, PlayerHandle, QualityLevel, SubtitleTrackInfo, VideoPlayerEmits, VideoPlayerExpose, VideoPlayerProps, } from './types';
12
13
  export { default as VideoPlayer } from './VideoPlayer.vue';
13
14
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,31 +1,37 @@
1
- import { computed as e, createCommentVNode as t, createElementBlock as n, createElementVNode as r, createVNode as i, defineComponent as a, h as o, normalizeStyle as s, onBeforeUnmount as c, onMounted as l, openBlock as u, ref as d, renderSlot as f, shallowRef as p, unref as m, useTemplateRef as h, watch as g } from "vue";
2
- import { PLAYER_DESTROYED_MESSAGE as _, makePlayerError as v, resolveLocaleMessages as y, toErrorEvent as b } from "@video-lab/protocol";
3
- import { INITIAL_OVERLAY as x, defineSentinelOverlays as S, reduceOverlay as C, resetOverlayForNewSource as w } from "@video-lab/player-ui";
4
- import { createPlayer as T } from "@video-lab/player-core";
1
+ import { computed as e, createCommentVNode as t, createElementBlock as n, createElementVNode as r, createVNode as i, defineComponent as a, h as o, normalizeStyle as s, onBeforeUnmount as c, onMounted as l, openBlock as u, ref as d, renderSlot as f, shallowRef as p, unref as m, watch as h } from "vue";
2
+ import { PLAYER_DESTROYED_MESSAGE as g, makePlayerError as _, resolveLocaleMessages as v, toErrorEvent as y } from "@video-lab/protocol";
3
+ import { INITIAL_OVERLAY as b, defineSentinelOverlays as x, reduceOverlay as S, resetOverlayForNewSource as C } from "@video-lab/player-ui";
4
+ import { createPlayer as w } from "@video-lab/player-core";
5
5
  //#region src/overlay-elements.ts
6
- function E(e, t) {
7
- return S(), o(e, t);
6
+ function T(e, t) {
7
+ return x(), o(e, t);
8
8
  }
9
- function D(e, t) {
9
+ function E(e, t) {
10
10
  return e[t] ?? t;
11
11
  }
12
- function O(e, t, n) {
13
- let r = `error.${t}`, i = D(e, r);
12
+ function D(e, t, n) {
13
+ let r = `error.${t}`, i = E(e, r);
14
14
  return i === r ? n : i;
15
15
  }
16
16
  //#endregion
17
17
  //#region src/use-player.ts
18
- function k(e, t, n) {
19
- let r = p(null), i = p(x), a = d(!1);
18
+ function O(e, t, n) {
19
+ let r = p(null), i = p(b), a = d(!1);
20
20
  function o(e) {
21
- let t = b(e);
22
- i.value = C(i.value, t), j(t, n);
21
+ let t = y(e);
22
+ i.value = r.value ? S(i.value, t) : {
23
+ ...i.value,
24
+ posterVisible: !1,
25
+ loadingVisible: !1,
26
+ error: t.payload,
27
+ action: "replace-source"
28
+ }, A(t, n);
23
29
  }
24
30
  function s(e) {
25
31
  let t = r.value;
26
32
  if (t) {
27
33
  if (t.destroyed) {
28
- o({ playerError: v("E_PLAYER_DESTROYED", _) });
34
+ o({ playerError: _("E_PLAYER_DESTROYED", g) });
29
35
  return;
30
36
  }
31
37
  e(t);
@@ -34,13 +40,19 @@ function k(e, t, n) {
34
40
  function u() {
35
41
  let s = e.value;
36
42
  if (s) {
37
- i.value = x;
43
+ i.value = b;
38
44
  try {
39
- r.value = T({
45
+ r.value = w({
40
46
  el: s,
41
- config: A(t),
47
+ config: k(t),
48
+ pageFullscreen: t.pageFullscreen,
42
49
  onEvent: (e) => {
43
- i.value = C(i.value, e), j(e, n);
50
+ i.value = S(i.value, e), A(e, n);
51
+ },
52
+ onDeliveredEvent: (e) => {
53
+ try {
54
+ n("deliveredPlayerEvent", e);
55
+ } catch {}
44
56
  }
45
57
  }), a.value = !0;
46
58
  } catch (e) {
@@ -51,19 +63,20 @@ function k(e, t, n) {
51
63
  function f() {
52
64
  r.value?.destroy(), r.value = null, a.value = !1;
53
65
  }
54
- l(u), c(f), g(() => JSON.stringify(t.source), () => {
55
- i.value = w(i.value), s((e) => {
66
+ l(u), c(f), h(() => JSON.stringify(t.source), () => {
67
+ i.value = C(i.value), s((e) => {
56
68
  e.load(t.source).catch(o);
57
69
  });
58
- }), g(() => t.muted, (e) => {
70
+ }), h(() => t.muted, (e) => {
59
71
  e !== void 0 && s((t) => t.setMuted(e));
60
- }), g(() => t.locale, (e) => {
72
+ }), h(() => t.locale, (e) => {
61
73
  e !== void 0 && s((t) => t.setLocale(e));
62
74
  }, { deep: !0 });
63
75
  function m() {
64
- f(), u();
76
+ let e = r.value;
77
+ e && (i.value.action === "play" ? e.play() : e.retry()).catch(() => {});
65
78
  }
66
- function h() {
79
+ function v() {
67
80
  i.value = {
68
81
  ...i.value,
69
82
  pauseImageVisible: !1,
@@ -75,14 +88,14 @@ function k(e, t, n) {
75
88
  overlay: i,
76
89
  isMounted: a,
77
90
  handleRetry: m,
78
- dismissPauseImage: h
91
+ dismissPauseImage: v
79
92
  };
80
93
  }
81
- function A(e) {
94
+ function k(e) {
82
95
  let t = { source: e.source };
83
- return e.preset !== void 0 && (t.preset = e.preset), e.autoplay !== void 0 && (t.autoplay = e.autoplay), e.muted !== void 0 && (t.muted = e.muted), e.loop !== void 0 && (t.loop = e.loop), e.playsinline !== void 0 && (t.playsinline = e.playsinline), e.playbackRate !== void 0 && (t.playbackRate = e.playbackRate), e.volume !== void 0 && (t.volume = e.volume), e.startTime !== void 0 && (t.startTime = e.startTime), e.preload !== void 0 && (t.preload = e.preload), e.controls !== void 0 && (t.controls = e.controls), e.interactive !== void 0 && (t.interactive = e.interactive), e.poster !== void 0 && (t.poster = e.poster), e.pauseImage !== void 0 && (t.pauseImage = e.pauseImage), e.locale !== void 0 && (t.locale = e.locale), e.danmaku !== void 0 && (t.danmaku = e.danmaku), e.debug !== void 0 && (t.debug = e.debug), t;
96
+ return e.preset !== void 0 && (t.preset = e.preset), e.autoplay !== void 0 && (t.autoplay = e.autoplay), e.muted !== void 0 && (t.muted = e.muted), e.loop !== void 0 && (t.loop = e.loop), e.playsinline !== void 0 && (t.playsinline = e.playsinline), e.playbackRate !== void 0 && (t.playbackRate = e.playbackRate), e.volume !== void 0 && (t.volume = e.volume), e.startTime !== void 0 && (t.startTime = e.startTime), e.preload !== void 0 && (t.preload = e.preload), e.controls !== void 0 && (t.controls = e.controls), e.showErrorOverlay !== void 0 && (t.showErrorOverlay = e.showErrorOverlay), e.showLoadingOverlay !== void 0 && (t.showLoadingOverlay = e.showLoadingOverlay), e.controlVisibility !== void 0 && (t.controlVisibility = e.controlVisibility), e.interactive !== void 0 && (t.interactive = e.interactive), e.poster !== void 0 && (t.poster = e.poster), e.pauseImage !== void 0 && (t.pauseImage = e.pauseImage), e.locale !== void 0 && (t.locale = e.locale), e.danmaku !== void 0 && (t.danmaku = e.danmaku), e.debug !== void 0 && (t.debug = e.debug), t;
84
97
  }
85
- function j(e, t) {
98
+ function A(e, t) {
86
99
  try {
87
100
  t("playerEvent", e);
88
101
  } catch {}
@@ -129,18 +142,6 @@ function j(e, t) {
129
142
  case "autoplayblocked":
130
143
  t("autoplayBlocked");
131
144
  break;
132
- case "reconnectstart":
133
- t("reconnectStart", {
134
- attempt: e.payload.attempt,
135
- maxAttempts: e.payload.maxAttempts
136
- });
137
- break;
138
- case "reconnectsuccess":
139
- t("reconnectSuccess");
140
- break;
141
- case "reconnectfailed":
142
- t("reconnectFailed");
143
- break;
144
145
  case "compatwarning":
145
146
  t("compatWarning", e.payload);
146
147
  break;
@@ -165,6 +166,9 @@ function j(e, t) {
165
166
  case "framefreeze":
166
167
  t("frameFreeze", e.payload);
167
168
  break;
169
+ case "pagefullscreenchange":
170
+ t("pageFullscreenChange", e.payload);
171
+ break;
168
172
  case "useraction":
169
173
  t("userAction", e.payload);
170
174
  break;
@@ -179,17 +183,11 @@ function j(e, t) {
179
183
  }
180
184
  }
181
185
  //#endregion
182
- //#region src/VideoPlayer.vue?vue&type=script&setup=true&lang.ts
183
- var M = {
184
- ref: "container",
185
- class: "sentinel-video__player",
186
- style: {
187
- width: "100%",
188
- height: "100%"
189
- }
190
- }, N = /* @__PURE__ */ a({
186
+ //#region src/VideoPlayer.vue
187
+ var j = /* @__PURE__ */ a({
191
188
  __name: "VideoPlayer",
192
189
  props: {
190
+ pageFullscreen: {},
193
191
  source: {},
194
192
  autoplay: {
195
193
  type: Boolean,
@@ -207,6 +205,15 @@ var M = {
207
205
  type: Boolean,
208
206
  default: void 0
209
207
  },
208
+ showErrorOverlay: {
209
+ type: Boolean,
210
+ default: void 0
211
+ },
212
+ showLoadingOverlay: {
213
+ type: Boolean,
214
+ default: void 0
215
+ },
216
+ controlVisibility: {},
210
217
  interactive: {
211
218
  type: Boolean,
212
219
  default: void 0
@@ -229,53 +236,54 @@ var M = {
229
236
  default: void 0
230
237
  }
231
238
  },
232
- emits: /* @__PURE__ */ "playerEvent.ready.play.pause.ended.timeUpdate.volumeChange.seeking.seeked.waiting.playing.qualityChange.subtitleChange.error.autoplayBlocked.reconnectStart.reconnectSuccess.reconnectFailed.compatWarning.stalled.playableChange.kernelHealth.audioHealth.bufferHealth.contextChange.sourceRoute.firstFrame.frameFreeze.userAction".split("."),
239
+ emits: /* @__PURE__ */ "playerEvent.deliveredPlayerEvent.ready.play.pause.ended.timeUpdate.volumeChange.seeking.seeked.waiting.playing.qualityChange.subtitleChange.error.autoplayBlocked.compatWarning.stalled.playableChange.kernelHealth.audioHealth.bufferHealth.contextChange.sourceRoute.firstFrame.frameFreeze.pageFullscreenChange.userAction".split("."),
233
240
  setup(a, { expose: o, emit: c }) {
234
- let l = a, d = c, { handle: p, overlay: g, isMounted: _, handleRetry: v, dismissPauseImage: b } = k(h("container"), l, d), x = e(() => y(l.locale).messages), S = e(() => typeof l.poster == "string" ? l.poster : l.poster?.url), C = e(() => typeof l.pauseImage == "string" ? l.pauseImage : l.pauseImage?.url), w = () => [
235
- S.value ? E("sentinel-poster", {
236
- visible: g.value.posterVisible,
241
+ let l = a, d = c, h = l.showErrorOverlay !== !1, g = l.showLoadingOverlay !== !1, _ = p(null), { handle: y, overlay: b, isMounted: x, handleRetry: S, dismissPauseImage: C } = O(_, l, d), w = e(() => v(l.locale).messages), k = e(() => typeof l.poster == "string" ? l.poster : l.poster?.url), A = e(() => typeof l.pauseImage == "string" ? l.pauseImage : l.pauseImage?.url), j = () => [
242
+ k.value ? T("sentinel-poster", {
243
+ visible: b.value.posterVisible,
237
244
  poster: l.poster
238
245
  }) : null,
239
- C.value ? E("sentinel-pause", {
240
- visible: g.value.pauseImageVisible,
246
+ A.value ? T("sentinel-pause", {
247
+ visible: b.value.pauseImageVisible,
241
248
  pauseImage: l.pauseImage,
242
- "close-label": D(x.value, "close"),
243
- "onSentinel-close": b
249
+ "close-label": E(w.value, "close"),
250
+ "onSentinel-close": C
244
251
  }) : null,
245
- E("sentinel-loading", {
246
- visible: g.value.loadingVisible,
247
- text: D(x.value, "loading")
252
+ T("sentinel-loading", {
253
+ visible: g && b.value.loadingVisible,
254
+ text: E(w.value, "loading")
248
255
  }),
249
- g.value.error ? E("sentinel-error", {
256
+ h && b.value.error ? T("sentinel-error", {
250
257
  visible: !0,
251
- code: g.value.error.code,
252
- message: O(x.value, g.value.error.code, g.value.error.message),
253
- retryable: g.value.error.retryable,
254
- "retry-label": D(x.value, "retry"),
255
- "onSentinel-retry": v
258
+ code: b.value.error.code,
259
+ message: D(w.value, b.value.error.code, b.value.error.message),
260
+ retryable: b.value.action === "retry" || b.value.action === "play",
261
+ "retry-label": E(w.value, b.value.action === "play" ? "play" : "retry"),
262
+ "onSentinel-retry": S
256
263
  }) : null
257
264
  ];
258
265
  return o({
259
- play: () => p.value?.play() ?? Promise.resolve(),
260
- pause: () => p.value?.pause(),
261
- seek: (e) => p.value?.seek(e),
262
- setMuted: (e) => p.value?.setMuted(e),
263
- setVolume: (e) => p.value?.setVolume(e),
264
- setPlaybackRate: (e) => p.value?.setPlaybackRate(e),
265
- enterFullscreen: () => p.value?.enterFullscreen() ?? Promise.resolve(),
266
- exitFullscreen: () => p.value?.exitFullscreen() ?? Promise.resolve(),
267
- setQuality: (e) => p.value?.setQuality(e),
268
- setSubtitle: (e) => p.value?.setSubtitle(e),
269
- setLocale: (e) => p.value?.setLocale(e),
270
- pushDanmaku: (e) => p.value?.pushDanmaku(e),
271
- setDanmakuEnabled: (e) => p.value?.setDanmakuEnabled(e),
272
- clearDanmaku: () => p.value?.clearDanmaku(),
273
- reconnect: (e) => p.value?.reconnect(e),
274
- destroy: () => p.value?.destroy(),
275
- getCurrentTime: () => p.value?.getCurrentTime() ?? 0,
276
- getDuration: () => p.value?.getDuration() ?? 0,
277
- getPlaybackContext: () => p.value?.getPlaybackContext() ?? null,
278
- getPlayerHandle: () => p.value
266
+ play: () => y.value?.play() ?? Promise.resolve(),
267
+ pause: () => y.value?.pause(),
268
+ seek: (e) => y.value?.seek(e),
269
+ setMuted: (e) => y.value?.setMuted(e),
270
+ setVolume: (e) => y.value?.setVolume(e),
271
+ setPlaybackRate: (e) => y.value?.setPlaybackRate(e),
272
+ setPageFullscreen: (e) => y.value?.setPageFullscreen(e) ?? Promise.reject(/* @__PURE__ */ Error("播放器未就绪")),
273
+ enterFullscreen: () => y.value?.enterFullscreen() ?? Promise.resolve(),
274
+ exitFullscreen: () => y.value?.exitFullscreen() ?? Promise.resolve(),
275
+ setQuality: (e) => y.value?.setQuality(e),
276
+ setSubtitle: (e) => y.value?.setSubtitle(e),
277
+ setLocale: (e) => y.value?.setLocale(e),
278
+ pushDanmaku: (e) => y.value?.pushDanmaku(e),
279
+ setDanmakuEnabled: (e) => y.value?.setDanmakuEnabled(e),
280
+ clearDanmaku: () => y.value?.clearDanmaku(),
281
+ retry: () => y.value?.retry() ?? Promise.resolve(),
282
+ destroy: () => y.value?.destroy(),
283
+ getCurrentTime: () => y.value?.getCurrentTime() ?? 0,
284
+ getDuration: () => y.value?.getDuration() ?? 0,
285
+ getPlaybackContext: () => y.value?.getPlaybackContext() ?? null,
286
+ getPlayerHandle: () => y.value
279
287
  }), (e, a) => (u(), n("div", {
280
288
  class: "sentinel-video",
281
289
  style: s({
@@ -285,11 +293,19 @@ var M = {
285
293
  pointerEvents: l.interactive === !1 ? "none" : void 0
286
294
  })
287
295
  }, [
288
- r("div", M, null, 512),
289
- i(w),
290
- m(_) ? t("", !0) : f(e.$slots, "ssr-placeholder", { key: 0 })
296
+ r("div", {
297
+ ref_key: "containerRef",
298
+ ref: _,
299
+ class: "sentinel-video__player",
300
+ style: {
301
+ width: "100%",
302
+ height: "100%"
303
+ }
304
+ }, null, 512),
305
+ i(j),
306
+ m(x) ? t("", !0) : f(e.$slots, "ssr-placeholder", { key: 0 })
291
307
  ], 4));
292
308
  }
293
309
  });
294
310
  //#endregion
295
- export { N as VideoPlayer };
311
+ export { j as VideoPlayer };
package/dist/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { PlayerCoreHandle } from '@video-lab/player-core';
2
- import { AudioHealthPayload, BufferHealthPayload, DanmakuConfig, DanmakuItem, FirstFramePayload, FrameFreezePayload, KernelHealthPayload, LocaleConfig, MediaSource, PauseImageConfig, PlayableReason, PlaybackContext, PlaybackContextPayload, PlayerError, PlayerEvent, PosterConfig, PresetName, QualityLevel, SourceRouteEventPayload, SubtitleTrackInfo, UserActionPayload } from '@video-lab/protocol';
2
+ import { AudioHealthPayload, BufferHealthPayload, ControlVisibilityConfig, DanmakuConfig, DanmakuItem, DeliveredPlayerEvent, FirstFramePayload, FrameFreezePayload, KernelHealthPayload, LocaleConfig, MediaSource, PageFullscreenAdapter, PageFullscreenState, PauseImageConfig, PlaybackContext, PlaybackContextPayload, PlayerError, PlayerEvent, PosterConfig, PresetName, QualityLevel, SourceRouteEventPayload, SubtitleTrackInfo, UserActionPayload } from '@video-lab/protocol';
3
3
  /**
4
4
  * 消费方拿到的底层句柄(逃生舱)。
5
5
  *
@@ -23,12 +23,20 @@ export type { DanmakuConfig, DanmakuItem, MediaSource, PlayerError, QualityLevel
23
23
  * 声明成 props 反而会把它们从 fallthrough 里摘出来,要自己再拼一遍。
24
24
  */
25
25
  export interface VideoPlayerProps {
26
+ /** 挂载期间保持稳定的宿主网页全屏布局适配器。 */
27
+ pageFullscreen?: PageFullscreenAdapter;
26
28
  /** 视频源。字符串按 URL 处理,对象可带 type / live / hls 等 */
27
29
  source: MediaSource | string;
28
30
  autoplay?: boolean;
29
31
  muted?: boolean;
30
32
  loop?: boolean;
31
33
  controls?: boolean;
34
+ /** 默认错误覆盖层,省略时开启。仅初始化读取;变更须重新挂载,不影响错误事件。 */
35
+ showErrorOverlay?: boolean;
36
+ /** 是否显示 SDK 运行时 Loading;构造期读取,默认 true。 */
37
+ showLoadingOverlay?: boolean;
38
+ /** 内置控件初始化显示策略;修改后须由宿主显式重建播放器。 */
39
+ controlVisibility?: ControlVisibilityConfig;
32
40
  /** false 时播放器不接收指针事件(点击穿透到下层,如首页预览卡片) */
33
41
  interactive?: boolean;
34
42
  playsinline?: boolean;
@@ -88,6 +96,7 @@ export interface VideoPlayerProps {
88
96
  export interface VideoPlayerEmits {
89
97
  /** 完整的契约事件流,供遥测适配器使用;不裁剪 payload。 */
90
98
  (e: 'playerEvent', payload: PlayerEvent): void;
99
+ (e: 'deliveredPlayerEvent', payload: DeliveredPlayerEvent): void;
91
100
  /**
92
101
  * metadata 就绪。`quality` 是可切档位清单(单码率源为空数组),团队层据此渲染清晰度菜单;
93
102
  * `subtitles` 是可切字幕轨清单(无字幕源为空/缺省,契约 1.0.0 起可选,ADR-027),团队层据此渲染字幕菜单。
@@ -137,12 +146,6 @@ export interface VideoPlayerEmits {
137
146
  }): void;
138
147
  (e: 'error', payload: PlayerError): void;
139
148
  (e: 'autoplayBlocked'): void;
140
- (e: 'reconnectStart', payload: {
141
- attempt: number;
142
- maxAttempts: number;
143
- }): void;
144
- (e: 'reconnectSuccess'): void;
145
- (e: 'reconnectFailed'): void;
146
149
  (e: 'compatWarning', payload: {
147
150
  code: string;
148
151
  message: string;
@@ -166,11 +169,9 @@ export interface VideoPlayerEmits {
166
169
  * `recoverable` 决定盖 loading(等)还是露重试入口(不等);`reason='degraded'`
167
170
  * 是唯一 `playable` 仍为 `true` 的值(掉帧严重但画面还在动,可以忽略)。
168
171
  */
169
- (e: 'playableChange', payload: {
170
- playable: boolean;
171
- reason: PlayableReason;
172
- recoverable: boolean;
173
- }): void;
172
+ (e: 'playableChange', payload: Extract<PlayerEvent, {
173
+ event: 'playablechange';
174
+ }>['payload']): void;
174
175
  /**
175
176
  * 内核健康 —— **非致命内核诊断的聚合**(契约 4.1.0 / ADR-062 / issue #391)。
176
177
  *
@@ -213,6 +214,8 @@ export interface VideoPlayerEmits {
213
214
  * ⚠️ 它不是掉帧率,也不与 `stalled` 重复(后者是缓冲驱动的等待)。
214
215
  */
215
216
  (e: 'frameFreeze', payload: FrameFreezePayload): void;
217
+ /** 实际网页全屏状态变化。 */
218
+ (e: 'pageFullscreenChange', payload: PageFullscreenState): void;
216
219
  /**
217
220
  * 用户动作(ADR-075),经白名单过滤,只含**发生在 SDK 内部**的那些。
218
221
  *
@@ -238,6 +241,8 @@ export interface VideoPlayerExpose {
238
241
  setMuted(muted: boolean): void;
239
242
  setVolume(volume: number): void;
240
243
  setPlaybackRate(rate: number): void;
244
+ /** 设置网页全屏;必须等宿主布局与 iframe 状态确认。 */
245
+ setPageFullscreen(active: boolean): Promise<void>;
241
246
  /** 进入全屏(容器托管,不碰 video 原生入口,iOS 微信崩溃入口由 FullscreenGuard 中和) */
242
247
  enterFullscreen(): Promise<void>;
243
248
  /** 退出全屏 */
@@ -253,9 +258,7 @@ export interface VideoPlayerExpose {
253
258
  setDanmakuEnabled(enabled: boolean): void;
254
259
  /** 清空屏上弹幕(ADR-028) */
255
260
  clearDanmaku(): void;
256
- reconnect(options?: {
257
- resetCounter?: boolean;
258
- }): void;
261
+ retry(): Promise<void>;
259
262
  destroy(): void;
260
263
  getCurrentTime(): number;
261
264
  getDuration(): number;
@@ -36,9 +36,9 @@ export declare function toConfig(props: VideoPlayerProps): PlayerConfig;
36
36
  * 播放器事件 → Vue emits。名字从 wire 上的小写拼写换成 camelCase 事件名,
37
37
  * 和 `vue-frame` 的 `forward` 逐条对应(cross-mode-parity):同样的事件、同样的 payload。
38
38
  *
39
- * **契约声明的 19 个事件必须一个不少地出现在这里**,由 `protocol/tests/consumer-surface.contract.test.ts`
39
+ * **契约声明的 27 个事件必须一个不少地出现在这里**,由 `protocol/tests/consumer-surface.contract.test.ts`
40
40
  * 静态断言。`video-react` 曾经漏过 4 个(seeking / seeked / waiting / playing)——
41
- * 而静态 iframe 模式是裸广播、19 个全发,于是同一份契约在几种接入方式下能收到的事件
41
+ * 而静态 iframe 模式是裸广播、27 个全发,于是同一份契约在几种接入方式下能收到的事件
42
42
  * 不一样,parity 红线实际已破。别再以"业务暂时用不到"为由少接一个。
43
43
  */
44
44
  export declare function forward(event: PlayerEvent, emit: VideoPlayerEmits): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@video-lab/vue",
3
- "version": "1.0.1",
3
+ "version": "3.0.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -25,23 +25,24 @@
25
25
  ],
26
26
  "sideEffects": false,
27
27
  "peerDependencies": {
28
- "vue": ">=3.5.0"
28
+ "vue": "^3.4.0"
29
29
  },
30
30
  "dependencies": {
31
- "@video-lab/protocol": "1.0.1",
32
- "@video-lab/player-ui": "1.0.1",
33
- "@video-lab/player-core": "1.0.1"
31
+ "@video-lab/protocol": "3.0.0",
32
+ "@video-lab/player-core": "3.0.0",
33
+ "@video-lab/player-ui": "3.0.0"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@vitejs/plugin-vue": "^6.0.8",
37
- "@vue/test-utils": "^2.4.0",
37
+ "@vue/test-utils": "2.4.6",
38
38
  "jsdom": "^24.0.0",
39
39
  "typescript": "~5.9.0",
40
40
  "vite": "^8.1.5",
41
41
  "vite-plugin-dts": "^5.0.3",
42
42
  "vitest": "^4.1.10",
43
- "vue": "^3.5.0",
44
- "vue-tsc": "^2.0.0"
43
+ "vue": "3.4.0",
44
+ "vue-tsc": "^2.0.0",
45
+ "@vue/server-renderer": "3.4.0"
45
46
  },
46
47
  "description": "Video Lab Player Vue 3 inline 组件:直连 player-core 的高性能接入方式",
47
48
  "publishConfig": {