@cycjimmy/jsmpeg-player

中文文档
7.0.0发布于 2026/11/01MITES Module零依赖构建来源已验证近 30 天下载 4.6万

MPEG1 Video Player Based On JSMpeg

原始使用文档
文档目录11 节
  1. How to use
  2. Install
  3. Usage
  4. Snapshot
  5. WebSocket authentication
  6. Multiple players
  7. Use in browser
  8. CDN
  9. Migrating to v7
  10. Development
  11. Encoding Video/Audio for jsmpeg by ffmpeg . E.g:

JSMpeg Player(TS Player)

Test CI libraries dependency status libraries sourcerank Release date vite semantic-release npm license

  • jsmpeg-player has been renamed to @cycjimmy/jsmpeg-player for scoped NPM package.
  • JSMpeg player is based on jsmpeg.
  • The video must be compressed into the TS format of MPEG1 / MP2.
  • Autoplay with sound is blocked by the browser until the page receives a user gesture: Apple device automatically plays without sound, you need to guide the user to click on the video in the lower right corner of the video icon to unlock the sound. Chrome and Safari follow the same autoplay policy, where the sound stays in sync with the picture and starts as soon as the user interacts with the page, or can be unlocked right away through the same icon. (no similar problem in non-autoplay mode)
  • Demo

How to use

Install

NPM version NPM bundle size npm download

$ npm install @cycjimmy/jsmpeg-player --save
# or
$ yarn add @cycjimmy/jsmpeg-player

Usage

