当前位置: 首页 > news >正文

基于FFmpeg命令行的实时图像处理与RTSP推流解决方案

前言

在一些项目开发过程中需要将实时处理的图像再实时的将结果展示出来,此时如果再使用一张一张图片显示的方式展示给开发者,那么图像窗口的反复开关将会出现窗口闪烁的问题,实际上无法体现出动态画面的效果。因此,需要使用码流的方式来展示图像处理后的效果。

FFmpeg是一款开源且广泛使用的码流开发工具,其支持通过调用C库来实现码流处理软件,同时还支持通过调用命令行的方式实现码流相关的功能。FFmpeg由法国天才程序员Fabrice Bellard在2000年时开发初版,后于2004年找到接手人Michael Niedermayer维护到至今。FFmpeg提供了多种多媒体格式的封装和解封装,包括多种音频视频编码、多种协议的流媒体、多种色彩格式转换、多种采样率转换、多种码率转换等。当FFmpeg经过编译后可以获得可执行程序ffmpeg用于码流处理、可执行程序ffplay用于播放各种媒体文件或流、可执行程序ffprobe用于分析媒体文件或媒体流。

使用FFmpeg C库开发的问题

由于多年的发展FFmpeg的C库API在2016年6月26日发布的6.1.6版本后,一些关键API被弃用和替换。比如,弃用初始化API:av_register_all;替换解码、编码API:avcodec_decode_video2,avcodec_encode_video2替换为avcodec_send_frame,avcodec_receive_packet,avcodec_send_frame,avcodec_receive_packet;数据包管理:av_init_packet替换为av_packet_alloc,av_packet_free;以及编解码器上下文管理:av_malloc替换为avcodec_alloc_context3,avcodec_free_context。在学习使用过程中由于网络上的教程或购买的书籍中的内容不一致很容易陷入开发学习错误的陷阱。

假设开发者通过一段时间的学习,将所有需要使用的API区分开来并能够熟练编程。此时,开发者如果没有足够的码流相关的知识,那么又会陷入报错不知是什么原因的另一个陷阱中。在多媒体开发时需要了解视频抽象层(Network Abstraction Layer,NAL)和编码层(Video Coding Layer,VCL),且主要了解NAL。如果没有足够的知识,那么在FFmpeg在实现逻辑上的报错时可能就会束手无策。由图1所示,提示了使用了弃用的像素格式,但是却没有提示可以使用哪些像素格式,且使用格式AV_PIX_FMT_YUV420P能在头文件pixfmt.h中找到,还需要额外的手册说明哪些格式可以使用,学习难度陡峭。

图1 av_make_error_string报错

使用FFmpeg命令行开发实现

由于FFmpeg经过编译之后可以获得ffmpeg、ffplay和ffprobe可执行文件,通过命令行的方式即可实现各种码流处理功能。其中ffmpeg命令行支持的常用选项如下:

选项

参数

功能

-re

控制码流速度

-i

-

stdin标准输入

-i

多媒体文件

指定输入文件

-c:v和-c:a

编码类型

修改视频音频编码

-f

封装类型

修改封装

表1 ffmpeg命令行部分常用选项参数

当需要开发实时图像处理与推流经过处理后的图像为码流数据时,通过stdin的方式向ffmpeg的推流命令行进程中实时写入图像数据即可将码流推流至码流服务器(例用mediamtx作为RTSP码流服务器),如以下实现核心代码所示,在while(1)循环中持续读取图片文件写入ffmpeg进程的标准输入。

command_line = 'ffmpeg -loglevel error -re -framerate {} -i - -c:v libx264 -f rtsp {}'.format(1/frame_duration, RTSP_URL)

command_list = shlex.split(command_line)

process = subprocess.Popen(command_list, stdin=subprocess.PIPE, text=False)

while(1)

{

        with open(real_time_picture, 'rb') as f:

        process.stdin.write(f.read())

        process.stdin.flush()

        process.stdin.write('q\n'.encode())

        process.stdin.flush()

}

       在上述实现中,退出process进程需要输入字符q。通过查看FFmpeg的源代码也可以得知,在输入字符q之后,ffmpeg进程需要结束一些处理,同时有必要(ffmpeg保存媒体文件等)时还需要写入文件尾来结束ffmpeg进程处理。

图2 键盘输入q后完整退出ffmpeg进程

命令行ffmpeg也支持通过文件名模式,如pic_name%d.jpg作为选项-i的参数持续读取文件夹中的图片并推流。但是这种方式在进程运行之后就只能遍历完匹配文件名的图片并停止,如果ffmpeg边读取图片,同时修改图片会导致进程异常退出。而且,在windows系统下默认不支持多个进程同时访问修改一个文件。

总结

在需要实时获取图像处理结果的需求中,可以直接只用ffmpeg命令行的方式将实时处理的图片进行推流,通过播放码流的方式查看图片处理结果,并大幅度加速需求的开发进度,减少由于在FFmpeg的API学习中的开发投入。同时,建议使用标准输入的方式将实时处理的图片送入ffmpeg命令行进程和RTSP推流的方式将码流推送至码流服务器,高效利用标准输入的灵活性避免其他问题的出现。

相关文章:

  • 使用java代码注册onloyoffice账号 || 注册onloyoffice账号
  • vue中 vue.config.js反向代理
  • 计算机网络 | 应用层(3)-- 因特网中的电子邮件
  • 使用银行卡二要素API让支付更加安心
  • 北斗导航 | Transformer增强BiLSTM网络的GNSS伪距观测量误差探测
  • B. And It‘s Non-Zero
  • 提示词的神奇魔力——如何通过它改变AI的输出
  • 免费送源码:Java+ssm+HTML 三分糖——甜品店网站设计与实现 计算机毕业设计原创定制
  • springboot + mybatis 需要写 .xml吗
  • Java—— 五道算法水题
  • 力扣热题100题解(c++)—链表
  • 架构师备考-设计模式23种及其记忆特点
  • 【虚幻C++笔记】碰撞检测
  • 指标监控:Prometheus 结合 Grafana,监控redis、mysql、springboot程序等等
  • 一文详解Adobe Photoshop 2025安装教程
  • Springboot集成SSE实现消息推送+RabbitMQ解决集群环境下SSE通道跨节点事件推送问题
  • 【BBDM】main.py -- notes
  • CrewAI Community Version(二)——Agent
  • springboot入门-DTO数据传输层
  • 大模型的使用
  • 上海市市管干部任职前公示:赵亮拟为地区区长人选
  • 王一博赛车故障退赛冲上热搜,工作室回应:下次再战
  • 关键词看中国经济“一季报”:稳,开局良好看信心
  • 美联合健康集团高管枪杀案嫌疑人对谋杀指控不认罪
  • 全国首例!上市公司董监高未履行公开增持承诺,投资者起诉获赔
  • 华夏银行青岛分行另类处置不良债权,德州近百亩土地被神奇操作抵押贷款