1 year ago
#363661
Chorum
How to record original Webcam Stream while displaying it
I would like to record a Webcamstream while displaying it in a Frame. (Later record up to 3 Streams and/or capturing a Frame with MQTT Data.)
I found a really nice Class for it and changed it for my needs. Thats the actual Class:
class multi_thread_stream:
def __init__(self, ready=None):
self.ready = ready
self.cap = cv2.VideoCapture(cam1fullurl)
self.capr = cv2.VideoCapture(cam1fullurl)
self.frame = {}
self.t1 = threading.Thread(target=self.capture_stream)
self.t2 = threading.Thread(target=self.display_image)
self.t1.name = 'capture_thread'
self.t2.name = 'display_thread'
self.t1.start()
self.t2.start()
threadpoolc1.append(self.t1)
threadpoolc1.append(self.t2)
global rec_mp4_key
def setpicnostream_for_class(self):
print('setpicnostream_for_class activated')
global picnostream
global videoframe
global videolabel1
global left_frame
img = Image.open(r'C:\Users\User\Python\Medien\Bilder\streamoff.png')
x = left_frame.winfo_width()
y = left_frame.winfo_height()
img = img.resize((x,y), Image.ANTIALIAS)
picnostream = ImageTk.PhotoImage(img)
label2.config(font=("Courier bold", 20),image = picnostream)
def end(self):
self.t1.exit()
self.t2.exit()
def capture_stream(self):
global streamactivekey
global screenshot
global rec_mp4_key
global cam1fullurl
if streamactivekey == 'True':
while True:
#if rec_mp4_key == 'False':
self.ret, self.frame = self.cap.read()
# self.capr = self.frame
# break
global readed_frame
readed_frame = self.frame
self.ready.set()
if cv2.waitKey(1) & 0xFF == ord('q'):
break
if streamactivekey == 'False':
print('streamactivekey in capture_stream =',streamactivekey)
self.setpicnostream_for_class()
self.cap.release()
sys.exit()
break
def display_image(self):
global rec_mp4_key
global rec_stop
print('display_image activated')
self.counter = 0
self.counterold = 0
self.old = 0
if streamactivekey == 'True':
time.sleep(0.1)
while True:
"""
if rec_mp4_key == 'True':
out = cv2.VideoWriter(filenamev, get_video_type(filenamev), frames_per_seconds, get_dims(capr, res=start_res))
rec_start = 'True'
"""
self.ready.wait()
fwidth = left_frame.winfo_width()
fheight = left_frame.winfo_height()
frootx = left_frame.winfo_rootx()
frooty = left_frame.winfo_rooty()
global picnostreamsize
picnostreamsize = (frootx, frooty)
size = (fwidth, fheight)
framex=cv2.cvtColor(self.frame,cv2.COLOR_BGR2RGB)
cv2imageresized = cv2.resize(framex,size, interpolation = cv2.INTER_AREA)
now = datetime.now()
offset = 30
font = cv2.FONT_HERSHEY_TRIPLEX
bottomLeftCornerOfText = (50,offset)
upperRightCornerOfText = (710,offset)
fontScale = 1
fontColor = (255,0,0)
thickness = 2
lineType = 2
rawtime = now.strftime("%H : %M : %S : %f")
mytime = rawtime[:-4]
rawtime2 = now.strftime("%S")
rawtimex = int(now.strftime("%S"))
seconds = "0"+str(rawtimex)
if seconds == "31" or seconds == "01":
seconds = "0"
else:
seconds = "0"+str(rawtimex)
if rawtimex > 9:
seconds = rawtime2[:]
if seconds == self.old:
self.counter += 1
else:
print(f'Frame/Second = {self.counter}/{seconds}')
fpsstring = f'FPS : {self.counter}'
self.counter = 0
self.old = seconds
frame = cv2.putText(cv2imageresized,fpsstring, upperRightCornerOfText, font, fontScale,fontColor,thickness,cv2.LINE_AA)
#frame = cv2.putText(cv2imageresized,fpsstring, bottomLeftCornerOfText, font, fontScale,fontColor,thickness,lineType)
#frame = cv2.putText(cv2imageresized,fpsstring, upperRightCornerOfText, font, fontScale,fontColor,thickness,cv2.LINE_AA)
#print(f'display_imagetime = {counter}---{seconds}-{rawtime}')
#print(f'Frame/Second = {counter}/{seconds}')
framex=Image.fromarray(cv2imageresized)
framex=ImageTk.PhotoImage(framex)
"""
if rec_mp4_key == 'True' and rec_start == 'True':
print('rec_mp4_key in display :',rec_mp4_key)
#out.write(self.frame)
cv2.imshow("In write Frame", self.frame)
if rec_stop == 'True':
print('rec_stop =',rec_stop)
rec_mp4_key = 'False'
capr.release()
"""
label2.configure(image=framex)
label2.image=framex
self.ready.clear()
if cv2.waitKey(1) & 0xFF == ord('q'):
break;
if streamactivekey == 'False':
print('streamactivekey in display_image =',streamactivekey)
sys.exit()
break
def record_stream(self):
capr = self.capr
global cam1fullurl
global rec_mp4_key
global rec_stop
basepathinc = r'C:/Videotool/Videos'
frames_per_seconds = 24.0
start_res = '720p'
def change_rec_resolution(capr,width,height):
capr.set(3, width)
capr.set(4, height)
resolutions = {
"480p": (640,480),
"720p": (1280,720),
"1080p": (1920,1080),
"4k": (3840,2160),
}
def get_dims(capr, res='1080p'):
width, height = resolutions['480p']
if res in resolutions:
width, height = resolutions[res]
change_rec_resolution(capr, width, height)
return width, height
VIDEO_TYPE = {
'avi': cv2.VideoWriter_fourcc(*'mp4v'),
'mp4': cv2.VideoWriter_fourcc(*'mp4v'),
#'mp4': cv2.VideoWriter_fourcc(*'H264'),
}
print('Aufnahme')
isExist = os.path.exists(basepathinc)
print('path exists :',isExist)
print('Video fullpath :',basepathinc)
if not isExist:
os.makedirs(basepathinc)
print(f'path {basepathinc} created')
os.chdir(basepathinc)
now = datetime.now()
rawtime = now.strftime("%H_%M_%S_%f")
mytime = rawtime[:-4]
filenamev='record'+mytime+'.mp4'
print(filenamev)
def get_video_type(filenamev):
filenamev, ext = os.path.splitext(filenamev)
if ext in VIDEO_TYPE:
return VIDEO_TYPE[ext]
return VIDEO_TYPE['avi']
rec_start = 'False'
if streamactivekey == 'True':
time.sleep(0.1)
self.ready.wait()
if rec_mp4_key == 'True':
out = cv2.VideoWriter(filenamev, get_video_type(filenamev), frames_per_seconds, get_dims(capr, res=start_res))
rec_start = 'True'
while True:
if rec_mp4_key == 'True' and rec_start == 'True':
print('rec_mp4_key in display :',rec_mp4_key)
#out.write(self.frame)
cv2.imshow("In write Frame", self.frame)
self.ready.clear()
if rec_stop == 'True':
print('rec_stop =',rec_stop)
rec_mp4_key = 'False'
capr.release()
def __del__(self):
self.cap.release()
cv2.destroyAllWindows()
Sorry for the Comments and may be bad Coding, I am new in Python. May be there are not needed Lines left in the Code...
The Capture and the Displaying are working in different Threads and Threadpools, because of the I/O Blocking. For Displaying, everything is fine. I would be happy for some more FPS but its ok.
But my attempts to write the Stream to a File while displaying the Stream, are not working.
For Testing i use a simple imshow()
The posted Code let the displayed Stream run with normal FPS, but the imshow() Window pops up in Gray and dont respond anymore.
May be its a Problem to access the Stream 2 Times ?
The strange thing is, that the Line :
out = cv2.VideoWriter(filenamev, get_video_type(filenamev), frames_per_seconds, get_dims(capr, res=start_res))
is writing a full named mp4 File with 1kb size. (Nothing in it)
That should not happen. out.write(self.frame)
should do that later.
I would be happy, if Someone could help me with my Problem.
Here are the Start and Stop Functions:
def stop_rec():
print('stop_rec activated')
global rec_mp4_key
global rec_stop
rec_stop = 'True'
def start_rec():
print('start_rec activated')
global rec_mp4_key
rec_mp4_key = 'True'
global rec_stop
rec_stop = 'False'
global mts
t3 = threading.Thread(target=mts.record_stream)
t3.name = 'record thread'
t3.start()
threadpoolcamrecord.append(t3)
python
multithreading
opencv
webcam
0 Answers
Your Answer