0
# Multimedia Components
1
2
Media player widgets, video display, and audio/video control components with modern playback interfaces. These components provide comprehensive multimedia functionality with fluent design integration.
3
4
## Capabilities
5
6
### Media Player
7
8
Core media player widget with comprehensive playback controls and modern interface design.
9
10
```python { .api }
11
class MediaPlayer(QWidget):
12
def __init__(self, parent=None): ...
13
def setMedia(self, media: Union[str, QUrl, QMediaContent]): ...
14
def media(self) -> QMediaContent: ...
15
def play(self): ...
16
def pause(self): ...
17
def stop(self): ...
18
def setPosition(self, position: int): ...
19
def position(self) -> int: ...
20
def setVolume(self, volume: int): ...
21
def volume(self) -> int: ...
22
def duration(self) -> int: ...
23
def state(self) -> QMediaPlayer.State: ...
24
25
# Signals
26
positionChanged = pyqtSignal(int)
27
durationChanged = pyqtSignal(int)
28
stateChanged = pyqtSignal(QMediaPlayer.State)
29
volumeChanged = pyqtSignal(int)
30
31
class MediaPlayerBase(QWidget):
32
def __init__(self, parent=None): ...
33
def setMediaPlayer(self, player: QMediaPlayer): ...
34
def mediaPlayer(self) -> QMediaPlayer: ...
35
```
36
37
**Usage Example:**
38
```python
39
from qfluentwidgets import MediaPlayer
40
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent
41
from PyQt5.QtCore import QUrl
42
43
# Create media player
44
media_player = MediaPlayer(self)
45
media_player.setFixedSize(600, 400)
46
47
# Load media file
48
media_file = "path/to/video.mp4"
49
media_player.setMedia(media_file)
50
51
# Connect to signals
52
media_player.positionChanged.connect(self.on_position_changed)
53
media_player.durationChanged.connect(self.on_duration_changed)
54
media_player.stateChanged.connect(self.on_state_changed)
55
56
def on_position_changed(self, position):
57
# Update progress slider
58
progress_slider.setValue(position)
59
60
def on_duration_changed(self, duration):
61
# Set slider range
62
progress_slider.setRange(0, duration)
63
duration_label.setText(self.format_time(duration))
64
65
def on_state_changed(self, state):
66
if state == QMediaPlayer.PlayingState:
67
play_button.setText("Pause")
68
else:
69
play_button.setText("Play")
70
71
# Control playback
72
play_button.clicked.connect(media_player.play)
73
pause_button.clicked.connect(media_player.pause)
74
stop_button.clicked.connect(media_player.stop)
75
```
76
77
### Video Display
78
79
Dedicated video display widget for rendering video content with proper aspect ratio handling.
80
81
```python { .api }
82
class VideoWidget(QVideoWidget):
83
def __init__(self, parent=None): ...
84
def setAspectRatioMode(self, mode: Qt.AspectRatioMode): ...
85
def aspectRatioMode(self) -> Qt.AspectRatioMode: ...
86
def setFullScreen(self, fullScreen: bool): ...
87
def isFullScreen(self) -> bool: ...
88
def sizeHint(self) -> QSize: ...
89
```
90
91
**Usage Example:**
92
```python
93
from qfluentwidgets import VideoWidget, MediaPlayer
94
from PyQt5.QtCore import Qt
95
96
# Create video display
97
video_widget = VideoWidget(self)
98
video_widget.setAspectRatioMode(Qt.KeepAspectRatio)
99
video_widget.setMinimumSize(320, 240)
100
101
# Create media player and connect to video widget
102
player = QMediaPlayer(self)
103
player.setVideoOutput(video_widget)
104
105
# Create media player UI
106
media_player = MediaPlayer(self)
107
media_player.setMediaPlayer(player)
108
109
# Layout video and controls
110
layout = QVBoxLayout(self)
111
layout.addWidget(video_widget, 1) # Video takes most space
112
layout.addWidget(media_player, 0) # Controls at bottom
113
114
# Fullscreen toggle
115
def toggle_fullscreen():
116
video_widget.setFullScreen(not video_widget.isFullScreen())
117
118
fullscreen_btn.clicked.connect(toggle_fullscreen)
119
120
# Handle escape key to exit fullscreen
121
def keyPressEvent(self, event):
122
if event.key() == Qt.Key_Escape and video_widget.isFullScreen():
123
video_widget.setFullScreen(False)
124
super().keyPressEvent(event)
125
```
126
127
### Media Control Bars
128
129
Specialized control bars with playback buttons, progress tracking, and volume controls.
130
131
```python { .api }
132
class StandardMediaPlayBar(QWidget):
133
def __init__(self, parent=None): ...
134
def setMediaPlayer(self, player: QMediaPlayer): ...
135
def setPlayButtonVisible(self, visible: bool): ...
136
def setVolumeButtonVisible(self, visible: bool): ...
137
def setProgressSliderVisible(self, visible: bool): ...
138
def setTimeLabelsVisible(self, visible: bool): ...
139
140
class SimpleMediaPlayBar(QWidget):
141
def __init__(self, parent=None): ...
142
def setMediaPlayer(self, player: QMediaPlayer): ...
143
def setCompactMode(self, compact: bool): ...
144
145
class MediaPlayBarButton(QToolButton):
146
def __init__(self, parent=None): ...
147
def __init__(self, icon: Union[FluentIconBase, QIcon, str], parent=None): ...
148
def setPlayIcon(self, icon: Union[FluentIconBase, QIcon, str]): ...
149
def setPauseIcon(self, icon: Union[FluentIconBase, QIcon, str]): ...
150
def setPlaying(self, playing: bool): ...
151
```
152
153
**Usage Example:**
154
```python
155
from qfluentwidgets import (StandardMediaPlayBar, SimpleMediaPlayBar,
156
MediaPlayBarButton, FluentIcon as FIF)
157
158
# Standard media control bar
159
standard_bar = StandardMediaPlayBar(self)
160
standard_bar.setMediaPlayer(player)
161
162
# Customize visibility
163
standard_bar.setPlayButtonVisible(True)
164
standard_bar.setVolumeButtonVisible(True)
165
standard_bar.setProgressSliderVisible(True)
166
standard_bar.setTimeLabelsVisible(True)
167
168
# Simple media control bar
169
simple_bar = SimpleMediaPlayBar(self)
170
simple_bar.setMediaPlayer(player)
171
simple_bar.setCompactMode(True)
172
173
# Custom media buttons
174
play_pause_btn = MediaPlayBarButton(self)
175
play_pause_btn.setPlayIcon(FIF.PLAY)
176
play_pause_btn.setPauseIcon(FIF.PAUSE)
177
178
stop_btn = MediaPlayBarButton(FIF.STOP, self)
179
next_btn = MediaPlayBarButton(FIF.NEXT, self)
180
prev_btn = MediaPlayBarButton(FIF.PREVIOUS, self)
181
182
# Connect custom buttons
183
play_pause_btn.clicked.connect(self.toggle_playback)
184
stop_btn.clicked.connect(player.stop)
185
next_btn.clicked.connect(self.next_track)
186
prev_btn.clicked.connect(self.previous_track)
187
188
def toggle_playback(self):
189
if player.state() == QMediaPlayer.PlayingState:
190
player.pause()
191
play_pause_btn.setPlaying(False)
192
else:
193
player.play()
194
play_pause_btn.setPlaying(True)
195
```
196
197
## Complete Media Player Example
198
199
```python
200
from qfluentwidgets import *
201
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent, QMediaPlaylist
202
from PyQt5.QtCore import QUrl, QTimer
203
204
class FluentMediaPlayer(QWidget):
205
def __init__(self, parent=None):
206
super().__init__(parent)
207
self.setupUi()
208
self.setupMediaPlayer()
209
self.setupConnections()
210
211
def setupUi(self):
212
# Main layout
213
layout = QVBoxLayout(self)
214
215
# Title bar
216
title_bar = QHBoxLayout()
217
self.title_label = TitleLabel("Media Player")
218
self.minimize_btn = TransparentToolButton(FIF.MINIMIZE)
219
self.close_btn = TransparentToolButton(FIF.CLOSE)
220
221
title_bar.addWidget(self.title_label)
222
title_bar.addStretch()
223
title_bar.addWidget(self.minimize_btn)
224
title_bar.addWidget(self.close_btn)
225
226
# Video display area
227
self.video_widget = VideoWidget(self)
228
self.video_widget.setAspectRatioMode(Qt.KeepAspectRatio)
229
self.video_widget.setMinimumSize(640, 360)
230
231
# Control panel
232
control_layout = QHBoxLayout()
233
234
# Playback controls
235
self.prev_btn = MediaPlayBarButton(FIF.PREVIOUS, self)
236
self.play_pause_btn = MediaPlayBarButton(FIF.PLAY, self)
237
self.stop_btn = MediaPlayBarButton(FIF.STOP, self)
238
self.next_btn = MediaPlayBarButton(FIF.NEXT, self)
239
240
# Progress controls
241
self.position_slider = Slider(Qt.Horizontal, self)
242
self.position_slider.setFixedHeight(20)
243
244
# Time labels
245
self.current_time_label = CaptionLabel("00:00")
246
self.duration_label = CaptionLabel("00:00")
247
248
# Volume controls
249
self.volume_btn = MediaPlayBarButton(FIF.VOLUME, self)
250
self.volume_slider = Slider(Qt.Horizontal, self)
251
self.volume_slider.setRange(0, 100)
252
self.volume_slider.setValue(70)
253
self.volume_slider.setFixedWidth(100)
254
255
# Add to control layout
256
control_layout.addWidget(self.prev_btn)
257
control_layout.addWidget(self.play_pause_btn)
258
control_layout.addWidget(self.stop_btn)
259
control_layout.addWidget(self.next_btn)
260
control_layout.addStretch()
261
control_layout.addWidget(self.current_time_label)
262
control_layout.addWidget(self.position_slider, 1)
263
control_layout.addWidget(self.duration_label)
264
control_layout.addStretch()
265
control_layout.addWidget(self.volume_btn)
266
control_layout.addWidget(self.volume_slider)
267
268
# Playlist area
269
self.playlist_widget = ListWidget(self)
270
self.playlist_widget.setMaximumHeight(150)
271
272
# Add to main layout
273
layout.addLayout(title_bar)
274
layout.addWidget(self.video_widget, 1)
275
layout.addLayout(control_layout)
276
layout.addWidget(self.playlist_widget)
277
278
def setupMediaPlayer(self):
279
# Media player
280
self.player = QMediaPlayer(self)
281
self.player.setVideoOutput(self.video_widget)
282
283
# Playlist
284
self.playlist = QMediaPlaylist(self)
285
self.player.setPlaylist(self.playlist)
286
287
# Position update timer
288
self.position_timer = QTimer(self)
289
self.position_timer.timeout.connect(self.update_position)
290
self.position_timer.start(100) # Update every 100ms
291
292
def setupConnections(self):
293
# Player signals
294
self.player.stateChanged.connect(self.on_state_changed)
295
self.player.positionChanged.connect(self.on_position_changed)
296
self.player.durationChanged.connect(self.on_duration_changed)
297
self.player.volumeChanged.connect(self.on_volume_changed)
298
299
# Control connections
300
self.play_pause_btn.clicked.connect(self.toggle_playback)
301
self.stop_btn.clicked.connect(self.player.stop)
302
self.prev_btn.clicked.connect(self.playlist.previous)
303
self.next_btn.clicked.connect(self.playlist.next)
304
305
# Slider connections
306
self.position_slider.sliderPressed.connect(self.on_position_slider_pressed)
307
self.position_slider.sliderReleased.connect(self.on_position_slider_released)
308
self.volume_slider.valueChanged.connect(self.player.setVolume)
309
310
# Playlist connections
311
self.playlist_widget.itemDoubleClicked.connect(self.play_selected_item)
312
313
def add_media_file(self, file_path: str):
314
"""Add media file to playlist"""
315
media_content = QMediaContent(QUrl.fromLocalFile(file_path))
316
self.playlist.addMedia(media_content)
317
318
# Add to playlist widget
319
file_name = os.path.basename(file_path)
320
self.playlist_widget.addItem(file_name)
321
322
def toggle_playback(self):
323
"""Toggle between play and pause"""
324
if self.player.state() == QMediaPlayer.PlayingState:
325
self.player.pause()
326
else:
327
self.player.play()
328
329
def on_state_changed(self, state):
330
"""Handle player state changes"""
331
if state == QMediaPlayer.PlayingState:
332
self.play_pause_btn.setIcon(FIF.PAUSE.icon())
333
else:
334
self.play_pause_btn.setIcon(FIF.PLAY.icon())
335
336
def on_position_changed(self, position):
337
"""Handle position changes"""
338
if not self.position_slider.isSliderDown():
339
self.position_slider.setValue(position)
340
341
self.current_time_label.setText(self.format_time(position))
342
343
def on_duration_changed(self, duration):
344
"""Handle duration changes"""
345
self.position_slider.setRange(0, duration)
346
self.duration_label.setText(self.format_time(duration))
347
348
def on_volume_changed(self, volume):
349
"""Handle volume changes"""
350
self.volume_slider.setValue(volume)
351
352
# Update volume icon
353
if volume == 0:
354
self.volume_btn.setIcon(FIF.MUTE.icon())
355
elif volume < 50:
356
self.volume_btn.setIcon(FIF.VOLUME.icon())
357
else:
358
self.volume_btn.setIcon(FIF.VOLUME.icon())
359
360
def on_position_slider_pressed(self):
361
"""Handle position slider press"""
362
self.position_timer.stop()
363
364
def on_position_slider_released(self):
365
"""Handle position slider release"""
366
self.player.setPosition(self.position_slider.value())
367
self.position_timer.start()
368
369
def play_selected_item(self, item):
370
"""Play selected playlist item"""
371
row = self.playlist_widget.row(item)
372
self.playlist.setCurrentIndex(row)
373
self.player.play()
374
375
def format_time(self, milliseconds):
376
"""Format time in MM:SS format"""
377
seconds = milliseconds // 1000
378
minutes = seconds // 60
379
seconds = seconds % 60
380
return f"{minutes:02d}:{seconds:02d}"
381
382
def update_position(self):
383
"""Update position display"""
384
if self.player.state() == QMediaPlayer.PlayingState:
385
position = self.player.position()
386
if not self.position_slider.isSliderDown():
387
self.position_slider.setValue(position)
388
389
# Usage
390
media_player = FluentMediaPlayer()
391
media_player.add_media_file("video1.mp4")
392
media_player.add_media_file("audio1.mp3")
393
media_player.show()
394
```
395
396
## Advanced Features
397
398
### Custom Media Controls
399
400
```python
401
class CustomMediaControls(QWidget):
402
def __init__(self, player: QMediaPlayer, parent=None):
403
super().__init__(parent)
404
self.player = player
405
self.setupUi()
406
407
def setupUi(self):
408
layout = QHBoxLayout(self)
409
410
# Playback speed control
411
speed_combo = ComboBox(self)
412
speed_combo.addItems(["0.5x", "0.75x", "1.0x", "1.25x", "1.5x", "2.0x"])
413
speed_combo.setCurrentText("1.0x")
414
speed_combo.currentTextChanged.connect(self.change_playback_speed)
415
416
# Quality selection
417
quality_combo = ComboBox(self)
418
quality_combo.addItems(["Auto", "1080p", "720p", "480p", "360p"])
419
420
# Fullscreen button
421
fullscreen_btn = ToolButton(FIF.FULL_SCREEN, self)
422
fullscreen_btn.clicked.connect(self.toggle_fullscreen)
423
424
layout.addWidget(QLabel("Speed:"))
425
layout.addWidget(speed_combo)
426
layout.addWidget(QLabel("Quality:"))
427
layout.addWidget(quality_combo)
428
layout.addStretch()
429
layout.addWidget(fullscreen_btn)
430
431
def change_playback_speed(self, speed_text):
432
speed = float(speed_text.replace('x', ''))
433
self.player.setPlaybackRate(speed)
434
```
435
436
### Playlist Management
437
438
```python
439
class PlaylistManager:
440
def __init__(self, playlist: QMediaPlaylist, list_widget: ListWidget):
441
self.playlist = playlist
442
self.list_widget = list_widget
443
self.media_files = []
444
445
def add_files(self, file_paths: List[str]):
446
for file_path in file_paths:
447
self.add_file(file_path)
448
449
def add_file(self, file_path: str):
450
media = QMediaContent(QUrl.fromLocalFile(file_path))
451
self.playlist.addMedia(media)
452
self.media_files.append(file_path)
453
454
# Add to UI
455
file_name = os.path.basename(file_path)
456
self.list_widget.addItem(file_name)
457
458
def remove_current(self):
459
current_index = self.playlist.currentIndex()
460
if current_index >= 0:
461
self.playlist.removeMedia(current_index)
462
self.media_files.pop(current_index)
463
self.list_widget.takeItem(current_index)
464
465
def shuffle(self):
466
self.playlist.shuffle()
467
468
def set_repeat_mode(self, mode: QMediaPlaylist.PlaybackMode):
469
self.playlist.setPlaybackMode(mode)
470
```
471
472
## Error Handling and Validation
473
474
```python
475
def handle_media_errors(self):
476
"""Handle media player errors"""
477
self.player.error.connect(self.on_media_error)
478
479
def on_media_error(self, error):
480
"""Handle media playback errors"""
481
error_messages = {
482
QMediaPlayer.NoError: "No error",
483
QMediaPlayer.ResourceError: "Resource error - file not found or corrupted",
484
QMediaPlayer.FormatError: "Format error - unsupported media format",
485
QMediaPlayer.NetworkError: "Network error - connection failed",
486
QMediaPlayer.AccessDeniedError: "Access denied - insufficient permissions",
487
QMediaPlayer.ServiceMissingError: "Service missing - codec not available"
488
}
489
490
message = error_messages.get(error, f"Unknown error: {error}")
491
492
# Show error dialog
493
error_dialog = MessageBox("Media Error", message, self)
494
error_dialog.exec()
495
```
496
497
## Best Practices
498
499
### Performance Optimization
500
501
1. **Use appropriate video resolution** for display size
502
2. **Implement buffering indicators** for network streams
503
3. **Handle large playlists efficiently** with lazy loading
504
4. **Optimize UI updates** during playback
505
506
### User Experience
507
508
1. **Provide keyboard shortcuts** for common actions
509
2. **Remember user preferences** (volume, position, etc.)
510
3. **Support drag-and-drop** for adding media files
511
4. **Implement proper fullscreen handling**
512
513
### Accessibility
514
515
1. **Add tooltips** to all control buttons
516
2. **Support keyboard navigation** through controls
517
3. **Provide audio descriptions** when available
518
4. **Respect system accessibility settings**