网络摄像头通过rtsp协议拉流与本地保存

文章描述了如何使用Python和OpenCV4.9.0.80处理RTSP视频流,解决并发保存和实时播放时的错误,并实现每分钟自动保存最新视频的功能。同时,文中提到了视频分辨率调整和文件管理策略。
摘要由CSDN通过智能技术生成

环境

  • python 3.11.8
  • opencv-python == 4.9.0.80
  • numpy == 1.26.4

通过rtsp协议拉流

有一个问题就是如果要同时拉流保存与同时保存最近1分钟视频的需求,会触发一个问题。当写入视频的时候同时读取回抛错。目前是采取每10秒钟保存视频的方式保存。
而且有个采用opencv拼接视频效率并不高
如果是采用opencv读取视频后转存为另一部视频时在cv2.waitkey(1000 // 帧率),不然会出现另存的视频播放速度快的问题

import datetime
import math
import os

import cv2
import time

username = 'username'
password = 'password'
ip = '192.168.1.101'
# 显示的视频分辨率
show_width = 1600
show_height = 800
# 保存的视频分辨率
save_width = 1920
save_height = 1080
# 每个厂商的视频流地址不一定相同,示例使用的海康威视的摄像头
url = f'rtsp://{username}:{password}@{ip}/Stream2'
# url = f'rtsp://{username}:{password}@{ip}/Streaming/channels/1'
# 通过rtsp协议获取码流数据
cap = cv2.VideoCapture(url)
# 获取视频分辨率与帧率
old_width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
old_height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
old_fps = cap.get(cv2.CAP_PROP_FPS)
print(f'{old_width}@{old_height} {old_fps}')
# 设置视频保存的编码格式
fourcc = cv2.VideoWriter.fourcc(*'mp4v')
# 保存视频播放倍率
play_speed = 1.0
play_interval = int(round(1000 / old_fps * play_speed))
# 判断展示分辨率与保存分辨率
if show_width > old_width and show_height > old_height:
    show_width, show_height = old_width, old_height
if save_width > old_width and save_height > old_height:
    save_width, save_height = old_width, old_height

curr_time = datetime.datetime.now()
curr_time_minutes_fmt = curr_time.strftime('%Y%m%d%H%M')
curr_time_second = curr_time.second // 10
curr_time_second_fmt = curr_time.strftime(f'%Y%m%d%H%M{curr_time_second}')

last_time = curr_time - datetime.timedelta(minutes=1)
last_time_second_fmt = last_time.second // 10
last_time_fmt = last_time.strftime(f'%Y%m%d%H%M{last_time_second_fmt}')
video_field_path = os.path.join('./Video', ip, curr_time_minutes_fmt)
if not os.path.exists(video_field_path):
    os.mkdir(video_field_path)
video_file_path = os.path.join(video_field_path, f'{curr_time_second_fmt}@{int(old_fps)}.mp4')
out_frame = cv2.VideoWriter(video_file_path, fourcc, math.floor(old_fps), (int(save_width), int(save_height)))

while True:
    curr_time = datetime.datetime.now()
    pre_time = curr_time - datetime.timedelta(minutes=1)
    pre_time_second_fmt = pre_time.second // 10
    pre_time_fmt = pre_time.strftime(f'%Y%m%d%H%M{pre_time_second_fmt}')
    # 按每分钟去保存数据
    if last_time_fmt != pre_time_fmt:
        curr_time_second_fmt = curr_time.second // 10
        curr_time_minutes_fmt = curr_time.strftime(f'%Y%m%d%H%M')
        curr_time_fmt = curr_time.strftime(f'%Y%m%d%H%M{curr_time_second_fmt}')
        print(curr_time_fmt, pre_time_fmt, last_time_fmt)
        out_frame.release()
        last_time_fmt = pre_time_fmt
        video_field_path = os.path.join('./Video', ip, curr_time_minutes_fmt)
        if not os.path.exists(video_field_path):
            os.mkdir(video_field_path)
        video_file_path = os.path.join(video_field_path, f'{curr_time_fmt}@{int(old_fps)}.mp4')
        out_frame = cv2.VideoWriter(video_file_path, fourcc, math.floor(old_fps),
                                    (int(save_width), int(save_height)))
    list_dir = os.listdir(os.path.join('./Video', ip))
    if len(list_dir) > 10:
        datetime_video = list(filter(lambda x: str(x).isdigit(), list_dir))
        first_video_dir = list(sorted(datetime_video, key=lambda x: int(str(x))))[0]
        remove_video_dir = os.path.join('./Video', ip, first_video_dir)
        print(remove_video_dir)
        for video_file in os.listdir(remove_video_dir):
            video_file_path = os.path.join(remove_video_dir, video_file)
            os.remove(video_file_path)
        os.rmdir(remove_video_dir)
    ret, frame = cap.read()
    if not ret:
        break
    save_img = cv2.resize(frame, (int(save_width), int(save_height)))
    show_img = cv2.resize(frame, (int(show_width), int(show_height)))
    out_frame.write(save_img)
    cv2.imshow('hk_video', show_img)
    current_time = time.time()
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cv2.destroyAllWindows()
cap.release()
out_frame.release()
  • 13
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值