问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

使用GStreamer管道和OpenCV实现自定义码率视频录制

创作时间:
作者:
@小白创作中心

使用GStreamer管道和OpenCV实现自定义码率视频录制

引用
CSDN
1.
https://blog.csdn.net/csdnn345/article/details/144559225

本文介绍如何使用GStreamer管道读取摄像头RTSP流,并实现自定义码率的视频录制。通过结合OpenCV和GStreamer,可以有效控制视频体积,适用于需要长时间录制和存储视频的场景。

一、背景

在成功编译出GStreamer支持的OpenCV后,本文将介绍如何使用GStreamer管道读取摄像头RTSP流,同时实现自定义码率的视频录制,有效控制视频体积。

二、代码及参数说明

1. 代码

import cv2

# 使用GStreamer管道
gst_str = (
    'appsrc ! videoconvert ! x264enc bitrate=2000 speed-preset=ultrafast ! '
    'video/x-h264,profile=baseline ! h264parse ! mp4mux ! filesink location=output.mp4'
)

# 打开摄像头,此处rtsp为摄像头的RTSP流地址
cap = cv2.VideoCapture(rtsp)

# 获取视频帧宽度和高度
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

# 创建VideoWriter对象
out = cv2.VideoWriter(gst_str, cv2.CAP_GSTREAMER, 0, 30, (frame_width, frame_height), True)

while cap.isOpened():
    ret, frame = cap.read()
    if ret:
        # 写入帧到视频文件
        out.write(frame)
        
        # 显示帧
        cv2.imshow('frame', frame)
        
        # 按q键退出
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    else:
        break

# 释放资源
cap.release()
out.release()
cv2.destroyAllWindows()

代码很简单,下面着重说明部分参数的含义:

2. 参数说明

(1)gst_str

  • appsrc:GStreamer元素,用于从应用程序中接收数据。它将OpenCV捕获的帧输入到GStreamer管道中;
  • videoconvert:GStreamer元素,用于视频格式转换。它确保输入的视频帧格式与编码器兼容;
  • x264enc:使用x264编码器对视频进行编码;
  • bitrate=2000:设置视频编码的比特率为2000 kbps(2 Mbps);
  • speed-preset=ultrafast:编码速度预设为"ultrafast",以最快速度进行编码,通常会产生较大的文件;
  • video/x-h264:表示使用H.264视频格式;
  • profile=baseline:指定编码配置文件为baseline,适用于低延迟和低复杂度的应用场景;
  • h264parse:GStreamer元素,用于解析H.264码流。它确保H.264码流格式正确,适合后续处理;
  • mp4mux:GStreamer元素,用于将视频流封装成MP4格式;
  • filesink:GStreamer元素,用于将数据写入文件;
  • location=output.mp4:指定输出文件的位置和名称。

(2)speed-preset

在GStreamer的x264enc元素中,speed-preset选项用于控制编码速度与压缩效率之间的权衡,它影响编码器的复杂度和生成文件的大小。以下是speed-preset的其他可用设置:

  • ultrafast:极快,编码速度最快,但压缩效率最低,文件体积最大。
  • superfast:非常快,编码速度很快,压缩效率较低。
  • veryfast:很快,编码速度快,压缩效率一般。
  • faster:较快,编码速度较快,压缩效率稍高。
  • fast:快,编码速度与压缩效率的平衡点。
  • medium:中等,默认设置,压缩效率较高,但编码速度较慢。
  • slow:慢,编码速度慢,压缩效率更高。
  • slower:较慢,编码速度更慢,压缩效率更高。
  • veryslow:很慢,编码速度最慢,压缩效率最高。
  • placebo:极慢,编码速度极慢,压缩效率最高(一般不建议使用)。

实测下来使用superfast或者veryfast并没有比ultrafast的视频体积小,反而更大了。使用ultrafast录制10分钟720p@25fps,码率5000kbps的视频,体积在270MB左右(虽然还是有点大,但比之前好多了),使用superfast或者veryfast录制,体积反而大了50MB,不知道是不是因为有啥参数设置的不对。

(3)cv2.VideoWriter

  • gst_str:GStreamer管道字符串,定义了视频处理和保存的整个流程;
  • cv2.CAP_GSTREAMER:指定OpenCV使用GStreamer作为视频捕获和处理后端;
  • 0:通常用于指定四字符编码(FourCC),但在使用GStreamer时不需要,所以设置为0。

上面介绍的只是代码中用到的一些参数,还有一大堆参数没有用到,可能如果再配合其它参数还能进一步优化视频体积,这个就慢慢学习吧。

三、问题

1. 编码器比较

为了进一步比较,也在不使用GStreamer的情况下仅使用h264编码(ffmpeg后端)录制视频,编码方式需要设置为"avc1"。

fourcc = cv2.VideoWriter_fourcc(*'avc1')
out = cv2.VideoWriter(dst, fourcc, fps, frame_size)

实测使用avc1编码方式录制的视频体积比mp4v编码格式小,但问题在于没法控制码率。此外cv2.VideoWriter_fourcc()还可以设置h264/x264编码器,应该也是指定h264编码格式,但运行会报错:

表示h264字节码并不被支持,自动替换成了avc1。问题在于opencv默认使用ffmpeg框架来处理视频,但是ffmpeg并没有h264解码器。消除报错的一种方法是使用cisco开源的openh264,另一种方法是将mp4格式改为mkv。但只是消除报错,依然没法控制码率。

2. x264enc不可用

初次运行时报错:

[WARN:0@1.277] global cap_gstreamer.cpp:2436 open OpenCV | GStreamer warning: error opening writer pipeline: no element "x264enc"

这个警告表明,OpenCV通过GStreamer尝试使用x264enc编码器时找不到相应的GStreamer元素。x264enc是GStreamer中的H.264编码器元素,如果GStreamer没有安装该插件或配置不正确,就会导致该错误。

解决方案:

首先查看x264enc是否可用

不可用,然后:

安装GStreamer插件

sudo apt install gstreamer1.0-libav gstreamer1.0-plugins-bad gstreamer1.0-plugins-good gstreamer1.0-plugins-base

安装x264编码器

sudo apt-get install x264

安装完整的GStreamer插件

sudo apt-get install gstreamer1.0-plugins-good gstreamer1.0-plugins-ugly

三步下来,再次查看x264enc是否可用,依然显示不可用,在内心即将崩溃的时候,试着重新运行了一遍程序,居然可以了,也不知道是哪一步起作用了。

四、总结

通过GStreamer和OpenCV的结合,可以实现自定义码率的视频录制,这对于需要长时间录制和存储视频的场景非常重要。此外,GStreamer还可以用来做低延迟的视频推流拉流,这可能也是后续工作要用到的需求,看来GStreamer的学习之路才刚刚开始。

参考资料

[1] x264参数配置-preset_x264enc speed-preset=ultrafast-CSDN博客
[2] [VideoWriter]保存H264/MPEG4格式MP4视频—visionguide

[3] OpenCV保存H264视频的问题-CSDN博客
[4] OpenCV: FFMPEG: tag 0x34363268/'h264' is not supported with codec—stackoverflow

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号