npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@video-lab/player-core

v4.1.5

Published

Video Lab Player 播放核心:xgplayer 抽象、统一恢复与播放稳定性能力

Readme

@video-lab/player-core

Video Lab Player 的播放核心。它包装 xgplayer,并对外提供统一的命令与事件接口。

依赖 @video-lab/protocol、xgplayer、hls.js/light 与 xgplayer-flv.js,不依赖 React 或 Vue。业务应用通常使用 @video-lab/react 或 @video-lab/vue;仅在自定义集成时直接使用本包。

安装

pnpm add @video-lab/player-core

什么时候直接使用它

| 你的场景 | 推荐入口 | | --- | --- | | React / Vue 业务页面,使用 SDK 默认组合 | @video-lab/react / @video-lab/vue | | 需要 iframe 隔离 | @video-lab/react-frame / @video-lab/vue-frame | | 自己持有 DOM、渲染覆盖层和播放器生命周期 | 本包 | | 静态 CMS iframe | @video-lab/embed-helper |

直接使用本包意味着宿主自己负责创建容器、把 PlayerEvent 连接到 UI、处理命令 rejection,并在页面卸载时 销毁句柄。它不是“功能更全”的默认业务入口;框架宿主优先使用对应组合包。

已实现范围

生产装配以 src/create-player.ts 为准。它固定注册下面这些 SDK BasePlugin;消费方不能逐个关闭:

| 组件 | 职责 | |:---|:---| | SafeDestroyPlugin | 清理事件与根节点样式,支持重复销毁 | | AutoplayGuardPlugin | 上报自动播放被拒绝 | | VisibilityPlugin | 在适用平台处理页面切回后的恢复意图 | | CompatPlugin | 识别 UC / 夸克等已知兼容风险并上报 | | WakeLockPlugin | 播放时维持屏幕唤醒 | | FullscreenGuardPlugin | 规避已知全屏崩溃入口 | | ZIndexGuardPlugin | 归一播放器根节点层级 | | HealthMonitorPlugin | 测量卡顿并提交观测与恢复意图 | | PlayableStatePlugin | 聚合可播放状态并发出 playablechange | | MediaSessionPlugin | 将媒体元信息同步给 W3C Media Session |

SourceRouter 是构造前运行的纯函数,不是 xgplayer 插件;网络与媒体恢复由 PlaybackRecovery / RecoveryController 统一调度。ReconnectPlugin 与 ErrorRecoveryPlugin 的源码只保留历史回归,不进入生产 preset。HLS 会按路由追加 SDK 自有的 OwnedHlsPlugin,字幕与弹幕插件只在对应配置启用时注册。

支持清晰度与 ABR:setQuality 命令、qualitychange 事件及 ready.quality 档位清单(单码率源为空数组)。也支持字幕、弹幕和通过 source.hls.lowLatencyMode 显式开启的低延迟 HLS。

用法

<div id="video-player"></div>
import { createPlayer } from '@video-lab/player-core'
import '@video-lab/player-core/style.css'

const container = document.querySelector('#video-player')
if (!(container instanceof HTMLElement)) throw new Error('播放器容器未找到')

const player = createPlayer({
  el: container,
  config: {
    source: {
      sources: [
        { url: 'https://media.example.com/video/master.m3u8', type: 'hls' },
        { url: 'https://media.example.com/video.mp4', type: 'mp4' },
      ],
    },
    muted: true,
  },
  onEvent: (e) => console.log(e.event, e.payload),
})

await player.play()
player.seek(30)

window.addEventListener('pagehide', () => player.destroy(), { once: true })

destroy() 是幂等的,但应在组件卸载或页面离开时调用;不要在播放器创建后立即销毁。

