[英]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.我正在构建一个通过 RTSP 记录来自 IP 摄像机的帧的应用程序。
My engine is in charge to save a video in mp4 with Opencv VideoWriter working well.我的引擎负责将视频保存在 mp4 中,Opencv VideoWriter 运行良好。 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).
我正在寻找的是创建一个 startRecord 和一个 stopRecord 类方法,它们将根据触发器分别开始和停止记录(它可能是我传递给线程的参数)。 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.正如您在主 I 阅读框架中看到的那样,并将它们存储在一个单独的线程中。 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.
然后我开始记录(记录方法是无限循环,因此阻塞),然后在 15 秒后,我试图传递一个“stop_record”参数以正确停止记录。
A part of the code comes from Storing RTSP stream as video file with OpenCV VideoWriter部分代码来自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
我读了很多 OpenCV 对于多线程来说可能非常棘手
N. 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.当按下空格键时,它会切换一个内部变量,将
self.record
设为True
以开始录制,设为False
以停止录制。 Specifically, to check when the spacebar is pressed, you can check if the returned key value from cv2.waitKey()
is 32
.具体来说,要检查何时按下空格键,您可以检查
cv2.waitKey()
返回的键值是否为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。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.