简体   繁体   中英

How to start and stop saving video frames according to a trigger with OpenCV VideoWriter

I am building an app that records frames from IP camera through RTSP.

My engine is in charge to save a video in mp4 with Opencv VideoWriter working well. What I am looking for is to create a startRecord and a stopRecord class method that will respectively start and stop recording according to a trigger (it could be an argument that I pass to the thread). Is anyone know what the best way to do that kind of stuff?

Here is my class:

from threading import Thread
import cv2
import time
import multiprocessing
import threading
class RTSPVideoWriterObject(object):
    def __init__(self, src=0):
        # Create a VideoCapture object
        self.capture = cv2.VideoCapture(src)

        # 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 endRecord(self):
        self.capture.release()
        self.output_video.release()
        exit(1)

    def startRecord(self,endRec):

        self.frame_width = int(self.capture.get(3))
        self.frame_height = int(self.capture.get(4))
        self.codec = cv2.VideoWriter_fourcc(*'mp4v')
        self.output_video = cv2.VideoWriter('fileOutput.mp4', self.codec, 30, (self.frame_width, self.frame_height))
        while True:          
            try:
                self.output_video.write(self.frame)
                if endRec:
                    self.endRecord()
            except AttributeError:
                pass




if __name__ == '__main__':

    rtsp_stream_link = 'rtsp://foo:192.5545....'
    video_stream_widget = RTSPVideoWriterObject(rtsp_stream_link)

    stop_threads = False
    t1 = threading.Thread(target = video_stream_widget.startRecord, args =[stop_threads]) 
    t1.start() 
    time.sleep(15)
    stop_threads = True

As you can see in the main I reading frames and store them in a separate thread. Then I am starting to record (record method is with an infinite loop so blocking) and then after 15 sec, I am trying to pass a 'stop_record' argument to stop recording properly.

A part of the code comes from Storing RTSP stream as video file with OpenCV VideoWriter

Is someone have an idea? I read a lot that OpenCV can be very tricky for multithreading

N.

Instead of passing arguments to the thread, use a internal flag in the class to determine when to start/stop recording. The trigger could be as simple as pressing the spacebar to start/stop recording. When the spacebar is pressed it will switch an internal variable, say self.record to True to start recording and False to stop recording. Specifically, to check when the spacebar is pressed, you can check if the returned key value from cv2.waitKey() is 32 . If you want the trigger based on any other key, take a look at this post to determine the key code. Here's a quick example to start/stop recording a video using the spacebar:

from threading import Thread
import cv2

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

        # 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(*'mp4v')
        self.output_video = cv2.VideoWriter('output.mp4', 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)
            if self.record:
                self.save_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)
        # Press spacebar to start/stop recording
        elif key == 32:
            if self.record:
                self.record = False
                print('Stop recording')
            else:
                self.record = True
                print('Start recording')

    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()
        except AttributeError:
            pass

我通过在类中创建一个全局变量来解决这个问题,对于你的案例 endRec。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM