NodeJS+Angular通过FFmpeg实现摄像头RTSP流的配置问题
解决WebSocket传摄像头帧转RTSP流的FFmpeg配置问题
核心问题分析
从报错信息可定位两个关键问题:
- 输入格式不匹配:你配置FFmpeg接收
rawvideo格式,但Angular发送的是JPEG压缩的Base64数据,导致FFmpeg计算的预期原始帧大小(6404803=921600)和实际接收的压缩数据大小(76343)不匹配,触发Invalid buffer size错误。 - 无RTSP接收服务器:FFmpeg仅负责编码推流,本身不提供RTSP服务,你指定的
rtsp://127.0.0.1:554/rtsp/stream没有对应服务器监听,导致连接被拒绝。
修复步骤
1. 启动RTSP接收服务器
先部署轻量RTSP服务器,推荐rtsp-simple-server:
# 安装(通过Go模块,也可直接下载预编译二进制) go install github.com/aler9/rtsp-simple-server@latest # 启动服务器 rtsp-simple-server
默认监听8554端口,推流地址为rtsp://localhost:8554/stream。
2. 修正FFmpeg参数与NodeJS逻辑
关键调整:
- 将FFmpeg输入格式从
rawvideo改为image2pipe,适配JPEG帧流输入 - 移除
-pixel_format rgb24,JPEG输入无需指定原始像素格式 - 仅在WebSocket连接建立时启动一次FFmpeg进程(原逻辑每帧重启进程,无法形成连续流)
- 避免过早关闭FFmpeg的stdin(
ffmpeg.stdin.end()会终止输入导致流中断)
修改后的NodeJS代码:
const { spawn } = require('child_process'); const { v4: uuidv4 } = require('uuid'); exports.stream = (ws, req) => { try { const mess = `connection from: ${req._remoteAddress} at ${req._startTime}.`; const initialMess = `Started ${mess}`; ws.uuid = uuidv4(); console.log(initialMess); let ffmpeg = null; let streamConfig = null; ws.on('message', function incoming(message) { message = JSON.parse(message); // 首次收到消息时初始化FFmpeg进程 if (!ffmpeg) { streamConfig = { width: message.width, height: message.height, framerate: message.framerate || 30 // 兜底帧率为30 }; console.log(`Stream config: ${streamConfig.width} x ${streamConfig.height} @ ${streamConfig.framerate}fps`); ffmpeg = spawn('ffmpeg', [ '-f', 'image2pipe', // 适配JPEG帧流输入 '-framerate', `${streamConfig.framerate}`, '-i', '-', // 从stdin读取数据 '-codec:v', 'libx264', '-preset', 'ultrafast', '-tune', 'zerolatency', '-pix_fmt', 'yuv420p', // 兼容VLC等多数播放器 '-f', 'rtsp', '-rtsp_transport', 'tcp', // 强制TCP传输,降低丢包概率 'rtsp://localhost:8554/stream' // 指向rtsp-simple-server地址 ]); // 监听FFmpeg错误输出 ffmpeg.stderr.on('data', (data) => { console.error(`FFmpeg: ${data.toString()}`); }); // FFmpeg进程退出时关闭WebSocket ffmpeg.on('exit', (code, signal) => { console.log(`FFmpeg process exited with code ${code} and signal ${signal}`); ws.close(); }); } // 解码Base64 JPEG数据并写入FFmpeg stdin const base64Data = message.video.replace(/^data:image\/jpeg;base64,/, ''); // 移除Base64前缀 const videoData = Buffer.from(base64Data, 'base64'); ffmpeg.stdin.write(videoData); }); ws.on('close', () => { const finalMess = `Stopped ${mess}`; rem(ws.uuid); // 假设rem是你定义的资源清理函数 console.log(finalMess); // 关闭FFmpeg进程 if (ffmpeg) { ffmpeg.stdin.end(); ffmpeg.kill(); } }); } catch (err) { console.error(err); } };
3. 调整Angular端帧率参数
确保framerate传递的是实际帧率值(如30),而非间隔除数:
const fps = 30; // 对应每~33ms发送一帧 socket.send(JSON.stringify({ video: this.canvas.toDataURL('image/jpeg'), width: this.canvas.width, height: this.canvas.height, framerate: fps }));
验证流程
- 启动
rtsp-simple-server - 启动NodeJS服务器
- 运行Angular应用,建立WebSocket连接并发送摄像头帧
- 打开VLC,输入地址
rtsp://localhost:8554/stream即可播放RTSP流
内容的提问来源于stack exchange,提问作者Ridweng
相关产品推荐
相关产品推荐

