en un clic
pyqt-multimedia
// PyQt/PySide multimedia - audio playback, video playback, camera, audio recording, media player
// PyQt/PySide multimedia - audio playback, video playback, camera, audio recording, media player
| name | pyqt-multimedia |
| description | PyQt/PySide multimedia - audio playback, video playback, camera, audio recording, media player |
| metadata | {"author":"mte90","version":"1.0.0","tags":["python","qt","pyqt","multimedia","audio","video","camera","media"]} |
Audio and video playback, camera capture, and media processing in PyQt/PySide.
Qt Multimedia provides classes for audio, video, and camera functionality:
from PyQt6.QtMultimedia import QMediaPlayer, QAudioOutput
from PyQt6.QtWidgets import QApplication, QPushButton, QVBoxLayout, QWidget, QSlider, QLabel
from PyQt6.QtCore import Qt, QUrl
import sys
class AudioPlayer(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Audio Player")
self.player = QMediaPlayer()
self.audio_output = QAudioOutput()
self.player.setAudioOutput(self.audio_output)
# UI
self.play_btn = QPushButton("Play")
self.pause_btn = QPushButton("Pause")
self.stop_btn = QPushButton("Stop")
self.label = QLabel("No file loaded")
self.volume_slider = QSlider(Qt.Orientation.Horizontal)
self.volume_slider.setRange(0, 100)
self.volume_slider.setValue(50)
layout = QVBoxLayout()
layout.addWidget(self.label)
layout.addWidget(self.play_btn)
layout.addWidget(self.pause_btn)
layout.addWidget(self.stop_btn)
layout.addWidget(self.volume_slider)
self.setLayout(layout)
# Connections
self.play_btn.clicked.connect(self.player.play)
self.pause_btn.clicked.connect(self.player.pause)
self.stop_btn.clicked.connect(self.player.stop)
self.volume_slider.valueChanged.connect(
lambda v: self.audio_output.setVolume(v / 100)
)
self.player.positionChanged.connect(self.update_position)
def load_file(self, filepath):
self.player.setSource(QUrl.fromLocalFile(filepath))
self.label.setText(filepath.split('/')[-1])
def update_position(self, position):
# position in milliseconds
seconds = position // 1000
minutes = seconds // 60
seconds = seconds % 60
print(f"{minutes:02d}:{seconds:02d}")
if __name__ == "__main__":
app = QApplication(sys.argv)
window = AudioPlayer()
window.show()
sys.exit(app.exec())
from PyQt6.QtMultimedia import QMediaPlayer, QAudioOutput
from PyQt6.QtCore import QUrl, QModelIndex
from PyQt6.QtWidgets import QListView
class PlaylistPlayer:
def __init__(self, playlist_view: QListView):
self.player = QMediaPlayer()
self.audio_output = QAudioOutput()
self.player.setAudioOutput(self.audio_output)
self.playlist = [] # List of file paths
self.current_index = -1
def add_to_playlist(self, filepath):
self.playlist.append(filepath)
def play_index(self, index: int):
if 0 <= index < len(self.playlist):
self.current_index = index
self.player.setSource(QUrl.fromLocalFile(self.playlist[index]))
self.player.play()
def next(self):
if self.playlist:
self.current_index = (self.current_index + 1) % len(self.playlist)
self.play_index(self.current_index)
def previous(self):
if self.playlist:
self.current_index = (self.current_index - 1) % len(self.playlist)
self.play_index(self.current_index)
from PyQt6.QtMultimedia import QMediaPlayer, QAudioOutput
from PyQt6.QtMultimediaWidgets import QVideoWidget
from PyQt6.QtWidgets import (
QApplication, QWidget, QVBoxLayout, QHBoxLayout,
QPushButton, QSlider, QLabel
)
from PyQt6.QtCore import Qt, QUrl, QTimer
from PyQt6.QtGui import QAction
import sys
class VideoPlayer(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Video Player")
self.resize(800, 600)
# Media player
self.player = QMediaPlayer()
self.audio_output = QAudioOutput()
self.player.setAudioOutput(self.audio_output)
# Video widget
self.video_widget = QVideoWidget()
# Controls
self.play_btn = QPushButton("Play")
self.pause_btn = QPushButton("Pause")
self.stop_btn = QPushButton("Stop")
self.position_slider = QSlider(Qt.Orientation.Horizontal)
self.position_slider.setRange(0, 0)
self.time_label = QLabel("00:00 / 00:00")
self.volume_slider = QSlider(Qt.Orientation.Horizontal)
self.volume_slider.setRange(0, 100)
self.volume_slider.setValue(50)
# Layout
control_layout = QHBoxLayout()
control_layout.addWidget(self.play_btn)
control_layout.addWidget(self.pause_btn)
control_layout.addWidget(self.stop_btn)
control_layout.addWidget(self.position_slider)
control_layout.addWidget(self.time_label)
control_layout.addWidget(self.volume_slider)
main_layout = QVBoxLayout()
main_layout.addWidget(self.video_widget)
main_layout.addLayout(control_layout)
self.setLayout(main_layout)
# Connect
self.player.setVideoOutput(self.video_widget)
self.play_btn.clicked.connect(self.player.play)
self.pause_btn.clicked.connect(self.player.pause)
self.stop_btn.clicked.connect(self.stop)
self.player.positionChanged.connect(self.position_changed)
self.player.durationChanged.connect(self.duration_changed)
self.volume_slider.valueChanged.connect(
lambda v: self.audio_output.setVolume(v / 100)
)
def load_video(self, filepath):
self.player.setSource(QUrl.fromLocalFile(filepath))
def stop(self):
self.player.stop()
self.position_slider.setValue(0)
def position_changed(self, position):
self.position_slider.setValue(position)
self.update_time_label()
def duration_changed(self, duration):
self.position_slider.setRange(0, duration)
self.update_time_label()
def update_time_label(self):
pos = self.player.position() // 1000
dur = self.player.duration() // 1000
pos_m, pos_s = divmod(pos, 60)
dur_m, dur_s = divmod(dur, 60)
self.time_label.setText(
f"{pos_m:02d}:{pos_s:02d} / {dur_m:02d}:{dur_s:02d}"
)
def keyPressEvent(self, event):
if event.key() == Qt.Key.Key_Space:
if self.player.playbackState() == QMediaPlayer.PlaybackState.PlayingState:
self.player.pause()
else:
self.player.play()
elif event.key() == Qt.Key.Key_Left:
self.player.setPosition(max(0, self.player.position() - 5000))
elif event.key() == Qt.Key.Key_Right:
self.player.setPosition(
min(self.player.duration(), self.player.position() + 5000)
)
class FullscreenVideoPlayer(VideoPlayer):
def __init__(self):
super().__init__()
self.is_fullscreen = False
self.video_widget.doubleClicked.connect(self.toggle_fullscreen)
def toggle_fullscreen(self):
if self.is_fullscreen:
self.showNormal()
else:
self.showFullScreen()
self.is_fullscreen = not self.is_fullscreen
from PyQt6.QtMultimedia import QCamera, QMediaDevices
from PyQt6.QtMultimediaWidgets import QVideoWidget
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton
from PyQt6.QtCore import Qt
import sys
class CameraViewer(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Camera Viewer")
# Get available cameras
self.cameras = QMediaDevices.videoInputs()
if not self.cameras:
print("No cameras available")
return
# Create camera
self.camera = QCamera(self.cameras[0])
# Video widget
self.video_widget = QVideoWidget()
# Buttons
self.start_btn = QPushButton("Start")
self.stop_btn = QPushButton("Stop")
layout = QVBoxLayout()
layout.addWidget(self.video_widget)
layout.addWidget(self.start_btn)
layout.addWidget(self.stop_btn)
self.setLayout(layout)
# Connect camera to widget
self.camera.setVideoOutput(self.video_widget)
self.start_btn.clicked.connect(self.camera.start)
self.stop_btn.clicked.connect(self.camera.stop)
def closeEvent(self, event):
self.camera.stop()
super().closeEvent(event)
from PyQt6.QtMultimedia import QCamera, QMediaCaptureSession, QImageCapture
from PyQt6.QtMultimediaWidgets import QVideoWidget
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QPushButton, QLabel
from PyQt6.QtCore import QUrl
class CameraCapture(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Camera Capture")
self.camera = QCamera()
self.capture_session = QMediaCaptureSession()
self.capture_session.setCamera(self.camera)
self.video_widget = QVideoWidget()
self.capture_session.setVideoOutput(self.video_widget)
# Image capture
self.image_capture = QImageCapture()
self.capture_session.setImageCapture(self.image_capture)
self.capture_btn = QPushButton("Capture Photo")
self.preview_label = QLabel()
layout = QVBoxLayout()
layout.addWidget(self.video_widget)
layout.addWidget(self.capture_btn)
layout.addWidget(self.preview_label)
self.setLayout(layout)
self.capture_btn.clicked.connect(self.capture_photo)
self.camera.start()
def capture_photo(self):
self.image_capture.captureToFile()
def handle_captured(self, id, filePath):
print(f"Photo saved to: {filePath}")
from PyQt6.QtMultimedia import QCamera, QMediaCaptureSession, QMediaRecorder
from PyQt6.QtMultimediaWidgets import QVideoWidget
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QPushButton, QLabel
class VideoRecorder(QWidget):
def __init__(self):
super().__init__()
self.camera = QCamera()
self.capture_session = QMediaCaptureSession()
self.capture_session.setCamera(self.camera)
self.video_widget = QVideoWidget()
self.capture_session.setVideoOutput(self.video_widget)
# Recorder
self.recorder = QMediaRecorder()
self.capture_session.setRecorder(self.recorder)
self.record_btn = QPushButton("Start Recording")
self.status_label = QLabel("Ready")
layout = QVBoxLayout()
layout.addWidget(self.video_widget)
layout.addWidget(self.record_btn)
layout.addWidget(self.status_label)
self.setLayout(layout)
self.record_btn.clicked.connect(self.toggle_recording)
self.recorder.recorderStateChanged.connect(self.update_status)
def toggle_recording(self):
if self.recorder.recorderState() == QMediaRecorder.RecorderState.RecordingState:
self.recorder.stop()
else:
self.recorder.setOutputLocation(QUrl.fromLocalFile("output.mp4"))
self.recorder.record()
def update_status(self, state):
states = {
QMediaRecorder.RecorderState.StoppedState: "Stopped",
QMediaRecorder.RecorderState.RecordingState: "Recording",
QMediaRecorder.RecorderState.PausedState: "Paused"
}
self.status_label.setText(states.get(state, "Unknown"))
from PyQt6.QtMultimedia import QMediaRecorder, QMediaCaptureSession, QAudioInput
from PyQt6.QtCore import QUrl, QStandardPaths
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QPushButton, QLabel
import os
class AudioRecorder(QWidget):
def __init__(self):
super().__init__()
self.recorder = QMediaRecorder()
self.capture_session = QMediaCaptureSession()
self.audio_input = QAudioInput()
self.capture_session.setAudioInput(self.audio_input)
self.capture_session.setRecorder(self.recorder)
self.record_btn = QPushButton("Start Recording")
self.status_label = QLabel("Ready")
layout = QVBoxLayout()
layout.addWidget(self.record_btn)
layout.addWidget(self.status_label)
self.setLayout(layout)
self.record_btn.clicked.connect(self.toggle_recording)
self.recorder.recorderStateChanged.connect(self.update_status)
# Default output location
documents = QStandardPaths.writableLocation(
QStandardPaths.StandardLocation.MoviesLocation
)
self.output_path = os.path.join(documents, "recording.mp3")
def toggle_recording(self):
if self.recorder.recorderState() == QMediaRecorder.RecorderState.RecordingState:
self.recorder.stop()
else:
self.recorder.setOutputLocation(QUrl.fromLocalFile(self.output_path))
self.recorder.record()
def update_status(self, state):
if state == QMediaRecorder.RecorderState.RecordingState:
self.record_btn.setText("Stop Recording")
self.status_label.setText("Recording...")
else:
self.record_btn.setText("Start Recording")
self.status_label.setText("Ready")
# Ubuntu/Debian
sudo apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev \
gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly
# For audio/video codecs
sudo apt-get install gstreamer1.0-libav
PySide6 on Windows typically uses DirectShow or WMF backends. Install K-Lite Codec Pack for additional codec support.
# Check available codecs
from PyQt6.QtMultimedia import QMediaDevices
print("Audio outputs:", QMediaDevices.audioOutputs())
print("Video outputs:", QMediaDevices.videoOutputs())
# Check camera
print("Cameras:", QMediaDevices.videoInputs())
# Convert using QMediaEncoder with specific codec
from PyQt6.QtMultimedia import QMediaRecorder, QMediaFormat
recorder = QMediaRecorder()
recorder.setMediaFormat(QMediaFormat.MediaFormat.MPEG4)
recorder.setAudioCodec(QMediaFormat.AudioCodec.AAC)
recorder.setVideoCodec(QMediaFormat.VideoCodec.H264)
# ✅ GOOD: Check availability first
from PyQt6.QtMultimedia import QMediaDevices
if not QMediaDevices.audioInputs():
print("No microphone available")
return
# ✅ GOOD: Set output location before recording
recorder.setOutputLocation(QUrl.fromLocalFile(path))
recorder.record() # Start after setting location
# ✅ GOOD: Check player state
player.play()
# Wait for state change signal, don't assume immediate playback
# ✅ GOOD: Handle missing codecs
# Install K-Lite on Windows, gstreamer on Linux
# ✅ GOOD: Clean up resources
def closeEvent(self, event):
self.player.stop()
self.recorder.stop()
self.camera.stop()
super().closeEvent(event)
from PySide6.QtMultimedia import QMediaPlayer
from PySide6.QtMultimediaWidgets import QVideoWidget
from PySide6.QtWidgets import (
QApplication, QWidget, QVBoxLayout, QHBoxLayout,
QPushButton, QSlider, QLabel, QMainWindow
)
from PySide6.QtCore import Qt, QUrl, QTimer
from PySide6.QtGui import QAction
import sys
class VideoPlayer(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Video Player")
self.resize(800, 600)
# Media player
self.player = QMediaPlayer()
self.audio_output = QAudioOutput()
self.player.setAudioOutput(self.audio_output)
# Video widget
self.video_widget = QVideoWidget()
# Controls
self.play_btn = QPushButton("▶ Play")
self.pause_btn = QPushButton("❚❚ Pause")
self.stop_btn = QPushButton("■ Stop")
self.position_slider = QSlider(Qt.Orientation.Horizontal)
self.position_slider.setRange(0, 0)
self.time_label = QLabel("00:00 / 00:00")
self.volume_slider = QSlider(Qt.Orientation.Horizontal)
self.volume_slider.setRange(0, 100)
self.volume_slider.setValue(50)
# Toolbar layout
toolbar = QHBoxLayout()
toolbar.addWidget(self.play_btn)
toolbar.addWidget(self.pause_btn)
toolbar.addWidget(self.stop_btn)
toolbar.addWidget(self.position_slider)
toolbar.addWidget(self.time_label)
toolbar.addWidget(self.volume_slider)
toolbar.addStretch()
# Main layout
main_layout = QVBoxLayout()
main_layout.addWidget(self.video_widget)
main_layout.addLayout(toolbar)
self.setCentralWidget(QWidget())
self.centralLayout = self.centralWidget().layout()
self.centralLayout.addLayout(toolbar)
# Signal connections
self.player.setVideoOutput(self.video_widget)
self.play_btn.clicked.connect(self.player.play)
self.pause_btn.clicked.connect(self.player.pause)
self.stop_btn.clicked.connect(self.player.stop)
self.player.positionChanged.connect(self.position_changed)
self.player.durationChanged.connect(self.duration_changed)
self.volume_slider.valueChanged.connect(
lambda v: self.audio_output.setVolume(v / 100)
)
# Keyboard shortcuts
self.installEventFilter(self)
def load_video(self, filepath):
"""Load a video file."""
self.player.setSource(QUrl.fromLocalFile(filepath))
def position_changed(self, position):
"""Update position slider and time display."""
self.position_slider.setValue(position)
self.update_time_label()
def duration_changed(self, duration):
"""Update slider range and initial time display."""
self.position_slider.setRange(0, duration)
self.update_time_label()
def update_time_label(self):
"""Convert position/duration to MM:SS format."""
pos = self.player.position() // 1000
dur = self.player.duration() // 1000 if self.player.duration() > 0 else 0
pos_m, pos_s = divmod(pos, 60)
dur_m, dur_s = divmod(dur, 60)
self.time_label.setText(
f"{pos_m:02d}:{pos_s:02d} / {dur_m:02d}:{dur_s:02d}"
)
def keyPressEvent(self, event):
"""Handle keyboard shortcuts."""
if event.key() == Qt.Key.Key_Space:
if self.player.playbackState() == QMediaPlayer.PlaybackState.PlayingState:
self.player.pause()
else:
self.player.play()
elif event.key() == Qt.Key.Key_Left:
self.player.setPosition(max(0, self.player.position() - 5000))
elif event.key() == Qt.Key.Key_Right:
self.player.setPosition(
min(self.player.duration(), self.player.position() + 5000)
)
elif event.key() == Qt.Key.Key_k:
self.player.seek(5)
elif event.key() == Qt.Key.Key_j:
self.player.seek(-5)
if __name__ == "__main__":
app = QApplication(sys.argv)
# Set application properties
app.setApplicationName("Video Player")
app.setOrganizationName("MyOrg")
window = VideoPlayer()
window.show()
sys.exit(app.exec())
Controls Reference:
| Method | Description |
|---|---|
play() | Start playback |
pause() | Pause playback |
stop() | Stop playback and reset position |
setPosition(pos) | Set playback position (milliseconds) |
seek(seconds) | Seek relative to current position |
playbackState() | Returns current state (PlayingState, PausedState, StoppedState) |
position() | Current playback position in milliseconds |
duration() | Total duration in milliseconds |
Supported Formats:
.mp4, .avi, .mkv, .mov, .flv, .webm, .wmv.mp3, .wav, .ogg, .flac, .aacNote: Codec support varies by platform. On Linux, ensure GStreamer backends are installed.
from PySide6.QtMultimedia import QCamera, QMediaDevices, QMediaCaptureSession
from PySide6.QtMultimediaWidgets import QVideoWidget
from PySide6.QtWidgets import (
QApplication, QWidget, QVBoxLayout, QHBoxLayout,
QPushButton, QLabel, QComboBox, QDialogButtonBox
)
from PySide6.QtCore import Qt, QUrl
import sys
from typing import Optional
class CameraViewer(QWidget):
"""Camera viewer with live preview."""
def __init__(self):
super().__init__()
self.setWindowTitle("Camera Viewer")
self.setMinimumSize(640, 480)
# Available cameras
self.cameras = QMediaDevices.videoInputs()
if not self.cameras:
self.init_no_camera()
return
# Selected camera
self.camera = QCamera(self.cameras[0])
# Video widget for preview
self.video_widget = QVideoWidget()
# UI components
self.camera_label = QLabel("No cameras found")
self.camera_combo = QComboBox()
self.camera_combo.addItems([f"Camera {i}" for i in range(len(self.cameras))])
self.start_btn = QPushButton("Start")
self.stop_btn = QPushButton("Stop")
self.preview_label = QLabel("Ready")
# Layout
layout = QVBoxLayout()
# Camera selection
select_layout = QHBoxLayout()
select_layout.addWidget(QLabel("Camera:"))
select_layout.addWidget(self.camera_combo)
layout.addLayout(select_layout)
# Video preview
layout.addWidget(self.camera_label)
layout.addWidget(self.video_widget)
# Controls
control_layout = QHBoxLayout()
control_layout.addWidget(self.start_btn)
control_layout.addWidget(self.stop_btn)
layout.addLayout(control_layout)
# Status
layout.addWidget(self.preview_label)
layout.addStretch()
self.setLayout(layout)
# Setup camera
self.setup_camera()
# Connect signals
self.start_btn.clicked.connect(self.start_camera)
self.stop_btn.clicked.connect(self.stop_camera)
def init_no_camera(self):
"""Initialize UI when no camera is available."""
self.camera_label.setText("No camera detected")
self.preview_label.setText("No camera found")
self.camera_combo.hide()
def setup_camera(self):
"""Configure camera and connect to video output."""
camera_index = self.camera_combo.currentIndex()
camera = self.cameras[camera_index]
self.camera = QCamera(camera)
self.camera.setVideoOutput(self.video_widget)
def start_camera(self):
"""Start camera and enable preview."""
camera_index = self.camera_combo.currentIndex()
camera = self.cameras[camera_index]
self.camera = QCamera(camera)
self.camera.setVideoOutput(self.video_widget)
self.camera.start()
self.preview_label.setText("Camera active")
self.start_btn.setText("Restart")
self.stop_btn.setEnabled(True)
def stop_camera(self):
"""Stop camera and disable preview."""
self.camera.stop()
self.preview_label.setText("Camera stopped")
self.start_btn.setText("Start")
self.start_btn.setEnabled(False)
self.stop_btn.setEnabled(False)
def closeEvent(self, event):
"""Clean up camera resources."""
self.camera.stop()
super().closeEvent(event)
class CameraCapture(QWidget):
"""Camera with photo capture functionality."""
def __init__(self):
super().__init__()
self.setWindowTitle("Camera Capture")
self.setMinimumSize(640, 480)
self.camera = QCamera()
self.capture_session = QMediaCaptureSession()
self.image_capture = QImageCapture()
self.video_widget = QVideoWidget()
self.capture_session.setVideoOutput(self.video_widget)
self.capture_session.setCamera(self.camera)
self.capture_session.setImageCapture(self.image_capture)
# Image capture settings
self.image_capture.setCaptureMode(
QImageCapture.CaptureMode.Photo
)
self.image_capture.setResolution(
self.image_capture.resolutionHighest()
)
self.image_capture.setCompressionType(
QImageCapture.CompressionType.Jpeg
)
self.image_capture.setJpegQuality(85)
self.capture_btn = QPushButton("Capture Photo")
self.capture_btn.setEnabled(False)
self.status_label = QLabel("Ready")
# Layout
layout = QVBoxLayout()
layout.addWidget(self.video_widget)
layout.addWidget(self.capture_btn)
layout.addWidget(self.status_label)
self.setLayout(layout)
# Connect signals
self.capture_btn.clicked.connect(self.capture_photo)
self.camera.start()
def capture_photo(self):
"""Capture photo from camera."""
if self.camera.isRunning():
self.capture_session.setImageCapture(self.image_capture)
self.image_capture.triggerCapture(
self.image_capture.imageSize()
)
self.status_label.setText("Capturing...")
# Handle captured image
self.image_capture.imageReady.connect(self.on_image_ready)
else:
self.status_label.setText("Camera not running")
def on_image_ready(self, id: int, filePath: str):
"""Callback when image is captured."""
self.status_label.setText(f"Photo saved: {filePath}")
self.capture_btn.setEnabled(True)
# Display captured image
from PySide6.QtGui import QPixmap, QImage
pixmap = QPixmap(filePath)
self.video_widget.setPixmap(pixmap.scaled(
self.video_widget.size(),
Qt.AspectRatioMode.KeepAspectRatio,
Qt.TransformationMode.SmoothTransformation
))
if __name__ == "__main__":
app = QApplication(sys.argv)
window = CameraViewer()
window.show()
sys.exit(app.exec())
Camera Device Enumeration:
from PySide6.QtMultimedia import QMediaDevices
# Get all video input devices (cameras)
cameras = QMediaDevices.videoInputs()
print(f"Available cameras: {len(cameras)}")
for i, camera in enumerate(cameras):
print(f" Camera {i}: {camera}")
# Get all video output devices (displays)
video_outputs = QMediaDevices.videoOutputs()
# Get audio input devices (microphones)
audio_inputs = QMediaDevices.audioInputs()
# Get audio output devices (speakers)
audio_outputs = QMediaDevices.audioOutputs()
Photo Capture Options:
# Set capture mode
self.image_capture.setCaptureMode(
QImageCapture.CaptureMode.Photo
)
# Set resolution
self.image_capture.setResolution(
QImageCapture.Resolution.QVGA # or QualityBestResolution
)
# Set compression
self.image_capture.setCompressionType(
QImageCapture.CompressionType.Jpeg
)
self.image_capture.setJpegQuality(85)
# Set custom capture dimensions
self.image_capture.setCaptureSize(640, 480)
# Manual capture trigger
self.image_capture.triggerCapture(QSize(640, 480))
from PySide6.QtMultimedia import (
QMediaRecorder, QMediaCaptureSession, QCamera, QMediaDevices
)
from PySide6.QtMultimediaWidgets import QVideoWidget
from PySide6.QtWidgets import (
QApplication, QWidget, QVBoxLayout, QHBoxLayout,
QPushButton, QLabel, QFileDialog
)
from PySide6.QtCore import QUrl, QStandardPaths
from PySide6.QtGui import QDesktopServices
import os
import sys
class MediaRecorder(QWidget):
"""Complete media recording with audio/video support."""
def __init__(self):
super().__init__()
self.setWindowTitle("Media Recorder")
self.setMinimumSize(800, 600)
# Camera setup
self.camera = QCamera(QMediaDevices.videoInputs()[0])
self.capture_session = QMediaCaptureSession()
self.capture_session.setCamera(self.camera)
self.capture_session.setVideoOutput(self.video_widget)
# Video widget
self.video_widget = QVideoWidget()
# Recorder
self.recorder = QMediaRecorder()
self.capture_session.setRecorder(self.recorder)
# UI components
self.record_btn = QPushButton("Start Recording")
self.record_btn.setEnabled(False)
self.stop_btn = QPushButton("Stop Recording")
self.stop_btn.setEnabled(False)
self.status_label = QLabel("Ready")
self.progress_label = QLabel("")
self.recorder.recorderStateChanged.connect(self.update_status)
self.recorder.durationChanged.connect(self.duration_changed)
# Layout
layout = QVBoxLayout()
layout.addWidget(self.video_widget)
control_layout = QHBoxLayout()
control_layout.addWidget(self.record_btn)
control_layout.addWidget(self.stop_btn)
control_layout.addWidget(self.progress_label)
layout.addLayout(control_layout)
layout.addWidget(self.status_label)
layout.addStretch()
self.setLayout(layout)
# Setup recorder defaults
self.setup_recorder_defaults()
# Connect signals
self.record_btn.clicked.connect(self.toggle_recording)
self.stop_btn.clicked.connect(self.stop_recording)
def setup_recorder_defaults(self):
"""Configure default recording settings."""
# Default output location in Videos folder
documents = QStandardPaths.writableLocation(
QStandardPaths.StandardLocation.MoviesLocation
)
# Get video extension based on codec
self.output_format = "mp4"
self.output_path = os.path.join(documents, f"recording_{self._get_timestamp()}.{self.output_format}")
def _get_timestamp(self):
"""Generate timestamp string."""
from datetime import datetime
return datetime.now().strftime("%Y%m%d_%H%M%S")
def toggle_recording(self):
"""Toggle recording on/off."""
state = self.recorder.recorderState()
if state == QMediaRecorder.RecorderState.RecordingState:
self.recorder.stop()
else:
self.recorder.setOutputLocation(QUrl.fromLocalFile(self.output_path))
self.recorder.record()
def stop_recording(self):
"""Stop current recording."""
self.recorder.stop()
self.status_label.setText("Recording stopped")
self.record_btn.setEnabled(True)
self.record_btn.setText("Record Again")
self.stop_btn.setEnabled(False)
def update_status(self, state):
"""Update status based on recorder state."""
states = {
QMediaRecorder.RecorderState.StoppedState: "Ready to record",
QMediaRecorder.RecorderState.RecordingState: "Recording...",
QMediaRecorder.RecorderState.PausedState: "Paused",
QMediaRecorder.RecorderState.ErrorState: "Error occurred"
}
self.status_label.setText(states.get(state, "Unknown"))
def duration_changed(self, duration):
"""Update progress based on recording duration."""
if duration > 0:
seconds = duration // 1000
self.progress_label.setText(f"Recording: {seconds} seconds")
def closeEvent(self, event):
"""Clean up resources."""
self.recorder.stop()
self.camera.stop()
super().closeEvent(event)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MediaRecorder()
window.show()
sys.exit(app.exec())
from PySide6.QtMultimedia import QMediaRecorder, QMediaCaptureSession
from PySide6.QtCore import QUrl, QStandardPaths, QMimeType
import os
import sys
from PySide6.QtWidgets import (
QApplication, QWidget, QVBoxLayout, QPushButton, QLabel, QFileDialog
)
class AudioRecorder(QWidget):
"""Audio recording from microphone."""
def __init__(self):
super().__init__()
self.setWindowTitle("Audio Recorder")
self.recorder = QMediaRecorder()
self.capture_session = QMediaCaptureSession()
# Audio input setup
audio_inputs = QStandardPaths.writableLocation(
QStandardPaths.StandardLocation.MoviesLocation
)
self.status_label = QLabel("Ready")
self.record_btn = QPushButton("Start Recording")
layout = QVBoxLayout()
layout.addWidget(self.record_btn)
layout.addWidget(self.status_label)
self.setLayout(layout)
self.record_btn.clicked.connect(self.toggle_recording)
self.recorder.recorderStateChanged.connect(self.update_status)
# Default output
self.output_path = os.path.join(
audio_inputs, "recording.wav"
)
def toggle_recording(self):
"""Toggle recording state."""
state = self.recorder.recorderState()
if state == QMediaRecorder.RecorderState.RecordingState:
self.recorder.stop()
self.status_label.setText("Recording stopped")
else:
self.recorder.setOutputLocation(QUrl.fromLocalFile(self.output_path))
self.recorder.setAudioFormat(
QMediaRecorder.AudioFormat.WAV,
44100,
2,
2,
-16,
-1
)
self.recorder.record()
self.status_label.setText("Recording...")
def update_status(self, state):
"""Update status label."""
if state == QMediaRecorder.RecorderState.RecordingState:
self.status_label.setText("Recording...")
self.record_btn.setText("Stop")
else:
self.status_label.setText("Recording saved")
self.record_btn.setText("Start Recording")
def save_recording(self):
"""Save recording to file dialog."""
file_path, _ = QFileDialog.getSaveFileName(
self, "Save Recording", self.output_path,
"Audio Files (*.wav *.mp3 *.ogg *.flac);;All Files (*)"
)
if file_path:
self.recorder.setOutputLocation(QUrl.fromLocalFile(file_path))
self.output_path = file_path
if __name__ == "__main__":
app = QApplication(sys.argv)
window = AudioRecorder()
window.show()
sys.exit(app.exec())
from PySide6.QtMultimedia import QMediaRecorder, QMediaCaptureSession
from PySide6.QtCore import QUrl, QStandardPaths
import os
import sys
from PySide6.QtWidgets import (
QApplication, QWidget, QVBoxLayout, QPushButton, QLabel
)
class VideoRecorder(QWidget):
"""Video recording with encoding options."""
def __init__(self):
super().__init__()
self.setWindowTitle("Video Recorder")
self.camera = QCamera(QStandardPaths.writableLocation(
QStandardPaths.StandardLocation.VideosLocation
) + "camera.mp4")
self.capture_session = QMediaCaptureSession()
self.capture_session.setCamera(self.camera)
self.recorder = QMediaRecorder()
self.capture_session.setRecorder(self.recorder)
self.status_label = QLabel("Ready")
self.record_btn = QPushButton("Start Recording")
layout = QVBoxLayout()
layout.addWidget(self.record_btn)
layout.addWidget(self.status_label)
self.setLayout(layout)
self.record_btn.clicked.connect(self.toggle_recording)
self.recorder.recorderStateChanged.connect(self.update_status)
def toggle_recording(self):
"""Start/stop video recording."""
state = self.recorder.recorderState()
if state == QMediaRecorder.RecorderState.RecordingState:
self.recorder.stop()
else:
self.recorder.setMediaFormat(self._get_video_format())
self.recorder.setVideoCodec(self.recorder.videoFormat().videoCodec())
self.recorder.setAudioCodec(self.recorder.audioFormat().audioCodec())
self.recorder.setOutputLocation(QUrl.fromLocalFile("video.mp4"))
self.recorder.record()
def _get_video_format(self):
"""Get H.264 video format."""
return QMediaFormat(
QMediaFormat.MediaFormat.MPEG4,
self.camera.videoResolution(),
QMediaFormat.VelocityLevel.Normal,
2000000, # 2 Mbps bitrate
QMediaFormat.ResolutionSelector.Variable
)
def update_status(self, state):
"""Update status."""
if state == QMediaRecorder.RecorderState.RecordingState:
self.status_label.setText("Recording video...")
else:
self.status_label.setText("Recording complete")
def save_recording(self):
"""Open save dialog."""
file_path, _ = QFileDialog.getSaveFileName(
self, "Save Video", "recording.mp4",
"Video Files (*.mp4 *.avi *.mkv);;All Files (*)"
)
if file_path:
self.recorder.setOutputLocation(QUrl.fromLocalFile(file_path))
if __name__ == "__main__":
app = QApplication(sys.argv)
window = VideoRecorder()
window.show()
sys.exit(app.exec())
from PySide6.QtMultimedia import QMediaFormat, QMediaRecorder
# Configure video format
video_format = QMediaFormat()
video_format.setMediaType(QMediaFormat.MediaType.Video)
video_format.setMediaFormat(QMediaFormat.MediaFormat.MPEG4)
# Set resolution
video_format.setResolution(1280, 720) # 1280x720
# Set bitrate (bytes per second)
video_format.setBitRate(2000000) # 2 Mbps
# Set video codec
video_format.setVideoCodec(
QMediaFormat.VideoCodec.H264
)
# Set framerate
video_format.setFrameRate(30) # 30 FPS
# Create recorder and set format
recorder = QMediaRecorder()
recorder.setMediaFormat(video_format)
# Audio format configuration
audio_format = QMediaFormat()
audio_format.setMediaType(QMediaFormat.MediaType.Audio)
audio_format.setMediaFormat(QMediaFormat.MediaFormat.Mp3)
audio_format.setAudioCodec(QMediaFormat.AudioCodec.AAC)
audio_format.setBitRate(128000) # 128 kbps
# Full recording setup with encoding
recorder.setVideoCodec(QMediaFormat.VideoCodec.H264)
recorder.setAudioCodec(QMediaFormat.AudioCodec.AAC)
recorder.setVideoFormat(video_format)
recorder.setAudioFormat(audio_format)
recorder.setOutputLocation(QUrl.fromLocalFile("output.mp4"))
recorder.record()
from PySide6.QtMultimedia import QMediaRecorder, QMediaFormat
from PySide6.QtWidgets import QMessageBox
import sys
from PySide6.QtWidgets import QApplication
class ErrorHandlingRecorder(QMediaRecorder):
"""MediaRecorder with comprehensive error handling."""
def __init__(self, parent=None):
super().__init__(parent)
self.error_signal = lambda: self.error_occurred()
def error_occurred(self):
"""Handle recorder errors."""
error_state = self.error()
error_messages = {
QMediaRecorder.ErrorState.NoError: "No error",
QMediaRecorder.ErrorState.InvalidRoleError: "Invalid role error",
QMediaRecorder.ErrorState.InvalidFormatError: "Invalid format error",
QMediaRecorder.ErrorState.UnsupportedFormatError: "Unsupported format",
QMediaRecorder.ErrorState.CodecNotAvailableError: "Codec not available",
QMediaRecorder.ErrorState.UnknownError: "Unknown error"
}
error_msg = error_messages.get(error_state, "Unknown error")
QMessageBox.critical(self, "Recording Error", error_msg)
# Reset recorder state
self.stop()
# Usage with error handling
recorder = ErrorHandlingRecorder()
# Connect to error signal
recorder.error.connect(lambda: print("Recorder error occurred"))
# Set invalid format (to trigger error)
recorder.setMediaFormat(QMediaFormat())
from PySide6.QtMultimedia import QMediaPlayer
from PySide6.QtWidgets import QApplication, QWidget, QLabel, QPushButton
from PySide6.QtCore import QUrl
import sys
class ErrorHandlingPlayer(QMediaPlayer):
"""MediaPlayer with error handling."""
def __init__(self, parent=None):
super().__init__(parent)
self.status_label = QLabel("Ready")
def playback_error(self, error_state):
"""Handle playback errors."""
errors = {
QMediaPlayer.ErrorState.NoError: "No error",
QMediaPlayer.ErrorState.InvalidRoleError: "Invalid role error",
QMediaPlayer.ErrorState.ResourceNotAvailableError: "Resource not available",
QMediaPlayer.ErrorState.ResourceCannotBeReadError: "Cannot read resource",
QMediaPlayer.ErrorState.FormatError: "Format error",
QMediaPlayer.ErrorState.PlaybackFailedError: "Playback failed",
QMediaPlayer.ErrorState.UnknownMediaError: "Unknown media error",
QMediaPlayer.ErrorState.ProtocolError: "Protocol error",
QMediaPlayer.ErrorState.AbstractError: "Abstract error"
}
error_msg = errors.get(error_state, "Unknown error")
self.status_label.setText(f"Error: {error_msg}")
print(f"MediaPlayer error: {error_msg}")
# Usage
app = QApplication(sys.argv)
player = ErrorHandlingPlayer()
player.playbackError.connect(lambda e: print(f"Error: {e}"))
# Load invalid file (to trigger error)
player.setSource(QUrl.fromLocalFile("invalid_file.mp4"))
player.play()
sys.exit(app.exec())
from PySide6.QtMultimedia import QCamera, QCameraError
from PySide6.QtWidgets import QApplication, QWidget, QLabel, QPushButton
import sys
class ErrorHandlingCamera(QCamera):
"""Camera with error handling."""
def __init__(self, video_input, parent=None):
super().__init__(video_input, parent)
self.status_label = QLabel("Ready")
def camera_error(self, error):
"""Handle camera errors."""
error_codes = {
QCameraError.NoError: "No error",
QCameraError.UnsupportedBackendError: "Unsupported backend",
QCameraError.UnsupportedFormatError: "Unsupported format",
QCameraError.VideoInputNotFound: "Video input not found",
QCameraError.ErrorStartingCamera: "Error starting camera",
QCameraError.ErrorStoppingCamera: "Error stopping camera",
QCameraError.ErrorReadingProperty: "Error reading property",
QCameraError.ErrorWritingProperty: "Error writing property",
QCameraError.FrameAlreadyReleasedError: "Frame already released",
QCameraError.ErrorResolutionChange: "Error changing resolution",
QCameraError.ErrorSourceChange: "Error changing source",
QCameraError.ErrorInvalidState: "Invalid state",
QCameraError.ErrorImageBufferCreation: "Error creating image buffer",
QCameraError.ErrorImageBufferRelease: "Error releasing image buffer",
QCameraError.ErrorInvalidState: "Invalid camera state",
QCameraError.ErrorAccessingFrameBuffer: "Error accessing frame buffer",
QCameraError.ErrorRecordingStopped: "Recording stopped"
}
error_msg = error_codes.get(error, "Unknown error")
self.status_label.setText(f"Error: {error_msg}")
print(f"Camera error: {error_msg}")
# Usage
app = QApplication(sys.argv)
camera = ErrorHandlingCamera(QCameraError)
camera.start()
camera.stop()
sys.exit(app.exec())
from PySide6.QtMultimedia import QMediaPlayer, QMediaDevices, QCamera
from PySide6.QtWidgets import QMessageBox
from PySide6.QtCore import QUrl
import sys
class CommonErrorHandler:
"""Handle common multimedia errors."""
@staticmethod
def check_device_availability():
"""Check if required devices are available."""
if not QMediaDevices.audioInputs():
raise RuntimeError("No audio input devices found")
if not QMediaDevices.videoInputs():
raise RuntimeError("No camera devices found")
@staticmethod
def check_file_exists(filepath):
"""Verify file exists and is accessible."""
if not os.path.exists(filepath):
raise FileNotFoundError(f"File not found: {filepath}")
if not os.path.isfile(filepath):
raise FileExistsError("Path is not a file")
@staticmethod
def handle_codec_error(player, error_state):
"""Handle codec-related errors."""
if error_state == QMediaPlayer.ErrorState.FormatError:
QMessageBox.information(
None, "Codec Error",
"The required codec is not installed.\n\n"
"Install K-Lite Codec Pack (Windows) or GStreamer (Linux)."
)
@staticmethod
def handle_network_error(player, error_state):
"""Handle network stream errors."""
if error_state in [
QMediaPlayer.ErrorState.ResourceNotAvailableError,
QMediaPlayer.ErrorState.ProtocolError
]:
QMessageBox.warning(
None, "Network Error",
"Cannot access network stream.\n"
"Check your network connection and URL."
)
# Usage
try:
CommonErrorHandler.check_device_availability()
CommonErrorHandler.check_file_exists("video.mp4")
player = QMediaPlayer()
player.play()
except (RuntimeError, FileNotFoundError, FileExistsError) as e:
print(f"Setup error: {e}")
sys.exit(1)
| Codec | Container | Quality | Required Package |
|---|---|---|---|
| Audio | |||
| MP3 | .mp3 | Good | gstreamer1.0-plugins-good |
| WAV | .wav | Excellent | Built-in |
| OGG | .ogg | Good | gstreamer1.0-plugins-good |
| FLAC | .flac | Excellent | gstreamer1.0-plugins-good |
| AAC | .m4a | Good | gstreamer1.0-plugins-good |
| Video | |||
| H.264 (AVC) | .mp4, .avi, .mkv | Excellent | gstreamer1.0-plugins-bad |
| H.265 (HEVC) | .mp4 | Good | gstreamer1.0-libav |
| MPEG-4 | .mp4 | Good | Built-in |
| MPEG-2 | .mpg, .mpeg | Good | gstreamer1.0-plugins-bad |
| VP8 | .webm | Good | gstreamer1.0-plugins-good |
| VP9 | .webm | Good | gstreamer1.0-plugins-bad |
| AV1 | .webm | Excellent | gstreamer1.0-libav |
| Codec | Container | Quality | Recommended |
|---|---|---|---|
| Audio | |||
| MP3 | .mp3 | Good | K-Lite Codec Pack |
| WAV | .wav | Excellent | Built-in |
| AAC | .m4a | Good | K-Lite Codec Pack |
| WMA | .wma | Good | Built-in |
| Video | |||
| H.264 (AVC) | .mp4, .avi | Excellent | K-Lite Codec Pack |
| H.265 (HEVC) | .mp4 | Good | HEVC Extension |
| MPEG-4 | .mp4 | Good | Built-in |
| WMV | .wmv | Excellent | Built-in |
| AV1 | .webm | Good | AV1 Extensions |
| Codec | Container | Quality | Status |
|---|---|---|---|
| Audio | |||
| AAC | .m4a | Excellent | Built-in |
| ALAC | .m4a | Excellent | Built-in |
| WAV | .wav | Excellent | Built-in |
| Video | |||
| H.264 (AVC) | .mp4, .mov | Excellent | Built-in |
| H.265 (HEVC) | .mp4 | Good | Built-in (Free) |
| ProRes | .mov | Excellent | Built-in (Professional) |
| AAC | .m4a | Good | Built-in |
# Ubuntu/Debian
sudo apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev \
gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly
# For better codec support
sudo apt-get install gstreamer1.0-libav gstreamer1.0-clutter
# Fedora
sudo dnf install gstreamer1-devel gstreamer1-plugins-base-devel \
gstreamer1-plugins-good gstreamer1-plugins-bad gstreamer1-plugins-ugly
# Arch Linux
sudo pacman -S gstreamer gst-plugins-good gst-plugins-bad gst-plugins-ugly \
gst-libav gst-clutter
# Verify installation
python -c "from PySide6.QtMultimedia import QMediaDevices; \
print('Audio inputs:', len(QMediaDevices.audioInputs())); \
print('Video inputs:', len(QMediaDevices.videoInputs()))"
# Check codec support
from PySide6.QtMultimedia import QMediaDevices
def check_codec_support():
"""Check available codec support."""
audio_inputs = QMediaDevices.audioInputs()
video_inputs = QMediaDevices.videoInputs()
print(f"Audio devices: {len(audio_inputs)}")
print(f"Video devices: {len(video_inputs)}")
# If no devices, install codec pack
if not audio_inputs and not video_inputs:
print("No codec support detected!")
print("Install K-Lite Codec Pack: https://codecguide.com/install_windows_kl.mp")
K-Lite Codec Pack (Windows):
No additional installation required. PySide6 uses AVFoundation which includes:
from PySide6.QtMultimedia import QMediaFormat
# Check format compatibility
def check_format_compatibility(filepath):
"""Check if format is supported."""
media = QMediaFormat()
supported_formats = {
QMediaFormat.MediaFormat.MPEG4: "MPEG-4 (MP4, M4V)",
QMediaFormat.MediaFormat.Wav: "WAV (WAV)",
QMediaFormat.MediaFormat.Mp3: "MP3 (MP3)",
QMediaFormat.MediaFormat.Ogg: "OGG (OGG)",
QMediaFormat.MediaFormat.Flac: "FLAC",
QMediaFormat.MediaFormat.Aac: "AAC (M4A)",
QMediaFormat.MediaFormat.H264: "H.264 Video",
QMediaFormat.MediaFormat.H265: "H.265/HEVC Video",
}
return supported_formats
from PySide6.QtMultimedia import QMediaRecorder, QMediaFormat
# Best quality for recording
def setup_high_quality_recording():
recorder = QMediaRecorder()
# Video format
video_format = QMediaFormat()
video_format.setMediaType(QMediaFormat.MediaType.Video)
video_format.setMediaFormat(QMediaFormat.MediaFormat.MPEG4)
video_format.setVideoCodec(QMediaFormat.VideoCodec.H264)
video_format.setResolution(1920, 1080) # 1080p
video_format.setBitRate(8000000) # 8 Mbps
video_format.setFrameRate(60) # 60 FPS
# Audio format
audio_format = QMediaFormat()
audio_format.setMediaType(QMediaFormat.MediaType.Audio)
audio_format.setMediaFormat(QMediaFormat.MediaFormat.Mp3)
audio_format.setAudioCodec(QMediaFormat.AudioCodec.AAC)
audio_format.setBitRate(320000) # 320 kbps
audio_format.setSampleRate(48000)
recorder.setMediaFormat(video_format)
recorder.setAudioFormat(audio_format)
return recorder
# Web-compatible recording
def setup_web_recording():
recorder = QMediaRecorder()
video_format = QMediaFormat()
video_format.setMediaFormat(QMediaFormat.MediaFormat.MPEG4)
video_format.setVideoCodec(QMediaFormat.VideoCodec.H264)
video_format.setResolution(1280, 720) # 720p for web
video_format.setBitRate(2000000) # 2 Mbps
video_format.setFrameRate(30)
audio_format = QMediaFormat()
audio_format.setMediaFormat(QMediaFormat.MediaFormat.Mp3)
audio_format.setAudioCodec(QMediaFormat.AudioCodec.AAC)
audio_format.setBitRate(128000)
recorder.setMediaFormat(video_format)
recorder.setAudioFormat(audio_format)
return recorder
# Mobile-optimized recording
def setup_mobile_recording():
recorder = QMediaRecorder()
video_format = QMediaFormat()
video_format.setMediaFormat(QMediaFormat.MediaFormat.MPEG4)
video_format.setVideoCodec(QMediaFormat.VideoCodec.H264)
video_format.setResolution(640, 480) # 480p for mobile
video_format.setBitRate(500000) # 0.5 Mbps
video_format.setFrameRate(30)
audio_format = QMediaFormat()
audio_format.setMediaFormat(QMediaFormat.MediaFormat.Mp3)
audio_format.setAudioCodec(QMediaFormat.AudioCodec.AAC)
audio_format.setBitRate(96000)
recorder.setMediaFormat(video_format)
recorder.setAudioFormat(audio_format)
return recorder
from PySide6.QtMultimedia import QMediaDevices, QMediaPlayer
from PySide6.QtWidgets import QMessageBox, QLabel
def diagnose_codec_issues():
"""Diagnose codec-related problems."""
issues = []
# Check device availability
if not QMediaDevices.audioInputs():
issues.append("No audio input devices found")
if not QMediaDevices.videoInputs():
issues.append("No camera devices found")
# Test playback
player = QMediaPlayer()
try:
# This will fail if codec is missing
player.play()
issues.append("Playback test inconclusive")
except Exception as e:
issues.append(f"Playback error: {e}")
if issues:
QMessageBox.warning(
None, "Codec Issues",
"Issues detected:\n\n" + "\n".join(issues) + "\n\n"
"Consider installing codec packs for your platform."
)
return issues