当前位置: 首页 > news >正文

vue3+TS 前端调用海康摄像头视频流,后端用 Node.js 做 RTSP 转 WebSocket-FLV 转发,并且前后端优化延迟方案

Vue3+TS 前端调用海康摄像头视频流实践(RTSP → WS-FLV)

在物联网/安防监控项目中,前端经常需要接入摄像头实时视频流。以海康威视摄像头为例,它默认输出的是 RTSP 协议,但前端浏览器并不直接支持 RTSP。常见的做法是:

  • 后端转码/转协议:将 RTSP 转成浏览器支持的格式(如 FLV/HLS/WebRTC)。

  • 前端播放:通过 Video.js、flv.js 等播放器加载流媒体。

本文记录了一个基于 Vue3 + TypeScript 前端 + Node.js 后端 的实践过程。


一、整体架构

  1. 摄像头输出:RTSP 流(如 rtsp://username:password@ip:554/Streaming/Channels/101)。

  2. 后端转码:使用 ffmpeg 将 RTSP 转换为 FLV 格式,并通过 WebSocket 推流。

  3. 前端播放:使用 flv.js 在 Vue3 中播放 WebSocket-FLV 视频流。

架构图如下:

海康摄像头(RTSP) → Node.js(FFmpeg转码+WebSocket) → 前端Vue3(FLV.js播放器)

二、后端实现(Node.js)

1. 安装依赖

npm init -y
npm install express ws

2. Node.js 转发服务

// server.ts
import express from "express";
import { WebSocketServer } from "ws";
import { spawn } from "child_process";const app = express();
const port = 3000;// WebSocket 服务
const wss = new WebSocketServer({ port: 9999 });wss.on("connection", (ws) => {console.log("客户端已连接");const rtspUrl ="rtsp://username:password@192.168.1.100:554/Streaming/Channels/101";// ffmpeg 拉流并输出 FLV 格式到 stdoutconst ffmpeg = spawn("ffmpeg", ["-rtsp_transport","tcp","-i",rtspUrl,"-f","flv","-an", // 不要音频"pipe:1", // 输出到 stdout]);ffmpeg.stdout.on("data", (chunk) => {ws.send(chunk);});ffmpeg.stderr.on("data", (err) => {console.error("FFmpeg 错误:", err.toString());});ws.on("close", () => {console.log("客户端断开连接");ffmpeg.kill("SIGINT");});
});app.listen(port, () => {console.log(`HTTP 服务已启动: http://localhost:${port}`);
});


运行:

ts-node server.ts

三、前端实现(Vue3 + TS)

1. 安装依赖

npm install flv.js

2. 创建播放器组件

<!-- CameraPlayer.vue -->
<template><div class="video-box"><videoref="videoRef"class="video"controlsautoplaymutedstyle="width: 100%; height: auto;"></video></div>
</template><script lang="ts" setup>
import { onMounted, ref, onBeforeUnmount } from "vue";
import flvjs from "flv.js";const videoRef = ref<HTMLVideoElement | null>(null);
let flvPlayer: flvjs.Player | null = null;onMounted(() => {if (flvjs.isSupported() && videoRef.value) {flvPlayer = flvjs.createPlayer({type: "flv",url: "ws://localhost:9999", // WebSocket 地址isLive: true,});flvPlayer.attachMediaElement(videoRef.value);flvPlayer.load();flvPlayer.play();}
});onBeforeUnmount(() => {if (flvPlayer) {flvPlayer.destroy();flvPlayer = null;}
});
</script>

四、常见问题

  1. 延迟高?

    • RTSP → FLV 转码存在几百毫秒到几秒延迟,可以调节 ffmpeg 参数(如 -tune zerolatency)。

    • 如果对实时性要求极高,可以考虑 WebRTC 方案。

  2. 卡顿/黑屏?

    • 检查摄像头 RTSP 地址是否正确。

    • 确保 Node.js 服务和前端在同一个网络下。

    • 增加 -rtsp_transport tcp 确保走 TCP。

  3. 浏览器兼容性?

    • flv.js 基于 MSE(Media Source Extensions),主流 Chrome/Edge 都支持。

    • Safari 不支持 FLV,苹果设备建议使用 HLS(m3u8)。


五、总结

本文介绍了如何用 Node.js + FFmpeg 将海康摄像头的 RTSP 流 转换为 WebSocket-FLV 流,并在 Vue3 + TypeScript 前端中通过 flv.js 播放。

这种方式实现成本较低,适合局域网监控、安防平台、物联网视频监控等场景。若对低延迟和移动端兼容性要求高,可以进一步升级到 WebRTC 方案。

FFmpeg 低延迟 RTSP → FLV 配置参数优化

在默认配置下,ffmpeg 从 RTSP 拉流再转码推送到前端会有 1~3 秒延迟。通过合理的参数调整,可以将延迟控制在 500ms 左右,甚至更低。

1. 基础命令

ffmpeg -rtsp_transport tcp -i rtsp://user:pass@192.168.1.100:554/Streaming/Channels/101 \-preset ultrafast \-tune zerolatency \-fflags nobuffer \-flags low_delay \-strict experimental \-an \-c:v libx264 \-f flv pipe:1

2. 参数说明(关键优化点)

  • -rtsp_transport tcp
    强制走 TCP,避免 UDP 丢包造成花屏。

  • -fflags nobuffer
    禁用缓冲,降低延迟。

  • -flags low_delay
    设置低延迟模式。

  • -preset ultrafast
    x264 编码速度最快的预设,降低延迟(代价是压缩率差一些,文件体积大)。

  • -tune zerolatency
    针对实时应用优化,禁用 B 帧,减少缓存。

  • -c:v libx264
    使用 H.264 编码(浏览器兼容性最好)。

    如果摄像头本身就是 H.264 编码,可以用 -c copy 直接拷贝,进一步减少延迟和 CPU 消耗。

  • -an
    去掉音频,减少带宽和处理压力。

  • -f flv
    输出为 FLV 格式,方便前端 flv.js 播放。

  • pipe:1
    把数据输出到标准输出(stdout),由 Node.js WebSocket 转发给前端。


3. Node.js 集成示例(优化版)

const ffmpeg = spawn("ffmpeg", ["-rtsp_transport", "tcp","-i", rtspUrl,"-preset", "ultrafast","-tune", "zerolatency","-fflags", "nobuffer","-flags", "low_delay","-an","-c:v", "libx264",   // 或 "-c", "copy" 直接拷贝"-f", "flv","pipe:1"
]);

4. 进一步优化方向

  1. CPU 占用太高?

    • 如果摄像头 RTSP 已经是 H.264 编码,建议用 -c copy(不转码),直接推送:

       

ffmpeg -rtsp_transport tcp -i rtsp://... -c copy -an -f flv pipe:1
  1. 延迟还是大?

    • 确保网络延迟低,避免跨公网。

    • 在前端 flv.js 设置 isLive: true,并控制 stashInitialSize(缓冲大小)。

  2. 兼容 Safari / iOS?

    • Safari 不支持 FLV,建议额外推一份 HLS (.m3u8) 流。


👉 这样配置后,一般延迟可以控制在 300ms~800ms,适合安防监控、实时预览等场景。

既然后端 ffmpeg 已经优化到低延迟模式,那前端 flv.js 也要做对应的参数调整,否则缓冲区过大就会拖慢播放。下面是一个 前端 flv.js 播放器低延迟模式配置示例。


前端 flv.js 播放器参数优化(低延迟模式)

1. 基础配置

在创建播放器时,flv.js.createPlayer 支持传入 config 对象,可以调整缓冲策略:

flvPlayer = flvjs.createPlayer({type: "flv",url: "ws://localhost:9999",isLive: true, // 必须开启直播模式},{enableWorker: true,            // 启用分离线程解码,降低卡顿enableStashBuffer: true,       // 是否启用缓冲区stashInitialSize: 128,         // 初始缓冲区大小,默认 384KB,调小可降低延迟fixAudioTimestampGap: false,   // 去掉音频时间戳修复,避免延迟autoCleanupSourceBuffer: true, // 自动清理 SourceBuffer,防止内存泄漏}
);

2. 参数解释

  • isLive: true
    表示是直播流,不允许拖拽和缓存太多。

  • enableWorker: true
    使用 Web Worker 解析流,避免主线程阻塞,提升性能。

  • enableStashBuffer: true
    开启缓冲池,防止因网络波动而花屏。

  • stashInitialSize: 128
    初始缓冲大小(KB),默认是 384KB,这会导致 1~3 秒延迟
    调小到 128KB(甚至 64KB)可以明显降低延迟,但网络不稳定时更容易卡顿。

  • fixAudioTimestampGap: false
    不修复音频时间戳(直播通常只关心实时性,禁用该特性可减少延迟)。

  • autoCleanupSourceBuffer: true
    当缓存过大时自动清理,避免内存占用过多。

<template><div class="video-box"><videoref="videoRef"class="video"controlsautoplaymutedstyle="width: 100%; height: auto;"></video></div>
</template><script lang="ts" setup>
import { onMounted, ref, onBeforeUnmount } from "vue";
import flvjs from "flv.js";const videoRef = ref<HTMLVideoElement | null>(null);
let flvPlayer: flvjs.Player | null = null;onMounted(() => {if (flvjs.isSupported() && videoRef.value) {flvPlayer = flvjs.createPlayer({type: "flv",url: "ws://localhost:9999", // WebSocket 地址isLive: true,},{enableWorker: true,enableStashBuffer: true,stashInitialSize: 128, // KB,调小减少延迟fixAudioTimestampGap: false,autoCleanupSourceBuffer: true,});flvPlayer.attachMediaElement(videoRef.value);flvPlayer.load();flvPlayer.play();}
});onBeforeUnmount(() => {if (flvPlayer) {flvPlayer.destroy();flvPlayer = null;}
});
</script>

4. 调优建议

  1. 超低延迟

    • stashInitialSize 设置为 64 或更小,延迟能控制在 300~500ms。

    • 但要注意:网络抖动大时可能卡顿。

  2. 平衡模式

    • stashInitialSize 维持 128~256,延迟在 500ms~1s,稳定性更好。

  3. 移动端兼容

    • iOS/Safari 不支持 flv.js,需要额外提供 HLS(m3u8)。


这样前后端都优化后,一般能做到 500ms 内延迟,满足大部分监控、实时视频预览场景。

http://www.dtcms.com/a/398677.html

相关文章:

  • 计算机视觉(opencv)练习——抠图(图像裁剪与轮廓提取)
  • 网站建设知识点的总结怎么做网站一个平台
  • 西安做网站的在网站后台设置wap模板目录
  • 软件行业|Parasoft与IAR的嵌入式DevOps测试集成
  • 设计模式-状态模式详解
  • 微信小程序通用弹窗组件封装与动画实现
  • 「日拱一码」099 数据处理——降维
  • 速通ACM省铜第十三天 赋源码(Watermelon)
  • 【C++进阶系列】:位图和布隆过滤器(附模拟实现的源码)
  • 洛阳网站建设建站系统怎么删除网站的死链
  • 山东省城乡建设厅网站wordpress academia
  • 广州番禺服装网站建设济南网站优化
  • 下载huggingface中数据集/模型
  • vue事件循环机制
  • 分布式专题——19 Zookeeper分布式一致性协议ZAB源码剖析
  • 前端核心框架vue之(组件篇2/5)
  • 【分布式】分布式事务方案:两阶段、TCC、SEATA
  • Kafka介绍
  • Netty 解码器 DelimiterBasedFrameDecoder
  • 位运算 常见方法总结 算法练习 C++
  • 电子商务平台网站源码国外炫网站
  • PTZ相机的知识体系
  • Nginx反向代理配置全流程实战:从环境搭建到HTTPS部署
  • HTTPS 能抓包吗?实战答案与逐步可行方案(HTTPS 抓包原理、证书Pinning双向认证应对、工具对比)
  • 对网站建设的讲话wordpress 自定义面板
  • 【23】C++实战篇——C++报错:LNK2001:无法解析的外部符号 ,LNK2019: 无法解析的外部符号,原因分析及解决方法
  • 东莞建设银行官方网站礼品网站制作
  • TiDB Cloud 可观测性最佳实践
  • python+springboot毕业季旅游一站式定制服务系统
  • docker 启用容器端口被占用报错500