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

@sentinel-lab/video-player-core

v4.0.0

Published

Sentinel Video Player 播放核心:xgplayer 抽象 + 11 个生产稳定性插件(选源 / 重连 / 自动播放 / 兼容 / 卡顿测量等)

Readme

@sentinel-lab/video-player-core

Sentinel Video Player 的播放核心(L1)。包装 xgplayer 3.0.26,对外提供统一的命令 / 事件接口,把生产坑点挡在这一层。

依赖:@sentinel-lab/video-protocol + xgplayer 3.0.26(精确锁)+ xgplayer-hls.js + xgplayer-flv.js。不依赖 React / Vue

已实现范围

11 个稳定性插件全部实现(P0×5 + P1×3 + P2×3),逻辑均有单元测试覆盖:

| 插件 | 优先级 | 解决的 pitfall | |:---|:---:|:---| | safeDestroy | P0 | #3(destroy 后监听残留)、#4(root 样式残留)、#23(反复 destroy 崩溃) | | SourceRouter | P0 | #22(Firefox 不原生支持 HLS)、#27/#28/#29(FLV 在 iOS / 微信 / UC / 夸克 播不了)、#34(带 query 的 HLS URL 推断失败) | | AutoplayGuard | P0 | #16(autoplay 被拒未告知业务) | | Reconnect | P0 | #1(断网无重连)、#2(换源失败无重试) | | Visibility | P0 | #5 / #24(iOS 后台切回卡死) | | Compat | P1 | #9(UC 劫持播放器)、#10(夸克控件消失) | | WakeLock | P1 | #15(播放期间屏幕熄灭) | | HealthMonitor | P1 | #13 / #14(卡顿测量,经 stalled 事件上报) | | ErrorRecovery | P2 | #17 / #18(点播坏 ts 跳过、MP4 abort 续播) | | FullscreenGuard | P2 | #7(iOS 微信全屏崩溃) | | ZIndexGuard | P2 | 层级冲突(归一 player 根节点 z-index) |

清晰度 / ABR 全链路已实现:setQuality 命令、qualitychange 事件、ready.quality 档位清单 (从 hls.js 填充,单码率源为空数组)。字幕(setSubtitle / subtitlechange / ready.subtitles, ADR-027)、弹幕(pushDanmaku / setDanmakuEnabled / clearDanmaku + config.danmaku,ADR-028)、 LL-HLS 显式开启(source.hls.lowLatencyMode,ADR-024)也已接线。

用法

import { createPlayer } from '@sentinel-lab/video-player-core'

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

await player.play()
player.seek(30)
player.destroy() // 幂等,反复调用安全

设计上值得知道的几件事

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

MP4 永远走浏览器原生 <video> xgplayer-mp4 是硬阻塞(坑 #30/#31/#32,Issue #1872 卡死 / #1578 iOS 17+ 不兼容 / #964 SourceBuffer 溢出),永不引入。

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

safeDestroy 没有 enabled 开关。 ARCHITECTURE § 10.2 明确它"强制,不可关"——一个能被关掉的内存泄漏防护没有意义。

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

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

环境探测与测试

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

单元测试用轻量 stub,不实例化真实 Player(见 tests/create-player.test.tsMockPlayer)。

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