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

录制RTSP流时如何正确设置fps_mode为cfr参数?

问题:JavaCV实现RTSP转HLS并固定恒定帧率(CFR)

已通过FFmpeg命令实现可变帧率RTSP流转恒定帧率HLS,命令如下:

ffmpeg -use_wallclock_as_timestamps 1 -rtsp_transport tcp -i <rtsp-url> -fps_mode cfr -vf "fps=8.0" -max_delay 0 -f hls -fflags nobuffer -fflags flush_packets -vcodec libx264 -hls_flags program_date_time+split_by_time+append_list -hls_list_size 0 -hls_time 5 <output-file>

现尝试用JavaCV(版本:javacv 1.5.9、javacpp 1.5.9、ffmpeg 6.0-1.5.9)实现相同功能,但在FrameGrabber和FrameRecorder中设置fps_mode=cfr均未生效,求正确配置方法。

原JavaCV代码片段:

// FrameGrabber creation
FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber(streamURL);
frameGrabber.setOption("timeout", timeout);
frameGrabber.setOption("rtsp_transport", rtspTransportProtocol);
frameGrabber.setOption("loglevel", "debug");
frameGrabber.setOption("fflags", "nobuffer");
frameGrabber.setOption("use_wallclock_as_timestamps", "1");
frameGrabber.setOption("fps_mode", "cfr");
// frameGrabber.setOption("vsync", "1");
frameGrabber.setFormat("rtsp");
frameGrabber.setTimeout(3 * 1000000);
frameGrabber.start();

//FrameRecorder creation
FFmpegFrameRecorder hlsRecorder = new FFmpegFrameRecorder(outputFile, frameWidth, frameHeight, audioChannel);
hlsRecorder.setInterleaved(true);
hlsRecorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
hlsRecorder.setFrameRate(frameGrabber.getFrameRate());
hlsRecorder.setFormat("hls");
hlsRecorder.setGopSize(gopSize);
hlsRecorder.setOption("hls_flags", "program_date_time+split_by_time+append_list");
hlsRecorder.setOption("hls_list_size", "0"); // This option sets the playlist to an infinite size
hlsRecorder.setOption("hls_time", "5"); // This option sets the duration of each segment
// hlsRecorder.setVideoOption("fps_mode", "cfr");
// hlsRecorder.setVideoOption("vsync", "1");
hlsRecorder.start();

解决方案

核心配置要点

  1. fps_mode=cfr是视频编码器专属选项,需通过setVideoOption而非全局setOption配置在FrameRecorder上
  2. 必须添加fps滤镜实现帧率转换,对应FFmpeg命令的-vf "fps=8.0"
  3. 明确设置目标帧率,而非复用原流的可变帧率
  4. 补充原命令中缺失的max_delay、flush_packets等选项

修正后的完整代码

// FrameGrabber creation
FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber(streamURL);
frameGrabber.setOption("timeout", timeout);
frameGrabber.setOption("rtsp_transport", rtspTransportProtocol);
frameGrabber.setOption("loglevel", "debug");
frameGrabber.setOption("fflags", "nobuffer");
frameGrabber.setOption("use_wallclock_as_timestamps", "1");
frameGrabber.setOption("max_delay", "0"); // 对应FFmpeg的-max_delay 0
frameGrabber.setFormat("rtsp");
frameGrabber.setTimeout(3 * 1000000);
frameGrabber.start();

//FrameRecorder creation
FFmpegFrameRecorder hlsRecorder = new FFmpegFrameRecorder(outputFile, frameWidth, frameHeight, audioChannel);
hlsRecorder.setInterleaved(true);
hlsRecorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
hlsRecorder.setFrameRate(8.0); // 直接设置目标恒定帧率
hlsRecorder.setFormat("hls");
hlsRecorder.setGopSize(gopSize);

// 添加帧率转换滤镜,等价于FFmpeg的-vf "fps=8.0"
hlsRecorder.setVideoFilter("fps=8.0");
// 配置CFR模式相关的编码器选项
hlsRecorder.setVideoOption("fps_mode", "cfr");
hlsRecorder.setVideoOption("vsync", "1");

// HLS相关配置
hlsRecorder.setOption("hls_flags", "program_date_time+split_by_time+append_list");
hlsRecorder.setOption("hls_list_size", "0");
hlsRecorder.setOption("hls_time", "5");
hlsRecorder.setOption("fflags", "flush_packets"); // 对应FFmpeg的-fflags flush_packets

hlsRecorder.start();

关键说明

  • setVideoFilter("fps=8.0"):强制将可变帧率流转换为固定8fps,是实现恒定帧率的核心步骤
  • setVideoOption("fps_mode", "cfr"):告诉编码器以恒定帧率模式输出,配合vsync=1确保帧同步逻辑正确
  • setFrameRate(8.0):明确告知编码器输出的目标帧率,避免复用原流的可变帧率参数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 09:26:08