import JSMpeg from '@cycjimmy/jsmpeg-player'
// new JSMpeg.VideoElement(videoWrapper, videoUrl [, options] [, overlayOptions])
  • JSMpeg.VideoElement config:

    • videoWrapper: [String | Element] The wrapper of the video — either a CSS selector that must match an existing element, or a DOM element itself. It must be a container element (e.g. a div); do not pass the <canvas> itself — the children of a canvas are fallback content and are never rendered, which results in a black screen. Pass the canvas via the canvas option instead. The height and width of the wrapper are recommended to be initialized.
    • videoUrl: [String] A non-empty raw string. The built-in sources accept a relative or http(s):// URL to an MPEG-TS resource (the file name does not have to end with .ts), or a ws:// / wss:// URL delivering MPEG-TS. An already created WebSocket instance is not accepted. Custom sources (source in overlayOptions) define their own input.
    • options: [Object] support:
      • canvas: [String | Element] The HTML canvas element to use for video rendering. If none is given, the renderer will create its own canvas element. Default ''.
      • poster: [String] URL to an image to use as the poster to show before the video plays. (Recommended to set it manually)
      • autoplay: [Boolean] Whether to start playing immediately. Default false.
      • autoSetWrapperSize: [Boolean] Whether to set the wrapper element size automatically when the video loaded. Default false.
      • loop: [Boolean] Whether to loop the video (static files only). Default false.[overwrite]
      • control: [Boolean] Whether the user can control. The built-in play button and click-to-toggle apply to static files only: ws:// / wss:// live sources have no built-in playback control and must be driven with play() / pause(). Default true.
      • decodeFirstFrame: [Boolean] Whether to decode and display the first frame of the video. Default true.
      • picMode: [Boolean] Picture mode (no playButton). Default false.
      • progressive: [Boolean] whether to load data in chunks (static files only). Default true.
      • chunkSize [Number] The chunk size in bytes to load at a time. Default 1024*1024 (1mb).
      • hooks: [Object] The hook function
        • play: [Function] The hook function when the video play.
        • pause: [Function] The hook function when the video pause.
        • stop: [Function] The hook function when the video stop.
        • load: [Function] The hook function when the video established.
    • overlayOptions: [Object] More options can view the jsmpeg options
      • protocols: [String | Array] WebSocket subprotocols, forwarded to new WebSocket(url, protocols) (ws:// and wss:// URLs only). Can carry a Bearer token. Default undefined. See WebSocket authentication.
      • preserveDrawingBuffer: [Boolean] Keep the WebGL drawing buffer so the canvas can be read back, e.g. to take a snapshot with canvas.toDataURL(). Default false. See Snapshot.
  • JSMpeg.VideoElement instance supports the following methods:

    • play(): Start playback
    • pause(): Pause playback
    • stop(): Stop playback and seek to the beginning
    • destroy(): Stop playback, release the source, renderer, decoders and audio, and empty video wrapper. Required when the player is removed, see Multiple players.
  • JSMpeg.VideoElement.player instance API can view the JSMpeg.Player API

Snapshot

The WebGL drawing buffer is cleared once a frame has been composited, so reading the canvas without preparation returns a black image. Set preserveDrawingBuffer in overlayOptions:

const video = new JSMpeg.VideoElement('#videoWrapper', 'video.ts', {}, {
  preserveDrawingBuffer: true,
})

// Any time after the first frame has been rendered
const dataUrl = video.els.canvas.toDataURL('image/png')
  • The flag is read when the WebGL context is created, so it must be passed at construction time — it can not be enabled on a player that is already running.
  • If you pass your own element through the canvas option and it already has a WebGL context (because getContext('webgl') was called on it before the player was created), that context is reused and the flag is ignored. Let the player create the context instead.
  • Keeping the buffer has a performance cost, so leave the flag off if you do not need snapshots.
  • WebGL is not required: with disableGl: true the player falls back to the Canvas 2D renderer, where toDataURL() always works, at the price of a higher CPU usage.

WebSocket authentication

A browser can not set an Authorization header on a WebSocket handshake — new WebSocket(url, protocols) is all the WebSocket API offers. The closest browser-native option is to send the token as a subprotocol, which arrives on the server as the Sec-WebSocket-Protocol request header (kept out of the URL and out of access logs):

const video = new JSMpeg.VideoElement('#videoWrapper', 'wss://example.com/stream', {}, {
  protocols: ['Bearer.<token>'],
})
const player = new JSMpeg.Player('wss://example.com/stream', {
  protocols: ['Bearer.<token>'],
})
  • The server must accept the subprotocol and echo it back in the handshake response (Sec-WebSocket-Protocol). If none of the requested subprotocols is echoed, the browser aborts the connection.
  • Each value must be a valid HTTP token (RFC 7230): no spaces, +, / or =. JWTs (base64url) fit; tokens containing those characters need cookie-based auth instead (the handshake sends cookies for the target origin automatically).

Multiple players

Each JSMpeg.VideoElement is a complete, independent player: it opens its own source connection, creates its own WebGL context and runs its own decode loop. Only the AudioContext and the WASM module are shared, so how many players can play at once is bounded by the browser and the device, not by this library.

  • Browsers cap the number of live WebGL contexts per page (16 in Chrome, fewer on some mobile browsers). Past that limit the oldest contexts are dropped and their canvas stays black, without any exception being thrown.
  • Every stream is decoded in software on the main thread, and every player allocates its own decoder buffers (512 KB of video, 128 KB of audio by default). A grid of many streams competes for the same CPU time, whatever renderer is used.
  • progressive: true (the default) keeps one open request per player for the whole stream, which counts against the ~6 connections per origin of HTTP/1.1. This only applies to static files; ws:// and wss:// sources are not affected.

Call destroy() when a player goes away. In a SPA, discarding the instance returned by the constructor — e.g. calling it in componentDidMount without storing the result — leaves the player running after its markup is gone: the socket, the WebGL context and the decode loop all survive. A few navigations are then enough to exhaust the page, and since nothing throws, a hard reload appears to be the only fix.

// React
componentDidMount() {
  this.video = new JSMpeg.VideoElement('#videoWrapper', 'wss://example.com/stream');
}

componentWillUnmount() {
  this.video.destroy();
  this.video = null;
}

To keep many cameras on screen:

  • disableGl: true — the Canvas 2D renderer does not consume a WebGL context, at the price of a higher CPU usage.
  • audio: false — skip audio decoding for camera grids.
  • Create players only for the tiles that are visible (e.g. with IntersectionObserver) and destroy() them when they leave the viewport.
  • Serve a low-bitrate sub-stream to the thumbnails; for software decoding the resolution and bitrate of each stream matter more than the number of tiles.

Use in browser

jsdelivr

<div id="videoWrapper"></div>
<script src="jsmpeg-player.umd.min.js"></script>
<script>
  var videoUrl = '../static/media/test_video.ts';
  new JSMpeg.VideoElement('#videoWrapper', videoUrl);
</script>

CDN

To use via a CDN include this in your HTML:

<script src="https://cdn.jsdelivr.net/npm/@cycjimmy/jsmpeg-player@7/dist/jsmpeg-player.umd.min.js"></script>

Migrating to v7

v7 drops the CommonJS build and raises the Node and browser targets. import and the browser global are unchanged, so most consumers need no change at all.

  • dist/jsmpeg-player.cjs is no longer produced and exports no longer exposes a require condition. require('@cycjimmy/jsmpeg-player') keeps working on Node >= 20.19, because Node can require() an ES module, but it returns the module namespace: use require('@cycjimmy/jsmpeg-player').default.
  • main and module both point at dist/jsmpeg-player.esm.js. The browser field still points at the UMD build for CDN and legacy tooling.
  • engines.node is now ^22.22.2 || >=24.15.0, the floor of the new build toolchain. engines is stripped from the published tarball, so it only constrains contributors and CI, not consumers.
  • The build targets es2015 with the defaults browserslist, so IE is no longer supported. Babel down-leveling is gone, which makes jsmpeg-player.esm.js about 24% smaller and jsmpeg-player.umd.min.js slightly smaller than v6.
  • Deep paths keep working through the ./dist/* export.
  • The runtime CSS is still injected as a <style> element; there is no stylesheet to import.
// CommonJS consumers: require() can load an ES module from Node 20.19 on
const JSMpeg = require('@cycjimmy/jsmpeg-player').default

Development

$ npm run dev          # Vite dev server on top of the root index.html
$ npm run lint         # ESLint (flat config, @antfu/eslint-config)
$ npm run lint:style   # Stylelint for src/**/*.{css,scss}
$ npm test             # node --test
$ npm run package      # build dist/ and assemble .release/

index.html in the repository root is the development entry: it imports src/ through Vite, so changes show up without a build. static/index.html is the GitHub Pages demo and loads the pre-built jsmpeg-player.umd.js with a plain <script> tag; npm run build:deployment assembles it in .publish/. See CONTRIBUTING.md for the checks the CI runs.

Encoding Video/Audio for jsmpeg by ffmpeg. E.g:

$ ffmpeg -i input.mp4 -f mpegts \
         -codec:v mpeg1video -s 640x360 -b:v 700k -r 25 -bf 0 \
         -codec:a mp2 -ar 44100 -ac 1 -b:a 64k \
         output.ts
  • options
    • -s: video size
    • -b:v: video bit rate
    • -r: frame rate
    • -ar: sampling rate
    • -ac: number of audio channels
    • -b:a: audio bit rate

版本与发布记录

@cycjimmy/jsmpeg-player 共发布 24 个版本,首次发布于 2019/10/12;过去 12 个月发布了 7 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
7.0.0latest2026/11/0110 天前
6.1.82026/10/3011 天前
6.1.72026/10/3012 天前
6.1.62026/10/2912 天前
6.1.52026/10/2913 天前
6.1.42026/10/2813 天前

关于 @cycjimmy/jsmpeg-player 的常见问题

@cycjimmy/jsmpeg-player 是什么?

MPEG1 Video Player Based On JSMpeg

如何安装 @cycjimmy/jsmpeg-player?

在项目目录运行 npm install @cycjimmy/jsmpeg-player,或使用 pnpm add / yarn add / bun add。

@cycjimmy/jsmpeg-player 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/cycjimmy__jsmpeg-player 是否存在。

@cycjimmy/jsmpeg-player 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@cycjimmy/jsmpeg-player 可以商用吗?

@cycjimmy/jsmpeg-player 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@cycjimmy/jsmpeg-player 的下载量有多少?

根据 npm 官方下载统计,@cycjimmy/jsmpeg-player 在 2026/10/11 – 2026/11/09 这 30 天内被下载 45,942 次,日均约 1,531 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@cycjimmy/jsmpeg-player 还在维护吗?

最新版本 7.0.0 发布于 2026/11/01(10 天前);至今共发布 24 个版本,其中过去 12 个月发布了 7 个;首次发布于 2019/10/12。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。