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 🙏

© 2024 – Pkg Stats / Ryan Hefner

vue-jsmpeg-player

v1.3.0

Published

基于jsmpeg.js二次开发的流媒体播放器

Downloads

70

Readme

jsmpeg-player

介绍

本组件是基于jsmpeg.js二次开发的 vue2 组件(未来会支持 vue3)

  • web 播放实时视频流的几种方案对比,详见此处
  • 本方案详细介绍:在 Web 中低时延播放 RTSP 视频流(海康、大华)方案 - JSMpeg.js
  • jsmpeg.js 相关链接:giteegithub官网
  • 关于延迟问题:仅在局域网\本机下实测 1s 左右,在公网下未知,公网要考虑的东西太多(带宽、丢包、流量),公网下的流媒体服务框架这里推荐ZLMediaKitSRS
  • 关于性能问题
    • 注意:本方案存在性能瓶颈,可能不适用于大型项目,对性能有追求的请使用开源流媒体框架 ZLMediaKit、SRS
    • 由于是客户端软解码,所以性能不会太好,在目前的 i5 10 代+8g 这种配置机器上单个页面六路同屏应该是没问题的,再多就不行了,对性能有追求的只能用 webrtc 了,具体性能对比可见jsmpeg 官网性能对比
    • 在使用 vue 开发环境时,可能会产生内存溢出的错误,应该是由于频繁热更新导致的,刷新页面即可
  • 交流 QQ 群:56370082(请备注来源)

Note

[v1.2.1] 使用了 vite-plugin-libcss 插件打包,esm 方式引入(即 import)不需要再手动引入样式文件

[v1.2.0] jsmpeg.js 已迁移到独立仓库中,以 git 子模块的形式引入

  • 初次拉取仓库时请使用 git clone --recursive
  • 如果已经克隆了主仓库但没有克隆子模块,则使用 git submodule update --init --recursive

支持的格式

  • 视频:mpeg1

  • 音频:mp2

    仅支持 mpeg1 格式视频、mp2 格式音频!!!仅支持 mpeg1 格式视频、mp2 格式音频!!!仅支持 mpeg1 格式视频、mp2 格式音频!!!不要随便拿个 websocket 流去给 jsmpeg 使用,播放不了的!!!也无法直接播放 rtmp 流!!!

组件仓库/npm 地址

方案架构

rtsp 流 => ffmpeg 转码 => ~~http server 接收~~(已废弃,直接通过命令行获取转码数据) => websocket server 转发 => websocket client => 客户端软解码渲染

在这里插入图片描述

ffmpeg 推流命令示例:

ffmpeg ^
-rtsp_transport tcp -i rtsp://[用户名]:[密码]@[ip]:554/h264/ch1/main/av_stream -q 0 ^
-f mpegts ^
-codec:v mpeg1video -s 1920x1080 -b:v 1500k ^
-codec:a mp2 -ar 44100 -ac 1 -b:a 128k ^
http://127.0.0.1:8890/jsmpeg

PS:

  • 如果是公网,需要自行解决拉取摄像头 rtsp 流
  • 本组件仅实现了前端(客户端)部分的功能,后端部分的功能可参考 server 目录下的代码

安装教程

本组件使用了ES6+语法,要求如下:

  • vue > 2.6.0
  • core-js > 3 (如果不安装,编译会报错)
npm i core-js@3 vue@2 -S

npm i vue-jsmpeg-player -S

全局组件

// main.js
import Vue from 'vue'

import JSMpegPlayer from 'vue-jsmpeg-player'
import 'vue-jsmpeg-player/style.css'

Vue.use(JSMpegPlayer)

// 或者

import { JSMpegPlayer, JSMpegMultipathPlayer } from 'vue-jsmpeg-player'
import 'vue-jsmpeg-player/style.css'

Vue.component(JSMpegPlayer.name, JSMpegPlayer)
Vue.component(JSMpegMultipathPlayer.name, JSMpegMultipathPlayer)

局部组件

import { JSMpegPlayer, JSMpegMultipathPlayer } from 'vue-jsmpeg-player';
import 'vue-jsmpeg-player/style.css';

export default {
  ...

  components: {
    [JSMpegPlayer.name]: JSMpegPlayer,
    [JSMpegMultipathPlayer.name]: JSMpegMultipathPlayer
  },

  ...
}

使用

  • 单路播放
<template>
  <div>
    <jsmpeg-player :url="url" />
  </div>
</template>

<script>
export default {
  components: {},

  data() {
    return {
      url: 'ws://localhost:8089/xxx'
    }
  },
  computed: {},

  mounted() {},
  beforeDestroy() {},
  methods: {}
}
</script>

<style lang="scss"></style>
  • 多路播放
