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博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/901534.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【GIT】放弃”本地更改,恢复到远程仓库的状态git fetch origin git reset --hard origin/分支名

如果你想完全放弃本地更改&#xff0c;恢复到远程仓库的状态&#xff0c;可以按照以下步骤操作&#xff1a; 获取远程最新版本 首先执行&#xff1a; git fetch origin这条命令会把远程仓库的最新提交拉取到你的本地&#xff0c;但不会自动合并到你的当前分支。 硬重置你的当前…

flutter doctor 信号号超时

报错如下&#xff1a; :\Users\Administrator>flutter doctor Doctor summary (to see all details, run flutter doctor -v): [√] Flutter (Channel stable, 3.27.4, on Microsoft Windows [版本 10.0.22631.5189], locale zh-CN) [√] Windows Version (Installed versi…

【Linux】系统入门

【Linux】系统初识 起源开源 闭源版本内核内核编号 Linux的安装双系统(不推荐)WindowsLinuxvmware虚拟机vitualbox操作系统的镜像centos 7/ubuntu云服务器租用 Linux的操作lsmkdir 文件名pwdadduser userdel -rrm文件名cat /proc/cpuinfolinux支持编程vim code.c./a.out 运行程…

mybatis-plus整合springboot与使用方式

注解 TableField(exist false)&#xff1a;表示该属性不为数据库表字段&#xff0c;但又是必须使用的。 整合springboot pom <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xs…

[第十六届蓝桥杯 JavaB 组] 真题 + 经验分享

A&#xff1a;逃离高塔(AC) 这题就是简单的签到题&#xff0c;按照题意枚举即可。需要注意的是不要忘记用long&#xff0c;用int的话会爆。 &#x1f4d6; 代码示例&#xff1a; import java.io.*; import java.util.*; public class Main {public static PrintWriter pr ne…

GPU服务器声音很响可以怎么处理

当GPU服务器运行时噪音过大&#xff0c;通常是由于高负载下散热风扇高速运转所致。以下是分步骤的解决方案&#xff0c;帮助您有效降低噪音并保持设备稳定运行&#xff1a; 一、排查噪音来源 定位声源 • 使用 声级计 或手机分贝检测APP&#xff0c;确定最大噪音位置&#xff0…

STM32平衡车开发实战教程:从零基础到项目精通

STM32平衡车开发实战教程&#xff1a;从零基础到项目精通 一、项目概述与基本原理 1.1 平衡车工作原理 平衡车是一种基于倒立摆原理的两轮自平衡小车&#xff0c;其核心控制原理类似于人类保持平衡的过程。当人站立不稳时&#xff0c;会通过腿部肌肉的快速调整来维持平衡。平…

C#设计模式-状态模式

状态模式案例解析&#xff1a;三态循环灯的实现 案例概述 本案例使用 状态模式&#xff08;State Pattern&#xff09; 实现了一个 三态循环灯 的功能。每点击一次按钮&#xff0c;灯的状态会按顺序切换&#xff08;状态1 → 状态2 → 状态3 → 状态1...&#xff09;&#xff…

Mac系统升级node.js版本和npm版本并安装pnpm

1.升级node.js版本 第一步&#xff1a;查询当前node.js版本 node -v第二步&#xff1a;清除node.js的缓存 sudo npm cache clean -f第三步&#xff1a;验证缓存是否清空 npm cache verify第四步&#xff1a;安装n工具&#xff0c;n工具是专门用于管理node.js版本的工具 su…

[net 5] udp_dict_server 基于udp的简单字典翻译(服务器与业务相分离)

目录 1. 功能了解 1.1. 啥是 dic_server? 1.2. dic_server 的小目标 2. 基本框架 2.1. 基本文件框架 2.2. 业务与服务器解耦 -> 回调函数 3. 字典 3.1. 字典配置文件 3.2. 构建字典类 3.2.1. 字典类的基本成员 3.2.2. 字典类构造 3.2.2.1. 构造 3.2.2.2. 信息加…

七种驱动器综合对比——《器件手册--驱动器》

