简介
目前RTSP拉流是网络摄像头获取图片数据常用的方法,但通过CPU软解码的方式不仅延时高且十分占用资源,本文提供了一种从网络摄像头RTSP硬解码的拉流的方法,并且提供python代码以便从网络摄像头获取图片进行后续算法处理。
下载ffmpeg
Ffmpeg下载链接。建议下载稳定版本。
图1
这里会出现三个版本:
- essentials:必要的组件,东西可能不全。
- full:全面的,里面的库文件比较全。
- shared:有动态链接库。
通过版本号命名的为稳定版,日期命名的为最新版。仅是使用的话essentials即可,Qt等调库需要选择shared。
图2
图3
复制如图所示的bin文件地址,设置环境变量。
右击此电脑打开属性
图4
图5
图6
图7
按照图4~7将复制的bin文件环境变量路径添加进去。
测试FFmpeg
运行命令
ffmpeg -version
显示以上信息则安装完成。
ffplay拉流显示
ffplay rtsp://XXXXXXX/stream
使用ffplay即可拉流成功,但是为软解码,拉流延时较高。
使用ffmpeg硬解码并保存视频
首先查看支持的硬件
ffmpeg -hwaccels
如果是nvidia的显卡并安装的对应驱动,也安装了cuda,则可以使用cuda跟h_264cuvid 解码器
查看可用的对应格式解码器
ffmpeg -codecs | findstr "h264"
红色框中为可用解码器。
利用硬件解码器的命令如下,以h264_cuvid为例:
ffmpeg -hwaccel cuda -vcodec h264_cuvid -i rtsp://admin:qwer1234@192.0.0.64/h264/ch1/main/av_stream output.mp4
-hwaccel 选择硬件模式
-vcodec 选择解码器
-i RTSP地址
output.mp4 保存成.mp4视频
note:硬解码器必须与硬件环境对应如:cuda 对应 h264_cuvid
测量延时
测量延时方法
- 将网络摄像头对准手机计时器
- 把手机靠近播放视频的电脑屏幕
- 同时拍摄手机与电脑屏幕显示的计时器,可计算毫秒级延时 。
具体如下面的图片所示。
利用ffplay拉流时延时
延时时间:7580 – 6130 = 1450ms
此时采用CPU软解,故延时较高。
利用ffmpeg硬解码拉流时延时
延时时间:3390 – 2680 = 710ms
可见硬解码降低了RTSP延时。
查看任务管理器的GPU界面栏
双击红色区域放大GPU显示
当Video Decode出现波动时代表调用了硬件解码器。
python调用ffmpeg转成opencv的mat格式并显示
首先安装ffmpeg-python、opencv-python、Numpy
pip install ffmpeg-python
pip install opencv-python
pip install numpy
此时还需要环境中安装了Cuda。
Cuda安装网络资源很多,在此不做赘述。
Code
import cv2
import ffmpeg
import numpy as np
# RTSP 流地址
rtsp_url = "rtsp://admin:qwer1234@192.0.0.64/h264/ch1/main/av_stream"
# 创建 FFmpeg 进程
probe = ffmpeg.probe(rtsp_url)
video_info = next(stream for stream in probe['streams'] if stream['codec_type'] == 'video')
width = video_info['width']
height = video_info['height']
ffmpeg_cmd = (
ffmpeg
.input(rtsp_url, hwaccel='cuda', vcodec='h264_cuvid')
.output('pipe:', format='rawvideo',pix_fmt='bgr24')
.run_async(pipe_stdout=True)
)
# 读取并显示视频帧
while True:
in_bytes = ffmpeg_cmd.stdout.read(width * height * 3)
if not in_bytes:
break
frame = (
np
.frombuffer(in_bytes, np.uint8)
.reshape([height, width, 3])
)
cv2.imshow('RTSP Stream (GPU)', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
ffmpeg_cmd.wait()
cv2.destroyAllWindows()
上述Code即可通过python调用ffmpeg并且能够与opencv交互,能为后续开发图像算法做一个前端。