<template>
  <div>
    <jsmpeg-player.multipath v-model="players" />
  </div>
</template>

<script>
export default {
  components: {},

  data() {
    return {
      players: [
        {
          title: '桌面',
          url: 'ws://127.0.0.1:18081/desktop'
        }
      ]
    }
  },
  computed: {},

  mounted() {},
  beforeDestroy() {},
  methods: {}
}
</script>

<style lang="scss"></style>

使用说明

JSMpegPlayer - 单路播放器

属性 & Props

| 名称 | 类型 | 说明 | | -------------- | ------- | --------------------------------------------------------------------------------- | | url | string | 视频流地址(推荐 websocket,实际上 jsmpeg.js 原生也支持 http 方式,但没有经过测试) | | title | string | 播放器标题 | | no-signal-text | string | 无信号时的显示文本 | | options | object | jsmpeg 原生选项,直接透传,详见下表 | | closeable | boolean | 是否可关闭(单击关闭按钮,仅抛出事件) | | in-background | boolean | 是否处于后台,如 el-tabs 的切换,路由的切换等,支持.sync 修饰符 | | show-duration | boolean | 是否显示持续播放时间 | | default-muted | boolean | 默认静音 | | with-toolbar | boolean | 是否需要工具栏 | | loading-text | boolean | 加载时的文本,默认为:拼命加载中 |

原生属性:

| 名称 | 类型 | 说明 | | --- | --- | --- | | canvas | HTMLCanvasElement | 用于视频渲染的 HTML Canvas 元素。如果没有给出,渲染器将创建自己的 Canvas 元素。 | | loop | boolean | 是否循环播放视频(仅静态文件),默认=true | | autoplay | boolean | 是否立即开始播放(仅限静态文件),默认=false | | audio | boolean | 是否解码音频,默认=true | | video | boolean | 是否解码视频,默认=true | | poster | string | 预览图像的 URL,用来在视频播放之前作为海报显示。 | | pauseWhenHidden | boolean | 当页面处于非活动状态时是否暂停播放,默认=true(请注意,浏览器通常会在非活动选项卡中限制 JS) | | disableGl | boolean | 是否禁用 WebGL,始终使用 Canvas2D 渲染器,默认=false | | disableWebAssembly | boolean | 是否禁用 WebAssembly 并始终使用 JavaScript 解码器,默认=false(不建议设置为 true) | | preserveDrawingBuffer | boolean | WebGL 上下文是否创建必要的“截图” | | progressive | boolean | 是否以块的形式加载数据(仅静态文件)。当启用时,回放可以在完整加载源之前开始。 | | throttled | boolean | 当不需要回放时是否推迟加载块。默认=progressive | | chunkSize | number | 使用时,以字节为单位加载的块大小。默认(1 mb)1024*1024 | | decodeFirstFrame | boolean | 是否解码并显示视频的第一帧,一般用于设置画布大小以及使用初始帧作为"poster"图像。当使用自动播放或流媒体资源时,此参数不受影响。默认 true | | maxAudioLag | number | 流媒体时,以秒为单位的最大排队音频长度(可以理解为能接受的最大音画不同步时间)。 | | videoBufferSize | number | 流媒体时,视频解码缓冲区的字节大小。默认的 4 _ 1024 _ 1024 (4MB)。对于非常高的比特率,您可能需要增加此值。 | | audioBufferSize | number | 流媒体时,音频解码缓冲区的字节大小。默认的 128 * 1024 (128 kb)。对于非常高的比特率,您可能需要增加此值。 |

事件 & Emits

支持 jsmpeg.js 所有原生事件,并转换为短横线命名法,jsmpeg 官方文档 - 事件

| 名称 | 原生回调名称 | 参数 | 说明 | | --- | --- | --- | --- | | vue 组件事件 | - | - | - | | volume-change | - | number | 当音量变化时触发 | | muted | - | number | 当静音时触发 | | 原生事件 | | - | - | | video-decode | onVideoDecode | decoder, time | 视频帧解码事件,当成功解码视频帧时触发 | | audio-decode | onAudioDecode | decoder, time | 音频帧解码事件,当成功解码音频帧时触发 | | play | onPlay | player | 播放开始事件 | | pause | onPause | player | 播放暂停事件 | | ended | onEnded | player | 播放结束事件 | | stalled | onStalled | player | 播放停滞事件,当没有足够的数据播放一帧时触发 | | source-established | onSourceEstablished | source | 源通道建立事件,当 source 第一次收到数据包时触发 | | source-completed | onSourceCompleted | source | 源播放完成事件,当 source 收到所有数据时触发(即最后一个数据包) | | 扩展事件 | | - | - | | source-connected | - | - | 源连接事件(仅 websocket),当 source(websocket)连接上服务端时触发 | | source-interrupt | - | - | 源传输中断事件(仅 websocket),当 source(websocket)超过一定时间(5s)没有收到流时触发 | | source-continue | - | - | 源传输恢复/继续事件(仅 websocket),当 onSourceStreamInterrupt 触发后 websocket 第一次接收到流时触发 | | source-closed | - | - | 源关闭事件(仅 websocket),当 websocket 关闭后触发 | | resolution-decode | - | decoder, {width, height} | 分辨率解码事件,当获取到视频分辨率时触发发 |

