Skip to content

flyfish-dev/rtsp

Repository files navigation

RTSP

RTSP 是一个完整的 RTSP 播放方案:Chrome 扩展、通用 Web/React/Vue 组件、Electron/Tauri 桌面免插件应用共用同一个 Go 原生网关。

项目同时交付三种接入方式:

  1. Chrome 扩展方案:扩展 content script 自动挂载 <rtsp-player>,适合统一管控的业务页面。
  2. 通用组件方案@flyfish-dev/rtsp-player 提供 plain JS/Web Component、React、Vue 入口,并内置预构建 SDK,适合业务应用显式接入。
  3. 桌面免插件方案:Electron/Tauri 打包 Go sidecar,应用内直接原生播放 RTSP,无需安装 Chrome 扩展。

目标体验:安装扩展和本地 Go Runtime 后,业务网页只需要写:

<rtsp-player
  url="rtsp://user:pass@192.168.1.64:554/Streaming/Channels/101"
  width="640"
  height="360"
  autoplay
  controls>
</rtsp-player>

通用组件包:

npm install @flyfish-dev/rtsp-player

不使用 FFmpeg。Native 端实现:

  • Chrome Native Messaging Host 协议
  • 本地 HTTP API
  • 本地 WebSocket server
  • RTSP over TCP interleaved
  • Basic/Digest RTSP authentication
  • SDP H.264 track selection
  • RTP/H.264 depayload:Single NALU、STAP-A、STAP-B、MTAP16/24、FU-A、FU-B、Annex-B-in-RTP 兼容
  • RTP/H.265 depayload:Single NALU、AP、FU
  • H.264/H.265 SDP track selection
  • H.264/H.265 Annex-B access unit 输出
  • deepch/vdk H.264 RTSP demux + Pion WebRTC sample track
  • 多路并发 stream lifecycle:per-stream streamId、pending/active 状态、主动 stop 清理
  • 播放中断自恢复:解码器软重建、WebRTC/WS 停滞检测、指数退避整路重启

浏览器端默认优先 WebRTC,兼容 H.264/H.265;WebRTC 协商失败或 15 秒内没有可渲染视频帧时,自动回退 WebSocket + WebCodecs VideoDecoder 硬件优先解码。H.264 WebRTC 默认由 vdk 解析 RTSP 并输出干净 access unit,再交给 Pion sample track 重打包;遇到摄像头把 Annex-B H.264 起始码直接塞进 RTP payload 的非标准流时,WebSocket 路径也会容错拆包。

H.265/HEVC 能力依赖浏览器、Electron Chromium、Tauri 系统 WebView、操作系统 codec 和硬件。生产建议保留 H.264 子码流作为回退。

目录

native/       Go Native Host + Gateway + RTSP/WebRTC implementation
extension/    Chrome MV3 extension, player iframe, content-script component
web-sdk/      Optional standalone SDK custom element
packages/     Universal SDK package: JS/Web Component, React, Vue
apps/         Electron and Tauri desktop apps
scripts/      Build and Native Messaging Host install scripts
site/         Vercel homepage and documentation site

三种方案

方案一:Chrome 扩展 Runtime

适合企业内网、NVR 管理台、SaaS 业务页面。页面只写原生标签,扩展自动注入播放器 iframe。

<rtsp-player
  url="rtsp://user:pass@192.168.1.64:554/Streaming/Channels/101"
  width="960"
  height="540"
  autoplay
  controls></rtsp-player>

方案二:通用组件 SDK

适合业务前端工程显式依赖 SDK。构建产物在 packages/rtsp-sdk/dist/,免构建脚本同步输出到 web-sdk/rtsp-player-sdk.js

Plain HTML:

<script
  src="/rtsp-player-sdk.js"
  data-extension-id="你的扩展ID"></script>

<rtsp-player url="rtsp://user:pass@camera/stream" autoplay controls></rtsp-player>

React:

import { RtspPlayer } from "@flyfish-dev/rtsp-player/react";

<RtspPlayer
  extensionId="你的扩展ID"
  url="rtsp://user:pass@camera/stream"
  autoplay
  controls
/>;

Vue:

<script setup>
import { RtspPlayer } from "@flyfish-dev/rtsp-player/vue";
</script>

