Node调用ffmpeg管道推RTMP流延迟高、画面模糊优化咨询
实现思路
- Node.js 获取图片的 base64 数据
- 通过 ffmpeg 管道向 RTMP 服务推流
实现代码
const child_process = require('child_process') let child = child_process.spawn('ffmpeg', [ '-f', 'image2pipe', '-i', '-', '-vcodec', 'libx264', '-f', 'flv', 'rtmp://127.0.0.1:56413/live/test' ]); child.stdout.on('data', function (data) { console.log(data.toString()); }); child.stderr.on('data', function (data) { console.log(data.toString()); }); child.on('close', (code, signal) => { console.log('ffmpeg', code, signal); }); // 图片写入管道方法 function writeImg (base64) { let imgData = Buffer.from(base64, 'base64') child.stdin.write(imgData) } // 模拟循环获取图片数据 for (let i = 0; i < 100; i ++) { writeImg('/9j/4AAQSkZJRgABAQAA........') }
遇到的问题
- 画面延迟过高
- 画面模糊
优化方案
画面延迟过高优化
- 补全ffmpeg低延迟编码参数,替换原有libx264相关配置:输入侧提前指定帧率,参数放在
-i -之前,帧率数值和实际生成图片的频率完全匹配,比如每秒生成25帧就加-framerate 25;编码侧添加-tune zerolatency关闭x264前瞻缓存、-bf 0禁用B帧(B帧需要依赖前后帧编码,会引入固定延迟)、-preset ultrafast优先保证编码速度;输出侧添加-probesize 32 -analyzeduration 0减少格式探测等待时间、-flvflags no_duration_filesize关闭flv头信息预计算、-muxdelay 0将封装延迟设为0。 - 修复代码写入逻辑缺陷:现有模拟代码直接循环一次性写入100张图片,没有做帧率控制,数据会大量堆积在管道缓冲区,推流时间越长延迟越高。需要按设置的帧率定时写入图片,比如25帧场景下每40ms写入1张,和ffmpeg的处理节奏对齐,不要无节制向stdin灌入数据。
- 合理设置编码缓冲区:添加
-bufsize 1M参数(数值可根据码率调整,和单秒码率数值保持一致即可),避免编码器缓存过多待发送帧。
画面模糊优化
- 明确指定编码画质参数:现有参数没有设置码率和画质阈值,ffmpeg会用默认低码率编码,自然会出现模糊问题。可以添加
-crf 21参数(数值范围0-51,数值越小画质越好,18-23是肉眼无明显损失的常用区间);如果用固定码率模式,720p分辨率建议设置码率-b:v 2M,1080p分辨率建议设置码率-b:v 4M,可根据实际清晰度需求上下调整。 - 平衡编码速度和画质:如果用
ultrafast预设觉得画质损失过多,可以换成-preset veryfast,编码速度下降幅度很小,同码率下画质会有明显提升。 - 如果输入图片分辨率和推流输出分辨率不一致,添加
-sws_flags lanczos参数,用更高质量的缩放算法处理画面,避免缩放操作导致的画面发虚。 - 提前检查输入源质量,确保传入的base64图片本身没有经过过度压缩,不要传入分辨率过低、压缩痕迹明显的源图。
内容的提问来源于stack exchange,提问作者Yohann
相关产品推荐
相关产品推荐

