使用 OpenCV VideoWriter 将 RTSP 流存储为视频文件 [英] Storing RTSP stream as video file with OpenCV VideoWriter

查看:116
本文介绍了使用 OpenCV VideoWriter 将 RTSP 流存储为视频文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 OpenCV 开发 Python 模块,该模块连接到 RTSP 流以对视频执行一些预处理(主要是降低 fps 和分辨率),然后将其存储在文件系统中.

但是,即使在尝试了几种编解码器后,寻找类似的发展......我总是以一个空的视频结束.我见过这个其他线程(

from threading import Thread导入 cv2类 RTSPVideoWriterObject(object):def __init__(self, src=0):# 创建一个 VideoCapture 对象self.capture = cv2.VideoCapture(src)# 获取帧的默认分辨率(取决于系统)self.frame_width = int(self.capture.get(3))self.frame_height = int(self.capture.get(4))# 设置编解码器和输出视频设置self.codec = cv2.VideoWriter_fourcc('M','J','P','G')self.output_video = cv2.VideoWriter('output.avi', self.codec, 30, (self.frame_width, self.frame_height))# 启动线程从视频流中读取帧self.thread = Thread(target=self.update, args=())self.thread.daemon = 真self.thread.start()定义更新(自我):# 从不同线程的流中读取下一帧而真:如果 self.capture.isOpened():(self.status, self.frame) = self.capture.read()def show_frame(self):# 在主程序中显示帧如果 self.status:cv2.imshow('frame', self.frame)# 按键盘上的 Q 停止录音键 = cv2.waitKey(1)如果键 == ord('q'):self.capture.release()self.output_video.release()cv2.destroyAllWindows()退出(1)def save_frame(self):# 将获得的帧保存到视频输出文件中self.output_video.write(self.frame)如果 __name__ == '__main__':rtsp_stream_link = '你的流链接!'video_stream_widget = RTSPVideoWriterObject(rtsp_stream_link)而真:尝试:video_stream_widget.show_frame()video_stream_widget.save_frame()除了属性错误:经过

I'm developing a Python module, with OpenCV, that connects to an RTSP stream to perform some preprocessing on the video (mostly, reducing fps and resolution), and then store it in the file system.

But, even after trying several codecs, looking for similar developments... I always end up with an empty video. I've seen this other thread (cv::VideoWriter yields unreadable video), which may be similar, but was developed on C++.

Has anyone worked on this? I normally use a sample RTSP stream as reference, such as rtsp://freja.hiof.no:1935/rtplive/definst/hessdalen03.stream, and can receive and even watch the stream from VLC correctly.

I've seen quite a lot of threads discussing how to capture video from an RTSP stream, or how to work with VideoWriters and VideoReaders classes and video files, but almost nothing combining the two.

Any help would be highly appreciated :) Thanks!!


Edit 1: Sample code used to store the frames.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import cv2
import numpy

# Test frame.
width, height = 400, 300
width_2, height_2 = int(width / 2), int(height / 2)
frame = numpy.zeros((height, width, 3), numpy.uint8)
cv2.rectangle(frame, (0, 0), (width_2, height_2), (255, 0, 0), cv2.FILLED)
cv2.rectangle(frame, (width_2, height_2), (width, height), (0, 255, 0), cv2.FILLED)

frames = [frame for _ in range(100)]
fps = 25

# Define the codec.
#fourcc = cv2.VideoWriter_fourcc(*'X264')
#fourcc = cv2.VideoWriter_fourcc(*'XVID')
fourcc = cv2.VideoWriter_fourcc(*'MJPG')

# Create VideoWriter object
out = cv2.VideoWriter(filename='video.avi',
                      fourcc=fourcc,
                      apiPreference=cv2.CAP_FFMPEG,
                      fps=float(fps),
                      frameSize=(width, height),
                      isColor=True)

result = 0
for frame in frames:
    result += 0 if out.write(frame) is None else 1
print(result)

out.release()

Edit 2: Solution

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import cv2
import numpy

# Test frame.
width, height = 400, 300
width_2, height_2 = int(width / 2), int(height / 2)

frame1 = numpy.zeros((height, width, 3), numpy.uint8)
cv2.rectangle(frame1, (0, 0), (width_2, height_2), (255, 0, 0), cv2.FILLED)
cv2.rectangle(frame1, (width_2, height_2), (width, height), (0, 255, 0), cv2.FILLED)
cv2.imwrite('frame1.jpg', frame1)

frame2 = numpy.zeros((height, width, 3), numpy.uint8)
cv2.rectangle(frame2, (width_2, 0), (width, height_2), (255, 0, 0), cv2.FILLED)
cv2.rectangle(frame2, (0, height_2), (width_2, height), (0, 255, 0), cv2.FILLED)
cv2.imwrite('frame2.jpg', frame2)

range1 = [frame1 for _ in range(10)]
range2 = [frame2 for _ in range(10)]
frames = range1 + range2 + range1 + range2 + range1
fps = 2

# Define the codec.
fourcc = cv2.VideoWriter_fourcc(*'MJPG')

# Create VideoWriter object
out = cv2.VideoWriter('video.avi', fourcc, float(fps), (width, height))

for frame in frames:
    out.write(frame)

out.release()

解决方案

Here's a RTSP stream to video widget. I would recommend creating another thread for obtaining the frames as cv2.VideoCapture.read() is blocking. This can be expensive and cause latency as the main thread has to wait until it has obtained a frame. By putting this operation into a separate thread that just focuses on grabbing frames and processing/saving the frames in the main thread, it dramatically improves performance. You also can experiment with other codecs but using MJPG should be safe since its built into OpenCV. I used my IP camera stream and saved the frames to output.avi. Be sure to change rtsp_stream_link to your own RTSP stream link. :)

from threading import Thread
import cv2

class RTSPVideoWriterObject(object):
    def __init__(self, src=0):
        # Create a VideoCapture object
        self.capture = cv2.VideoCapture(src)

        # Default resolutions of the frame are obtained (system dependent)
        self.frame_width = int(self.capture.get(3))
        self.frame_height = int(self.capture.get(4))

        # Set up codec and output video settings
        self.codec = cv2.VideoWriter_fourcc('M','J','P','G')
        self.output_video = cv2.VideoWriter('output.avi', self.codec, 30, (self.frame_width, self.frame_height))

        # Start the thread to read frames from the video stream
        self.thread = Thread(target=self.update, args=())
        self.thread.daemon = True
        self.thread.start()

    def update(self):
        # Read the next frame from the stream in a different thread
        while True:
            if self.capture.isOpened():
                (self.status, self.frame) = self.capture.read()

    def show_frame(self):
        # Display frames in main program
        if self.status:
            cv2.imshow('frame', self.frame)

        # Press Q on keyboard to stop recording
        key = cv2.waitKey(1)
        if key == ord('q'):
            self.capture.release()
            self.output_video.release()
            cv2.destroyAllWindows()
            exit(1)

    def save_frame(self):
        # Save obtained frame into video output file
        self.output_video.write(self.frame)

if __name__ == '__main__':
    rtsp_stream_link = 'your stream link!'
    video_stream_widget = RTSPVideoWriterObject(rtsp_stream_link)
    while True:
        try:
            video_stream_widget.show_frame()
            video_stream_widget.save_frame()
        except AttributeError:
            pass

这篇关于使用 OpenCV VideoWriter 将 RTSP 流存储为视频文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