<template>
  <RtspPlayer
    extension-id="你的扩展ID"
    url="rtsp://user:pass@camera/stream"
    autoplay
    controls
  />
</template>

方案三:Electron / Tauri 免插件桌面应用

适合桌面监控台、内网工具、离线部署。应用内启动 Go sidecar,播放器走 runtime="desktop"

<rtsp-player
  runtime="desktop"
  transport="auto"
  codec="auto"
  url="rtsp://user:pass@camera/stream"
  autoplay
  controls>
</rtsp-player>

transport="auto" 默认 WebRTC first,失败后回退 ws-annexb

更多文档见 docs/

  • docs/overview.md
  • docs/chrome-extension.md
  • docs/web-component-gateway.md
  • docs/universal-components.md
  • docs/desktop-native.md
  • docs/multi-stream-lifecycle.md
  • docs/webrtc-hevc.md
  • docs/xiaomi-rtsp.md
  • docs/online-demo.md
  • docs/installers.md
  • docs/sdk-api.md
  • docs/security.md
  • docs/deployment.md
  • docs/validation.md
  • docs/troubleshooting.md

全链路

业务网页 <rtsp-player url="rtsp://...">
  ↓ content script 挂载组件 / 或 web-sdk 创建 iframe
Chrome extension player iframe
  ↓ chrome.runtime.sendMessage
Extension service worker
  ↓ chrome.runtime.sendNativeMessage("com.rtspweb.player")
Go Native Host 短进程
  ↓ 确保本地 Gateway daemon 已启动
Go Gateway 127.0.0.1:<random>
  ↓ RTSP over TCP interleaved
Camera / NVR
  ↓ RTP/H264 depay → Annex-B access unit
Gateway WebRTC / WebSocket fallback
  ↓ sample track / RTP passthrough / binary access unit
Player iframe / desktop webview
  ↓ WebRTC hardware decode or WebCodecs prefer-hardware
Canvas

一键安装包

推荐终端用户直接使用发布包:

https://rtsp.flyfish.dev/downloads/rtsp-macos-installer.dmg
https://rtsp.flyfish.dev/downloads/rtsp-macos-installer.zip
https://rtsp.flyfish.dev/downloads/rtsp-windows-installer.zip
https://rtsp.flyfish.dev/downloads/rtsp-linux-installer.tar.gz
release/installers/rtsp-macos-installer.dmg
release/installers/rtsp-macos-installer.zip
release/installers/rtsp-windows-installer.zip
release/installers/rtsp-linux-installer.tar.gz

三端安装包都提供图形入口:

  • macOS:打开 DMG 后运行 RTSP Installer.app
  • Windows:解压后运行 RTSP Installer.hta
  • Linux:解压后运行 RTSP Installer.desktop,或运行 install-gui.sh

图形安装器会根据系统语言显示中文或英文,准备本地 Runtime、复制 Chrome 扩展目录、注册 Native Messaging Host,并打开 Chrome 扩展页。脚本入口保留为备用。

发布包由维护者统一构建,普通用户只需要下载并运行当前系统的安装器。

固定 Chrome 扩展 ID:

giegomfhcmgebjhdiihnjohoinkbcjbh

Chrome 仍然要求用户在 chrome://extensions 中手动点击 Load unpacked。安装器会打开对应页面,并把 extension 目录复制到剪贴板或显示在完成提示中。

开发安装

1. 构建 Go Native Runtime

Linux/macOS:

./scripts/build.sh

Windows PowerShell:

./scripts/build.ps1

输出在 dist/

桌面应用开发

Electron:

npm run build:sdk
./scripts/build.sh
cd apps/electron
npm install
npm run start

Tauri:

npm run build:sdk
./scripts/build.sh
npm run build:desktop
cd apps/tauri
npm install
npm run dev

2. 加载 Chrome 扩展

打开:

chrome://extensions

开启 Developer mode,点击 Load unpacked,选择本仓库的 extension/ 目录。

扩展 ID 已通过 manifest key 固定为:

giegomfhcmgebjhdiihnjohoinkbcjbh

3. 注册 Native Messaging Host

macOS:

./scripts/install-host.sh giegomfhcmgebjhdiihnjohoinkbcjbh ./dist/rtsp-web-native-darwin-arm64

