Files
QSfera/Desktop/test/gui/helpers/ScreenRecorder.py
T
Курнат Андрей 2315f25754 Initial QSfera import
2026-06-07 10:20:04 +03:00

83 lines
2.1 KiB
Python

import os
import re
import threading
import time
import mss
import numpy as np
import imageio_ffmpeg
from datetime import datetime
from helpers.ConfigHelper import get_config
_recording_thread = None
_stop_event = threading.Event()
_video_path = None
def _build_video_path(scenario):
safe_name = re.sub(r"[^a-zA-Z0-9_]", "_", scenario.name)
timestamp = datetime.now().strftime("%d-%b-%Y_%H-%M-%S")
recordings_dir = os.path.join(get_config("guiTestReportDir"), "recordings")
os.makedirs(recordings_dir, exist_ok=True)
return os.path.join(recordings_dir, f"{safe_name}_{timestamp}.mp4")
def _record_loop(video_path):
with mss.mss() as sct:
monitor = sct.monitors[0]
width, height = monitor["width"], monitor["height"]
writer = imageio_ffmpeg.write_frames(
video_path,
size=(width, height),
fps=24,
codec="libx264",
output_params=["-crf", "23", "-pix_fmt", "yuv420p"],
)
writer.send(None)
interval = 1.0 / 24 # 1/24 seconds between each frame so we get 24 frames per second
next_frame_at = time.monotonic()
while not _stop_event.is_set():
frame = sct.grab(monitor)
# mss gives BGRA — drop alpha, flip B and R channels to get RGB
rgb = np.flip(np.array(frame)[:, :, :3], axis=2).tobytes()
writer.send(rgb)
next_frame_at += interval
sleep_for = next_frame_at - time.monotonic()
if sleep_for > 0:
time.sleep(sleep_for)
writer.close()
def start_recording(scenario):
global _recording_thread, _video_path
_video_path = _build_video_path(scenario)
_stop_event.clear()
_recording_thread = threading.Thread(target=_record_loop, args=(_video_path,), daemon=True)
_recording_thread.start()
def stop_recording(passed):
global _recording_thread, _video_path
if _recording_thread is None:
return
_stop_event.set()
_recording_thread.join()
_recording_thread = None
if passed and os.path.exists(_video_path):
os.remove(_video_path)
_video_path = None