| name | pyqt-multimedia | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| description | PyQt/PySide multimedia - audio playback, video playback, camera, audio recording, media player | ||||||||||||||
| metadata |
|
Audio and video playback, camera capture, and media processing in PyQt/PySide.
Qt Multimedia provides classes for audio, video, and camera functionality:
- QMediaPlayer - Audio/video playback
- QVideoWidget - Video display
- QAudioOutput - Audio output management
- QCamera - Camera capture
- QMediaRecorder - Audio/video recording
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_fullscreenfrom 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-libavPySide6 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)- Check device availability before use
- Set output location before recording
- Clean up on close
- Record without checking available disk space
- Use unsupported formats
- Forget to stop capture sessions
- Qt Multimedia: https://doc.qt.io/qt-6/qtmultimedia-index.html
- PySide6 Multimedia: https://doc.qt.io/qt-6/multimedia.html
- GStreamer: https://gstreamer.freedesktop.org/