Linux:

./scripts/install-host.sh giegomfhcmgebjhdiihnjohoinkbcjbh ./dist/rtsp-web-native-linux-amd64

Windows PowerShell:

./scripts/install-host.ps1 -ExtensionId giegomfhcmgebjhdiihnjohoinkbcjbh -BinaryPath .\dist\rtsp-web-native-windows-amd64.exe

4. 检测

点击 Chrome 扩展图标,看到:

Native Runtime 正常,Gateway 端口:xxxxx

如果客户现场 VLC 正常但网页无法播放,打开同一个弹窗里的 日志与诊断

  • 刷新日志:读取扩展日志、Native Gateway 日志、PID、端口和版本。
  • 复制日志:生成可直接发给技术支持的诊断文本。
  • 重启 Native:清理当前记录的旧 Gateway 进程并拉起已安装的新版本。

日志会记录 RTSP OPTIONS / DESCRIBE / SETUP / PLAY、WebRTC 协商、WebSocket 回退和浏览器解码错误,并自动遮蔽 RTSP 账号密码。

如果 VLC/FFmpeg 能播放但浏览器无画面,重点看日志里的 webrtc backend: vdk|pionvdk rtsp codec update receivedvdk rtsp codec update appliedvdk webrtc write sample failedwebrtc vdk refusing offer ... (B-frames possible) -> ws-annexbaccess unit timestamp reset detectedh264 annexb-in-rtph264 fu-a annexb-fragmenth264 runtime parameter syncwebrtc repacketize soft-starting h264 after parametersh264 sps oversized droppedh264 sps salvaged inline naluswebrtc answer profile-level-id upgradedwebrtc rtcp browser PLI/FIR forwarded。从 0.1.14 开始,Native 会兼容 Annex-B-in-RTP 这类非标准 H.264 RTP;0.1.15 继续补齐运行中才出现 PPS、长期等不到标准 IDR 标识的摄像头流,WebSocket/WebCodecs 路径会同步参数集并尽快出首帧,WebRTC 路径会在不转码的前提下软启动和重新封装 RTP;0.1.16 会丢弃部分国产摄像头在 SPS NAL 中夹带的厂商私有元数据(一般 >80KB),避免每个关键帧被放大数十倍而导致周期性卡顿、帧回退以及 WebRTC 解码失败;0.1.17 重做了 native host 的启动互斥锁,记录持有者 PID 并修复 Windows 上的进程存活探测,消除频繁出现的 gateway startup lock timeout0.1.18 在丢弃超大 vendor SPS 的同时,从其内部 Annex-B 数据中抢救出真实的 SPS/PPS/IDR,恢复 natapp 等透传链路上的异常流;0.1.19 让 WebRTC 真正能播 baseline 4.x 等高 level 码流,补齐 H.264 profile-level-id=42c033、浏览器 RTCP PLI/FIR 到 RTSP keyframe request 的反馈回路,以及关键帧前 SPS/PPS/SEI 聚合下发;0.1.20 把 H.264 WebRTC 默认路径切到 deepch/vdk RTSP demux;0.1.21 进一步把 WebRTC 发送端固定为 Pion TrackLocalStaticSample,vdk 负责抽出干净 SPS/PPS 和 access unit,Gateway 将同一帧的 NAL 合成一个 Annex-B sample 交给 Pion 重打包,避开手写 FU-A 循环和 vdk webrtcv3 的早写包/默认 STUN 风险(需要回退到旧路径时可通过 RTSP_WEBRTC_BACKEND=pion 环境变量切换);0.1.24 在 vdk 后端拉到第一份 codec 时解析 SPS 的 profile_idcconstraint_set1_flag,对 High/Main 等可能包含 B 帧的流(例如 mediamtx 滚动推送 1.mp4 的 IBBBP 24fps 流)直接拒绝 WebRTC 协商并向播放器返回 ws-annexb 回退,从根本上消除 Chrome WebRTC jitter buffer 把 B 帧当作迟到包丢弃导致的"反复跳帧/回退帧";同一版本 Player 端 WebCodecs 接入也不再强制把 access unit 时间戳改成单调递增,B 帧合法的 PTS 倒退会被原样送给 EncodedVideoChunk,由解码器内部完成 DPB reorder,只在 PTS 真的倒退超过 5 秒(摄像头时间戳重置)时才整体加上一个新的偏移量。

