These advertisements help me to keep writing articles on this website

Record a Qt window (screencast) with pyside

Here you find example code for a Qt app that uses pyside6 and imageio to record the active window and save it as an mp4 file.

Here is a screencast of the result. I type some text in the window, close the app and open the mp4 file in Preview:

screencast

And here is how to do it:

Create a virtual environment and install packages

python3 -m venv env
source env/bin/activate
pip install pyside6
pip install imageio
pip install imageio-ffmpeg      

Create main.py

Create main.py and paste this code:

import sys
import imageio
import numpy as np
from PIL import Image
from PySide6.QtWidgets import QApplication
from PySide6.QtWidgets import QMainWindow
from PySide6.QtWidgets import QLabel
from PySide6.QtWidgets import QWidget
from PySide6.QtWidgets import QLineEdit
from PySide6.QtCore import Qt
from PySide6.QtGui import QPixmap
from PySide6.QtCore import QSize
from PySide6.QtCore import QTimer
from __feature__ import snake_case, true_property


class VideoWriter(QTimer):
    fps = 24

    def __init__(self, widget, filepath):
        super().__init__()
        self.widget = widget
        self.writer = imageio.get_writer(filepath, format="mp4", mode="I", fps=self.fps)
        self.timeout.connect(self.append_frame)

    def render_pixmap(self):
        size = QSize(self.widget.size.width() * 2, self.widget.size.height() * 2)
        pixmap = QPixmap(size)
        pixmap.set_device_pixel_ratio(2)
        self.widget.render(pixmap)
        return pixmap

    def start_recording(self):
        self.start(1000 / self.fps)

    def append_frame(self):
        pixmap = self.render_pixmap()
        bytes = pixmap.to_image().bits().tobytes()
        size = pixmap.size()
        w = size.width()
        h = size.height()
        array = np.frombuffer(bytes, dtype=np.uint8).reshape(h, w, 4)
        self.writer.append_data(np.asarray(np.roll(array, 1)))

    def dispose(self):
        self.stop()
        self.writer.close()


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.window_title = "INPUT"
        self.size = QSize(200, 152)
        self.lineedit = QLineEdit()
        self.lineedit.set_parent(self)
        self.lineedit.set_focus()
        self.set_central_widget(self.lineedit)
        self.style_sheet = "border-style: none; padding: 8px; color:#fff; background-color: #f00"

app = QApplication(sys.argv)
mainwindow = MainWindow()
mainwindow.show()
video_writer = VideoWriter(mainwindow, "screencast.mp4")
video_writer.start_recording()

app.exec_()
video_writer.dispose()
Written by Loek van den Ouweland on March 21, 2021. Questions regarding this artice? You can send them to the address below.
By using this site, you acknowledge that you have read and understand our Cookie and Privacy Policy.