插槽 & Slot

| 名称 | 参数 | 说明 | | --------- | ---- | -------------------------------------------------- | | title | 无 | 标题插槽,使用此插槽后 title 属性失效 | | loading | 无 | loading 插槽,可自定义加载效果 | | no-signal | 无 | 无信号时的插槽,使用此插槽后 noSignalText 属性失效 |

方法 & Method

| 名称 | 参数 | 说明 | | -------------------------------------- | --------------------------------------------------------- | ------------ | | 原生方法 | | | | play() | - | 播放 | | pause() | - | 暂停播放 | | stop() | - | 停止播放 | | nextFrame() | - | 下一帧 | | 扩展方法 | | - | | rotate(angle: string, append: bollean) | angle:旋转角度,append:是否为追加角度(即当前角度+angle) | 旋转画面 | | toggleFullscreen() | | 切换全屏模式 | | snapshot() | | 截图 | | toggleMute() | | 切换禁音模式 | | toggleRecording() | | 切换录制模式 |

JSMpegMultipathPlayer - 多路播放器

  • [x] 多路播放
  • [x] 支持拖拽交换播放器位置
  • [x] 支持从外部拖入播放器
  • [x] 支持多种分屏模式

属性 & Props

| 名称 | 类型 | 说明 | | ------------- | -------- | --------------------------------------------------------------- | | value/v-model | string[] | 播放链接列表 | | tabindex | number | 起始的 tabindex,给每个播放器加上 tabindex,方便按下 tab 键切换 | | playerProps | object | 播放器选项,透传给单个播放器 |

事件 & Emits

| 名称 | 参数 | 说明 | | --- | --- | --- | | player-click | {data:object,intance:Vue,index:number} | 点击播放器时触发 | | player-noSignal | {data:object,intance:Vue,index:number} | loading 插槽,可自定义加载效果 | | player-swap | {sourcePlayer:object,sourceIndex:number,targetPlayer:object,targetIndex:number} | 当两个播放器拖拽交换时触发 |

插槽 & Slot

| 名称 | 参数 | 说明 | | ---- | ---- | ---- | | - | - | - |

从外部拖入一个播放器

要实现此功能,只需要在目标元素的 drag-out 事件中调用 dataTransfer.setData 方法即可

function handleDragOut(ev) {
  let dt = ev.dataTransfer
  ev.dataTransfer.effectAllowed = 'copy'
  dt.setData(
    'text/plain',
    JSON.stringify({
      id: '', // 非必传
      title: '',
      url: ''
    })
  )
}

功能 & 计划

  • [x] 自动重连
  • [x] 接流中断 loading
  • [x] 截图
  • [x] 录制
  • [x] 画面旋转
  • [x] 全屏切换
  • [x] 全屏切换
  • [x] 事件总线
  • [x] 多播放器同屏显示
  • [ ] 国际化
  • [ ] 移除 element-ui 的依赖
  • [ ] 画中画显示(原生只支持 video 元素画中画显示,目前还没想到方案)
  • [x] 已知的性能问题(在 data 中定义了 player,导致被双向绑定)
  • [x] 构建升级到 vite
  • [ ] 同时支持 vue2/vue3

效果演示

  • 无信号时:

在这里插入图片描述

  • 正常播放:

在这里插入图片描述

  • 旋转画面:

在这里插入图片描述

  • 接流中断:

在这里插入图片描述

  • 截图测试:

在这里插入图片描述

  • 录制测试:

在这里插入图片描述

服务端

参考JSMpegServer 文档

关于 ffmpeg 拉取桌面流见此文章:https://waitwut.info/blog/2013/06/09/desktop-streaming-with-ffmpeg-for-lower-latency/

开发/运行 DEMO

  1. 克隆仓库,git clone --recursive https://github.com/vCloudSail/jsmpeg-player
  2. 安装依赖包,运行 cmd: npm i
  3. 启动服务端,运行 cmd: npm run server (如果使用 vscode,建议通过 vscode 启动)
  4. 启动 DEMO 客户端,运行 cmd: npm run dev
  5. 查看 demo

在这里插入图片描述

参与贡献

  1. Fork 本仓库
  2. 新建 Feat_xxx 分支
  3. 提交代码
  4. 新建 Pull Request