欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > ffmpeg实现视频流抽帧

ffmpeg实现视频流抽帧

2025/4/19 17:27:13 来源:https://blog.csdn.net/qq_54088234/article/details/147239507  浏览:    关键词:ffmpeg实现视频流抽帧

ffmpeg 实现视频流抽帧

抽取实时视频帧

如果你的实时视频是通过 RTSP、UDP 或其他协议获取的,可以直接调用 FFmpeg 命令来抽取帧。

ffmpeg 命令

示例 1

ffmpeg -i rtsp://your_rtsp_stream_url -vf fps=1 -update 1 output.jpg

说明:

  • -i rtsp://your_rtsp_stream_url:指定输入的实时视频流 URL。
  • -vf fps=1:使用视频滤镜,每秒抽取 1 帧(可根据需要调整帧率,例如 fps=1/5 表示每 5 秒抽取一帧)。
  • -update 1 output.jpg:参数 -update 1 表示不断用最新的帧更新同一个输出文件(output.jpg),适合用于监控场景;如果需要保存多张图片,则可以使用类似 output_%04d.jpg 的命名格式保存为连续文件。

示例 2

ffmpeg -i "rtmp://ns8.indexforce.com/home/mystream" -vf fps=1 "frame_%03d.jpg"

说明:

  • -i "rtsp://your_rtsp_stream_url":指定 RTSP 视频流的 URL。
  • -vf fps=1:设置帧率,每秒抽取一帧。您可以根据需要调整此值,例如 fps=1/5 表示每 5 秒抽取一帧。
  • "frame_%03d.jpg":指定输出的图像文件名,%03d 表示编号,生成的文件名将依次为 frame_001.jpgframe_002.jpg 等。

示例 3

ffmpeg -i "rtmp://ns8.indexforce.com/home/mystream" -ss 1 -frames:v 1 "C:\Users\26913\Videos\ffmpeg-img\frame.jpg"

说明:

  • 从指定的 RTSP 流中读取数据,并只输出一帧图像,保存到 C:\Users\26913\Videos\ffmpeg-img 目录下,文件名为 frame.jpg
  • -ss 1:表示设置时间偏移量为 1 秒。也就是说,从视频的第 1 秒处开始处理。对于抽帧来说,FFmpeg 会在视频的 1 秒处截取当前帧。
    • 不加这个参数的话,会获取视频开头的第一帧。
    • 若视频流开头是黑屏或加载帧,可能会影响抓取效果。
    • 效率较低,因为 FFmpeg 需要解析部分流的关键帧来决定输出。

代码示例

引入依赖

        <!-- 集成javacv --><dependency><groupId>org.bytedeco</groupId><artifactId>javacv-platform</artifactId><version>1.5.11</version></dependency><!-- 集成ffmpeg:https://mvnrepository.com/artifact/org.bytedeco/ffmpeg --><dependency><groupId>org.bytedeco</groupId><artifactId>ffmpeg</artifactId><version>7.1-1.5.11</version></dependency>

1、javacv 写法

public class LiveStreamFrameExtractor {private static final Logger log = LoggerFactory.getLogger(LiveStreamFrameExtractor.class);/*** javacv实时抓取视频帧*/public static void main(String[] args) {String streamUrl = VideoConstant.RTSP_URL_2;String outputDirPath = VideoConstant.FRAME_FILE_PREFIX;File outputDir = new File(outputDirPath);if (!outputDir.exists()) {outputDir.mkdirs();}// 使用 try-with-resources 自动管理资源try (FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(streamUrl);Java2DFrameConverter converter = new Java2DFrameConverter()) {// 启动抓取器,开始实时视频读取grabber.start();int frameCount = 0;Frame frame;// 无限循环抓取实时视频帧while ((frame = grabber.grabImage()) != null) {// 可根据需要添加实时显示、处理等操作BufferedImage image = converter.convert(frame);if (image != null) {// 构造图片输出路径,例如 live_frame_0001.jpgString outputFileName = outputDirPath + File.separator + String.format("live_frame_%04d.jpg", frameCount);File outputFile = new File(outputFileName);ImageIO.write(image, "jpg", outputFile);System.out.println("保存帧:" + frameCount + " 到文件:" + outputFileName);}frameCount++;// 根据抓取帧率或其他需求设置适当延时,避免过快抽帧TimeUnit.MILLISECONDS.sleep(50);if (frameCount > 5) {break;}}System.out.println("抓取结束,共抓取 " + frameCount + " 帧");// 停止抓取器grabber.stop();} catch (Exception e) {log.error("抓取视频帧出错:", e);}}
}

2、ffmpeg 命令写法

@Slf4j
public class FfmpegProcess {static String rtspUrl = VideoConstant.RTSP_URL_1;static String streamOutputFile = VideoConstant.FRAME_FILE_PREFIX + File.separator + DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss") + ".jpg";public static void main(String[] args) throws Exception {String command = getStreamFrameExtractionCommand(rtspUrl, streamOutputFile);System.out.println("执行命令: " + command);// 创建操作系统进程ProcessBuilder builder = new ProcessBuilder();// 执行命令executeCommand(builder, command, "windows");// 合并标准输出和标准错误输出流builder.redirectErrorStream(true);Process process = builder.start();// 异步读取输出流,避免阻塞CompletableFuture<Void> future = readOutputAsync(process.getInputStream());int exitCode = process.waitFor();if (exitCode == 0) {System.out.println("执行成功");} else {System.err.println("执行过程中出现错误,退出代码:" + exitCode);}}/*** 获取实时视频流抽帧的命令(只抓取一张图片)** @param url        视频流 url,例如 rtsp 流地址* @param outputFile 输出文件路径* @return 实时视频流抽帧的命令*/private static String getStreamFrameExtractionCommand(String url, String outputFile) {return String.format("%s -y -i %s -ss 1 -frames:v 1 %s", VideoConstant.FFMPEG_PATH, url, outputFile);}/*** 异步读取 ffmpeg 输出流*/private static CompletableFuture<Void> readOutputAsync(InputStream inputStream) {return CompletableFuture.runAsync(() -> {try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {String line;while ((line = reader.readLine()) != null) {System.out.println(line);}} catch (IOException e) {log.error("读取 ffmpeg 输出流异常", e);}});}/*** 执行命令** @param builder 进程构建器* @param command 命令* @param osType  操作系统类型*/private static void executeCommand(ProcessBuilder builder, String command, String osType) {switch (osType) {case "windows":builder.command("cmd", "/c", command);break;case "Linux":case "macOS":builder.command("bash", "-c", command);break;default:throw new RuntimeException("不支持的操作系统类型");}}
}

学习参考

  • https://blog.csdn.net/asialee_bird/article/details/129014872?utm_source=chatgpt.com
  • 公共有效rtmp、rtsp、m3u8、音频视频测试地址(2025.1.23更新)_公开的rtsp流媒体地址-CSDN博客

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词