5. 授权业务页面 origin

扩展弹窗里添加页面来源,例如:

http://localhost:5173
https://your-app.example.com

也可以只在内网调试时使用 *,正式环境不要这样做。

页面也可以在加载时请求扩展自动把当前 origin 加入白名单:

window.postMessage({ type: "RTSP_INSTALL_STATUS_REQUEST", autoAllowOrigin: true }, location.origin);

扩展只会保存当前页面的 location.origin,不会接受页面传入任意第三方地址。

6. 网页使用组件

如果扩展 content script 已覆盖你的站点,直接写:

<rtsp-player
  url="rtsp://user:pass@192.168.1.64:554/Streaming/Channels/101"
  width="960"
  height="540"
  autoplay
  controls>
</rtsp-player>

可监听事件:

const p = document.querySelector('rtsp-player');
p.addEventListener('ready', () => console.log('ready'));
p.addEventListener('error', (e) => console.error(e.detail.error));

如果你不想依赖 content script,也可以使用 web-sdk/rtsp-player-sdk.js

<script
  type="module"
  src="/rtsp-player-sdk.js"
  data-extension-id="你的扩展ID"></script>

<rtsp-player url="rtsp://..."></rtsp-player>

原生 HTML/CSS/JS 集成 demo:

https://rtsp.flyfish.dev/docs/demo-page/index.html

该 demo 暴露 window.RTSPDemo.checkInstall()window.RTSPDemo.play(url)window.RTSPDemo.stop(),并从同站点本地 /docs/demo-page/downloads/ 提供 macOS、Windows、Linux 安装包下载。

生产化建议

  1. extension/manifest.json 的 content script matches 限定为你的业务域名,避免所有网页都能创建 RTSP 组件。
  2. 当前 unpacked 扩展已固定 ID;后续发布到 Chrome Web Store 后建议把安装助手切到 Web Store 页面。
  3. 用安装器一次性安装:Chrome 扩展目录、本地 Go 二进制、Native Messaging manifest。
  4. 本地 Gateway 已经只监听 127.0.0.1,并使用 Native Host secret + 单次 stream token。
  5. RTSP URL 不放在 iframe query string,避免账号密码泄漏到日志、历史记录或 Referer。
  6. 摄像头建议同时准备 H.264 子码流和 H.265/H.264 主码流;默认 WebRTC first,必要时切 H.264 回退。

协议说明

Gateway → Browser WebSocket:

  1. 文本帧:
{"type":"config","codec":"avc1.64001F","format":"annexb","mediaTransport":"ws-annexb"}
  1. 二进制帧:
byte 0      message type = 1
byte 1      key frame flag: 1 key, 0 delta
byte 2..3   reserved
byte 4..11  uint64 little-endian timestamp_us
byte 12..15 uint32 little-endian payload length
byte 16..   H.264 Annex-B access unit

WebCodecs H.264/H.265 使用 Annex-B 模式,因此 VideoDecoderConfig.description 不设置。WebRTC 路径优先直接转发摄像头 RTP;遇到 Annex-B-in-RTP 或非标准 FU-A/FU-B 外壳时,会在 Native 内重新封装为浏览器可接收的 H.264 RTP,不做编码转码。

限制

  • 当前只实现 RTSP over TCP interleaved;这是摄像头/NVR 最稳定的浏览器转流路径。
  • 当前只传视频,不传音频。
  • 不做转码和软件解码;浏览器不支持当前 H.264/H.265 profile/level 时,需要调整摄像头编码参数。
  • WebRTC/H.265 取决于浏览器、系统 WebView、操作系统和硬件能力。
  • 真实播放流畅度仍取决于摄像头 GOP、码率、网络、WebRTC/WebCodecs 支持和硬件解码能力。

联系与支持

如需定制集成、企业部署或问题反馈,可以通过下方方式联系。觉得项目有帮助,也欢迎支持维护。

客服联系 微信打赏 支付宝打赏 公众号
客服联系 微信打赏 支付宝打赏 公众号

About

Public release artifacts for RTSP Chrome runtime and SDK

Resources

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages