You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NodeJS+Angular通过FFmpeg实现摄像头RTSP流的配置问题

解决WebSocket传摄像头帧转RTSP流的FFmpeg配置问题

核心问题分析

从报错信息可定位两个关键问题:

  1. 输入格式不匹配:你配置FFmpeg接收rawvideo格式,但Angular发送的是JPEG压缩的Base64数据,导致FFmpeg计算的预期原始帧大小(6404803=921600)和实际接收的压缩数据大小(76343)不匹配,触发Invalid buffer size错误。
  2. 无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
}));

验证流程

  1. 启动rtsp-simple-server
  2. 启动NodeJS服务器
  3. 运行Angular应用,建立WebSocket连接并发送摄像头帧
  4. 打开VLC,输入地址rtsp://localhost:8554/stream即可播放RTSP流

内容的提问来源于stack exchange,提问作者Ridweng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 09:59:55