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-supply/dahua-player

v0.1.5

Published

Dahua WSPlayer wrapper for browser apps

Readme

@video-supply/dahua-player 中文文档

这是对大华 WSPlayer 的轻量封装,提供单入口初始化:

  • DahuaPlayer.init(options)

并对外暴露常用的播放/回放/倍速/跳转/全屏/布局切换等能力。

快速开始

import { DahuaPlayer } from '@video-supply/dahua-player';

const player = DahuaPlayer.init({
  container: 'player',
  auth: {
    token: 'YOUR_DAHUA_TOKEN',
    ip: '10.3.156.238',
    port: 8320,
  },
  cameraId: 'YOUR_CAMERA_ID',
  autoPlay: true,
  width: 'auto',
  height: 'auto',
});

await player.ready;

初始化参数(DahuaPlayer.init)

必填:

  • container: HTMLElement | string
  • auth: { token: string; ip?: string; port?: number; protocol?: 'http' | 'https' }

字段解释:

  • container
    • 播放器挂载容器
    • string:按 DOM id 查找
    • HTMLElement:直接使用该元素
  • auth.token
    • 鉴权 token(必填)
    • 仅做非空校验;内部通过 sessionStorage shim 注入给 WSPlayer 使用,避免 token 落盘
  • auth.ip
    • 现场部署的大华平台 IP(可选)
    • 用于内部拼装 targetOrigin,写入 sessionStorage.wsplayer_origin,可在网关/nginx 侧用于代理转发
  • auth.port
    • 现场部署的大华平台端口(可选)
    • 同上,用于拼装 targetOrigin
  • auth.protocol
    • 协议(可选):httphttps(默认 https

播放相关:

  • mode?: 'real' | 'record'
    • 播放模式:实时预览 / 录像回放(默认 real
  • cameraId?: string
    • 单通道编码(可选)
  • cameraIds?: string[]
    • 多通道编码(可选)
    • 最终实际播放数量会按“当前路数 num”裁剪
  • autoPlay?: boolean
    • true 时在 ready 后自动触发一次播放(默认 false
    • mode=real 需要 cameraId/cameraIds 至少一个存在
    • mode=record 需要 recordStartTime/recordEndTimecameraId/cameraIds 至少一个存在
  • recordStartTime?: number
    • 录像回放开始时间(Unix 秒)
    • mode=record + autoPlay=true 使用
  • recordEndTime?: number
    • 录像回放结束时间(Unix 秒)
    • mode=record + autoPlay=true 使用
  • recordSource?: number
    • 录像来源(透传给 WSPlayer)
    • mode=record + autoPlay=true 使用
  • streamType?: 1 | 2 | 3
    • 码流类型:1 主码流 / 2 辅码流1 / 3 辅码流2(默认 2
  • searchOnline?: boolean
    • 是否由组件内部查询在线状态(默认 false

布局/显示:

  • num?: number
    • 初始显示路数(默认 1
    • 常用值:1/4/9/16/25
  • maxNum?: number
    • 最大支持路数(默认 1
    • 上限仍受 WSPlayer 内核与浏览器性能影响
  • showRecordProgressBar?: boolean
    • 是否展示录像回放时间轴
    • 未传时:record 默认 truereal 默认 false
  • dblClickFullscreen?: boolean
    • 是否启用双击切换全屏/退出全屏(默认 true

高级:

  • staticPath?: string
    • 静态资源根路径(默认 /wsplayer-gov
  • sdkUrl?: string
    • WSPlayer 脚本地址(默认 /wsplayer-gov/wsplayer.min.js
  • playerOptions?: Record<string, unknown>
    • 透传给底层 PlayerManager 的原始配置(与内部默认配置合并)
  • debug?: boolean
    • 是否打印库内部调试日志
  • 回调
    • onReady:内核初始化完成(不等同于播放成功)
    • onPlay:播放成功(包含 real/record)
    • onPause:暂停
    • onPlaybackTime:回放当前时间变化(仅 mode=record,默认按秒变化触发)
      • 触发时机:底层 SDK 会高频推送回放帧信息;库内部只在 timeSec 变化时对外触发(约 1 次/秒)
      • payload:{ timeMs, timeSec, windowIndex?, channelCode?, raw? }
        • timeMs:当前回放时间(epoch 毫秒)
        • timeSec:当前回放时间(epoch 秒)
        • windowIndex:窗口索引(可选)
        • channelCode:通道编码(可选)
        • raw:原始 SDK data(可选,用于排障)
    • onError:初始化/播放等错误
    • onDestroy:销毁
    • onSdkMessage:透出 WSPlayer 原始消息(排障用)

实例与 SDK 方法

const instance = DahuaPlayer.init(...);
await instance.ready;
  • instance.ready: Promise<void>
    • 初始化完成后 resolve(对应 WSPlayer 的 initializationCompleted)
    • 只代表内核初始化完成,不代表已经播放成功
  • instance.pause(): void
    • 暂停当前播放窗口(默认窗口 0)
    • 语义等价于调用 instance.sdk.pause()(库内部做了兼容处理)
  • instance.destroy(): void
    • 销毁播放器实例并释放资源
    • 会移除 DOM、清理定时器、释放 sessionStorage shim
  • instance.on(event, handler) / instance.off(event, handler)
    • 订阅/取消订阅事件:ready / play / pause / playbackTime / error / destroy
    • play 事件 payload:{ mode?: 'real' | 'record' }
  • instance.getPlaybackTimeMs(): number | null
    • 主动获取最近一次收到的“当前回放时间(epoch ms)”
    • 仅 mode=record 时有意义;未收到回放时间前返回 null

回放时间示例(回调 + 主动获取)

const player = DahuaPlayer.init({
  container: 'player',
  auth: { token: 'YOUR_DAHUA_TOKEN' },
  mode: 'record',
  onPlaybackTime: ({ timeMs, timeSec, windowIndex, channelCode }) => {
    console.log('回放时间变化(秒级触发):', timeSec, timeMs, windowIndex, channelCode);
  },
});

await player.ready;

player.on('playbackTime', ({ timeMs, timeSec }) => {
  console.log('playbackTime 事件:', timeSec, timeMs);
});

player.sdk.playRecordVideo({
  startTime: Math.floor(Date.now() / 1000) - 60,
  endTime: Math.floor(Date.now() / 1000),
});

const t = player.getPlaybackTimeMs();
console.log('主动获取(可能为null):', t);

instance.sdk

  • getRaw(): any
    • 获取底层 WSPlayer/PlayerManager 实例(用于排障或调用未封装能力)
  • playRealVideo(opt: any): void
    • 实时预览播放
    • opt 透传给底层,同时支持以下通道入参(优先级从高到低):
      • opt.channelList(数组:[{ channelCode: string }, ...]
      • opt.cameraIds / opt.cameraId(内部会转为 channelList)
      • 初始化时的 cameraIds/cameraId
    • 多通道时会按当前路数 num 自动裁剪(最多播放 num 路)
  • playRecordVideo(opt: any): void
    • 录像回放播放
    • 通道入参与裁剪规则同 playRealVideo
    • 常用字段(透传底层):startTime/endTime/recordSource
  • pause(windowIndex?): void
    • 暂停指定窗口
    • windowIndex 不传时默认暂停当前窗口(底层实现可能按 0 处理)
  • play(windowIndex?): void
    • 继续播放指定窗口
  • close(windowIndex?): void
    • 关闭指定窗口播放
  • setPlayerNum(num: number): void
    • 切换布局路数(例如 1/4/9/16)
    • 变更后多通道播放的最大数量会随之变化(按新路数裁剪)
  • jumpPlayByDateTime(datetime: string | Date | number, index?: number): void
    • 录像跳转播放(仅 mode=record 可用)
    • datetime 支持:
      • string:推荐 YYYY-MM-DD HH:mm:ss
      • Date
      • number:时间戳(秒或毫秒,内部会自动兼容)
    • index:窗口索引(默认窗口 0)
  • jumpPlayByDateTimeAsync(datetime: string | Date | number, index?: number, options?): Promise<{ timeMs, timeSec, windowIndex?, channelCode?, raw? }>
    • 录像跳转播放(仅 mode=record 可用)
    • 内部基于回放时间(getVideoFrameInfo)判断跳转是否完成
    • 默认超时:30 秒
    • 返回:Promise resolve 为 { timeMs, timeSec, windowIndex?, channelCode?, raw? }(命中目标时间点时的回放时间 payload)
    • options 支持两种写法:
      • 直接传回调函数:jumpPlayByDateTimeAsync(dt, idx, (payload) => {})(等价于 onDone
      • 传配置对象:
        • timeoutMs?: number:超时时间(默认 30000)
        • toleranceMs?: number:时间命中容差(默认 1500)
        • onDone?: (payload) => void:跳转完成回调(在 Promise resolve 前触发)
    • reject 场景:超时 / 播放器销毁 / SDK 抛错(会触发 onError/error 事件)
  • playSpeed(speed: number, index: number): void
    • 设置录像回放倍速(仅 mode=record 可用)
    • speed 支持:0.125/0.25/0.5/1/1.25/1.5/2/4/8
    • index:窗口索引(通常传 0)
  • setFullScreen(): void
    • 设置播放器全屏
    • 优先调用 WSPlayer 内核全屏;如内核不支持,则回退浏览器 Fullscreen API
  • setExitFullScreen(): void
    • 退出全屏
    • 优先调用 WSPlayer 内核;如内核不支持,则回退浏览器 Fullscreen API
  • callRaw(method: string, ...args: any[]): any
    • 兜底调用底层实例的方法
    • method 为底层方法名字符串(不存在会抛出错误)

录像回放示例(多路 + 跳转 + 倍速)

const player = DahuaPlayer.init({
  container: 'player',
  auth: { token: 'YOUR_DAHUA_TOKEN' },
  mode: 'record',
  cameraIds: ['ID_1', 'ID_2', 'ID_3', 'ID_4'],
  num: 4,
  maxNum: 16,
});

await player.ready;

player.sdk.playRecordVideo({
  startTime: Math.floor(Date.now() / 1000) - 60,
  endTime: Math.floor(Date.now() / 1000),
  recordSource: 2,
});

player.sdk.playSpeed(2, 0);
await player.sdk.jumpPlayByDateTimeAsync('2026-03-01 12:00:00', 0, {
  onDone: ({ timeSec }) => console.log('跳转完成', timeSec),
});