九、驱动器 名称 功能与作用 工作原理 优势 应用 隔离式栅极驱动器 隔离式栅极驱动器用于控制功率晶体管&#xff08;如MOSFET、IGBT、SiC或GaN等&#xff09;的开关&#xff0c;其核心功能是将控制信号从低压侧传输到高压侧的功率器件栅极&#xff0c;同时在输入和输出之…

EM储能网关ZWS智慧储能云应用(8) — 电站差异化支持

面对不同项目、种类繁多的储能产品&#xff0c;如何在储能云平台上进行电站差异化支持尤为关键&#xff0c;ZWS智慧储能云从多方面支持储能电站差异化。 简介 随着行业发展&#xff0c;市场“内卷”之下&#xff0c;各大储能企业推陈出新的速度加快。面对不同项目、种类繁多…

图像预处理-色彩空间补充,灰度化与二值化

一.图像色彩空间转换 1.1 HSV颜色空间 HSV颜色空间使用色调&#xff08;Hue&#xff09;、饱和度&#xff08;Saturation&#xff09;和亮度&#xff08;Value&#xff09;三个参数来表示颜色 一般对颜色空间的图像进行有效处理都是在HSV空间进行的&#xff0c;然后对于基本…

Midnight Flag CTF 2025

周末还是三个比赛&#xff0c;可惜不好弄。不是远端连不上就是远端打不开。再有就是太难了。 Crypto ABC 这个题还是不算难的。给了两个30位数的平方和&#xff0c;并且pu1*baser0,qu2*baser1其中r 都很小&#xff0c;可以copper。 只是sage里的two_squres不管用&#xff0…

深度学习--激活函数

激活函数通过计算加权和并加上偏置来确定神经元是否应该倍激活&#xff0c;它们将输入信号转换为输出的可微运算。大多数激活函数都是非线性的&#xff0c;由于激活函数是深度学习的基础&#xff0c;下面简要介绍一些常见的激活函数。 1 RelU函数 最受欢迎的激活函数是修正线性…

深入解析 OrdinalEncoder 与 OneHotEncoder:核心区别与实战应用

标题&#xff1a;深入解析 OrdinalEncoder 与 OneHotEncoder&#xff1a;核心区别与实战应用 摘要&#xff1a; 本文详细探讨了机器学习中类别特征编码的两种核心方法——OrdinalEncoder 和 OneHotEncoder。通过对比两者的功能、特点、适用场景及代码实现&#xff0c;帮助读者…

CTF web入门之命令执行 完整版

web29 文件名过滤 由于flag被过滤,需要进行文件名绕过,有以下几种方法: 1.通配符绕过 fla?.* 2.反斜杠绕过 fl\ag.php 3.双引号绕过 fl’‘ag’.php 还有特殊变量$1、内联执行等 此外 读取文件利用cat函数,输出利用system、passthru 、echo echo `nl flag.php`; ec…

【Linux实践系列】:用c/c++制作一个简易的进程池

&#x1f525; 本文专栏&#xff1a;Linux Linux实践项目 &#x1f338;作者主页&#xff1a;努力努力再努力wz &#x1f4aa; 今日博客励志语录&#xff1a; 人生没有标准答案&#xff0c;你的错题本也能写成传奇。 ★★★ 本文前置知识&#xff1a; 匿名管道 1.前置知识回顾…

2.2 函数返回值

1.回顾def def sum(x,y): return xy res sum(10,20) #调用函数 print(res) 2.函数的三个重要属性 -函数的类型&#xff1a;function -函数的ID&#xff1a;16进制的整数数值 -函数的值&#xff1a;封装在函数中的数据和代码 # - 函数是一块内存空间&#xff0c;通过…

【3GPP核心网】【5G】精讲5G网络语音业务系统架构

1. 欢迎大家订阅和关注,精讲3GPP通信协议(2G/3G/4G/5G/IMS)知识点,专栏会持续更新中.....敬请期待! 目录 1. 音视频业务 2. 消息类业务 SMS over IMS SMS over NAS 3. 互联互通架构 3.1 音视频业务互通场景 3.2 5G 用户与 5G 用户互通 3.3 5G 用户与 4G 用户的互通…