接入完成清单

  • 宿主通过 config.source 提供已授权的媒体地址;SDK 不接收请求头,也不刷新签名 URL。
  • 将 onEvent 用于本地 UI 和状态同步;timeupdate 等事件可能高频,不能在回调里直接发送网络请求。
  • 需要可排序、可去重的上报时消费带 delivery 的 onEvent,再交给 @video-lab/telemetry;该包只归一事件, 业务方仍负责 transport 的队列、批量和失败观测。
  • 所有异步命令都 await 并处理 rejection;error 是诊断事实,加载/重试按钮应以 playablechange 的 playable、recoverable、action 驱动。
  • 组件或页面卸载时调用 destroy();需要切换 HLS/FLV 等不同内核时先销毁,再以新源重建。

设计上值得知道的几件事

SourceRouter 不是 xgplayer 的 BasePlugin,是纯函数。 选源必须发生在 new Player() 之前——内核插件(hls.js / flv.js)得在构造时就注册进去,而 BasePlugin 的生命周期最早只到 beforeCreate,拿不到这个时机。纯函数也更好测:UA 直接传进来,不用为了测 iOS 去改 navigator。

MP4 始终走浏览器原生 <video>。 这样可避免额外媒体管线带来的兼容性与缓冲风险。

destroy() 先摘监听,再销毁 player。 顺序反了的话,xgplayer 在销毁过程中还会抛 pause / ended,消费方会在组件已经卸载之后收到事件(坑 #3)。这个顺序有测试守着。

safeDestroy 没有 enabled 开关。 销毁保护必须始终启用,才能可靠地避免监听器与样式残留。

换内核会明确报错。 hls.js / flv.js 的内核插件在构造时注册,运行时换不了。load() 一个需要不同内核的源时抛 E_METHOD_NOT_SUPPORTED,而不是悄悄播不出来。消费方需要销毁 player 用新 source 重建。

新源加载失败只经 error 事件报告一次。 load() 在这次换源有结论时 resolve:新源起播、源故障已通过 error 报出、被更新的 load() 取代或播放器销毁。它只在换源前的校验失败(非法 source、换内核、改构造期配置、选不出可播放源)时 reject(ADR-136);reject 前会先暂停旧源,避免它在错误层下继续播放(ADR-137)。

直播的 duration 是 0,不是 Infinity。 Infinity 过不了 JSON 序列化(变成 null),而事件要跨 iframe 传,所以在源头就归一成 0。

环境探测与测试

detectEnv({ userAgent, hasMediaSource }) 是纯函数,UA 从外部注入。SSR 场景(没有 window / navigator)保守降级成"无 MSE、强制 HLS"——在服务端误判成能播 FLV 会让首屏白屏。

单元测试使用轻量 stub,不实例化真实播放器。

pnpm --filter @video-lab/player-core test

宿主网页全屏

通过 pageFullscreen 传入宿主布局适配器(setActive(active) / dispose()),句柄 setPageFullscreen(active) 等待布局确认。实际状态事件为 pagefullscreenchange;React 使用 onPageFullscreenChange,Vue 使用 @page-fullscreen-change。

网页全屏的组件接入示例见当前版本 React/Vue 接入包随包交付的 README 与接入 Skill。iframe 需要新版宿主与 iframe 协商支持;未启用时新入口不可用。浏览器原生全屏接口保持独立。

统一恢复(契约 v2)

旧 reconnect({ resetCounter }) 和 reconnectstart/success/failed 已移除。命令入口是 retry(): Promise<void>;Promise 完成只表示接受或合并请求。恢复中的重复请求共用预算,强播放证据通过 recovery 的 recovered 回报。

宿主 UI 读取 playablechange 的 playable、recoverable、action。error 只提供诊断;预算耗尽才给出 action: 'retry',宿主无需按错误原因拼接重试状态。组合层可通过构造配置关闭默认 Error/Loading 覆盖层,事件仍保留。静态 iframe URL 没有宿主命令通道,内部按钮仍走同一调度。

旧恢复 API 的迁移背景见维护仓库的 ADR-099;当前调用以本包导出类型和上述行为为准。

业务宿主请选择 React/Vue 接入包,按其随包交付的 README 与接入 Skill 选择模式并查找功能配方。