There are several implementation issues:
- As far
"output.mp4v"
is not a valid mp4
file extension in the current context.
Change the file name to "output.mp4"
"MP4V"
is case sensitive and suppposed to be "mp4v"
.
- As gerda commented, the frame size may not be 1920x1080.
- The
else:
, break
at the end of the loop may break the loop after one frame.
cv2.waitKey
is not working without using cv2.imshow
(without an open windows).
The loop is not terminated when q
is pressed.
The code may never reach to out.release()
.
Based on the following post, I tried to create a portable code that waits for Esc key, without root privilege in Linux.
The solution I found (waiting for Esc) seem a bit complicated... You may try other solutions.
Code sample:
import cv2
import numpy as np
import pyautogui
import time
from threading import Thread
from pynput.keyboard import Key, Listener
esc_key_pressed = False # Global variable.
# Wait for Esc key to be pressed (and released).
def wait_for_esc_key():
global esc_key_pressed
# Collect events until released https://stackoverflow.com/questions/24072790/how-to-detect-key-presses
with Listener(on_press=None, on_release=lambda key: (False if key == Key.esc else True)) as listener:
listener.join()
esc_key_pressed = True
SCREEN_SIZE = (1920, 1080)
fourcc = cv2.VideoWriter_fourcc(*"mp4v")
out = cv2.VideoWriter("output.mp4", fourcc, 20.0, (SCREEN_SIZE))
fps = 120
prev = 0
print('================= ScreenRecording Started =================')
print('Press Esc to end recording')
# Wait for Esc key in a thread (non-blocking wait).
wait_for_esc_key_thread = Thread(target=wait_for_esc_key)
wait_for_esc_key_thread.start()
#while True:
while (not esc_key_pressed):
time_elapsed = time.time() - prev
img = pyautogui.screenshot()
if time_elapsed > 1.0/fps:
prev = time.time()
frame = np.array(img)
if (frame.shape[0] != SCREEN_SIZE[1]) or (frame.shape[1] != SCREEN_SIZE[0]):
frame = cv2.resize(frame, SCREEN_SIZE) # Resize frame if size is not SCREEN_SIZE
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
out.write(frame)
#if cv2.waitKey(100) & 0xFF == ord('q'):
# break
time.sleep(0.001)
#cv2.destroyAllWindows()
out.release()