Chapter 27. Multimedia

This chapter reveals how multimedia in Qt6 stops being “magic” and becomes a manageable tool: you’ll discover non-obvious nuances of low latency, asynchronous duration, and proper component binding that professional developers use to avoid spending hours on “why isn’t it playing”.

It covers 3 key componentsQSoundEffect for instant effects, QMediaPlayer + QAudioOutput for music/streaming, and QVideoWidget for video, plus careful error handling via errorOccurred() and practical lambda connections.

Skip this chapter — and you’ll step on the typical Qt6 multimedia pitfalls again when your project is already close to release.

This chapter includes ready-to-use code examples.

Chapter Self-Check

Why can’t you call duration() immediately after setSource() in QMediaPlayer in Qt6?Answer
Correct answer: Duration is obtained asynchronously to improve efficiency and avoid blocking the program when loading files. You must use the durationChanged() signal to correctly obtain the value.
Why can’t QMediaPlayer in Qt6 play sound without additional objects?Answer
Correct answer: QMediaPlayer by itself doesn’t play sound—it requires QAudioOutput, which is set via setAudioOutput(). This is an architectural change in Qt6 for greater flexibility in output management.
In what units is volume measured in the QAudioOutput::setVolume() method in Qt6, and why is this important to consider?Answer
Correct answer: Volume is set from 0.0 to 1.0 (floating-point), not from 0 to 100. When passing values from controls (QDial), you need to divide by 100.0 for correct operation.
How does the QSoundEffect class differ from QMediaPlayer in terms of application?Answer
Correct answer: QSoundEffect is designed for quick playback of short sound effects (notifications, clicks) with low latency, supporting only WAV. QMediaPlayer—for full playback of audio/video in various formats with extended control.
Why are two separate signals used in Qt6: playbackStateChanged() and mediaStatusChanged()?Answer
Correct answer: playbackStateChanged() tracks playback state (play/pause/stop), while mediaStatusChanged()—media loading stages (loading, buffering, completion). This allows separate handling of playback control and content loading process.
What happens if you try to play a file format for which the system has no codec?Answer
Correct answer: QMediaPlayer will generate a FormatError via the errorOccurred() signal, as playback capabilities are limited by the operating system’s codecs. Proper error handling is necessary to inform the user.
Why does the video player in the example inherit from the audio player class rather than being created from scratch?Answer
Correct answer: QMediaPlayer is a high-level class supporting both audio and video. To add video capabilities, it’s sufficient to create a QVideoWidget and set it via setVideoOutput(), all controls remain identical.
What role does QMediaCaptureSession play when working with a camera?Answer
Correct answer: QMediaCaptureSession coordinates media capture from the device (camera) and sending to output (QVideoWidget). It links the source (QCamera) with the destination and manages the data flow between them.
Why is a switch construct with playbackState() check used in the slotPlay() method?Answer
Correct answer: One button performs two functions: starts playback and pauses. State checking allows calling pause() during playback and play() in all other cases, providing convenient toggling.
Why can’t you rely entirely on sound as the only means of notifying the user in an application?Answer
Correct answer: Sound on the computer is often disabled by the user, so critically important information must be duplicated visually. Sound should be used as an additional channel, but not the only means of communication.
What three objects need to be created to record video from a camera to a file?Answer
Correct answer: QCamera (camera capture), QMediaCaptureSession (data flow coordination), and QMediaRecorder (encoding and file writing). QMediaRecorder is attached to the session via setRecorder().
What needs to be configured in QMediaRecorder before starting recording to control output file quality?Answer
Correct answer: File format and codecs via QMediaFormat (container, video/audio codecs), encoding parameters via EncodingParameters (resolution, fps, bitrate), and save location via setOutputLocation().
Why does the SoundPlayer class store a pointer to QVBoxLayout as a class member?Answer
Correct answer: For the ability to extend the interface in derived classes. For example, VideoPlayer adds a QVideoWidget to this layout without rewriting the entire element layout structure.
Why is a lambda function used to handle volume changes in the audio player example?Answer
Correct answer: For value conversion: QDial passes int (0-100), while QAudioOutput::setVolume() accepts float (0.0-1.0). Lambda allows performing division by 100.0 directly in connect() without creating a separate slot.
What advantage does using QSoundEffect::Infinite for setLoopCount() provide?Answer
Correct answer: Provides infinite looping playback of sound (e.g., for background music or continuous effects) without needing to manually restart playback via completion signals.

Practical Exercises

Easy Level

Sound Effects for Interface Events
Create an application with three buttons. Each button press should play its unique sound effect (use short WAV files). Add a slider to adjust the volume of all sound effects simultaneously.
Hints: Use the QSoundEffect class for each sound. Create three QSoundEffect objects and load different WAV files via setSource(). Connect a QSlider with range 0-100 to a slot that will set the volume for all effects, dividing the value by 100.0. Don’t forget to call play() in the button handlers.

Medium Level

Mini-Playlist with Auto-Play
Extend the audio player example from the chapter: add the ability to load multiple files into a list (QListWidget). When the current track finishes, the player should automatically move to the next one in the list. Implement “Previous” and “Next” buttons for playlist navigation.
Hints: Use the mediaStatusChanged() signal with EndOfMedia status check to detect track completion. Store the file list and current index. When switching tracks, call setSource() with the new file. QListWidget::currentRow() and setCurrentRow() will help with selection synchronization. Handle cases of reaching the end/beginning of the list.

Hard Level

Simple Video Editor with Preview and Recording
Create an application that captures video from a webcam, displays it in real-time, and allows starting/stopping file recording. Add the ability to play back the last recording via a built-in video player. Implement recording resolution settings (720p/1080p) and a recording time indicator.
Hints: Use QCamera, QMediaCaptureSession, QVideoWidget for preview, and QMediaRecorder for recording. One QMediaCaptureSession can simultaneously output to QVideoWidget and record via QMediaRecorder. For playback, create a second QMediaPlayer with a separate QVideoWidget. Use QTimer to update the recording time counter. QMediaRecorder::recorderStateChanged() will help track start/end of recording. Configure EncodingParameters before starting recording.

💬 Join the Discussion!

Created your first multimedia player? Have questions about asynchronous QMediaPlayer operations or video recording?

Share your experience integrating multimedia into applications, discuss the nuances of handling different formats, or help other readers understand camera and recording!

Leave a Reply

Your email address will not be published. Required fields are marked *