If you've been working with QMediaPlayer in PyQt5 on Windows, you might have noticed something frustrating: the .duration() method returns completely wrong values for MP3 files. The reported duration is often much longer than the actual length of the track. On top of that, some audio files fail to load entirely, even though other Python audio libraries handle them without any trouble.
The good news is that this isn't a bug in your code. It's a known quirk of how Qt handles multimedia on Windows, and there's a straightforward fix.
Why does this happen?
Qt's multimedia framework on Windows supports two different backend plugins:
- DirectShow — the legacy Windows multimedia API
- Windows Media Foundation (WMF) — the modern replacement
For historical reasons (partly related to camera support), the DirectShow backend tends to be selected by default. Unfortunately, the DirectShow backend has known issues with duration reporting and limited format support. That's why your durations come back wrong, and why some files won't play at all.
The fix: switch to Windows Media Foundation
You can tell Qt to use the Windows Media Foundation backend instead by setting an environment variable before you create your QApplication instance. This is important — the environment variable needs to be set before Qt initializes its multimedia system.
Add these two lines at the very top of your script, before any PyQt5 imports:
import os
os.environ['QT_MULTIMEDIA_PREFERRED_PLUGINS'] = 'windowsmediafoundation'
The placement matters here. If you set this variable after importing PyQt5 multimedia modules or after creating the QApplication, Qt may have already chosen the DirectShow backend and your setting will be ignored.
A complete working example
Here's a full example showing the correct placement. Notice that the os.environ line comes before all PyQt5 imports:
import os
os.environ['QT_MULTIMEDIA_PREFERRED_PLUGINS'] = 'windowsmediafoundation'
import sys
from PyQt5.QtWidgets import QMainWindow, QApplication
from PyQt5.QtCore import QUrl
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.player = QMediaPlayer()
self.player.durationChanged.connect(self.print_duration)
self.player.error.connect(self.handle_error)
# Replace this with the path to your own audio file.
path_to_file = "my_song.mp3"
url = QUrl.fromLocalFile(path_to_file)
self.player.setMedia(QMediaContent(url))
self.show()
def print_duration(self, duration):
# Duration is reported in milliseconds.
seconds = duration // 1000
minutes = seconds // 60
remaining_seconds = seconds % 60
print(f"Duration: {minutes}:{remaining_seconds:02d} ({duration} ms)")
def handle_error(self):
print(f"Error: {self.player.errorString()}")
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
app.exec_()
Replace "my_song.mp3" with the actual path to an audio file on your system. When you run this, you should see the correct duration printed to the console.
If you're new to building PyQt5 applications, you might want to start with our tutorial on creating your first PyQt window to get familiar with the basics before working with multimedia.
Troubleshooting
If you've added the environment variable and you're still seeing wrong durations, double-check the following:
Is the environment variable set early enough? It must be set before QApplication is created. If you're setting it inside __init__ or after app = QApplication(sys.argv), it's too late. Move it to the very top of your script, before any PyQt5 imports.
Are you running on Windows? This particular issue — and this fix — are specific to Windows. On macOS and Linux, Qt uses different multimedia backends and you typically won't see this problem.
Is your PyQt5 installation complete? Make sure you have the multimedia plugins installed. If you installed PyQt5 via pip, you may also need the PyQt5-sQt5 package, which bundles the required Qt plugins. See our guide on installing PyQt5 on Windows for detailed setup instructions.
Connecting an error handler
Adding an error signal handler (as shown in the example above) is always a good idea when working with QMediaPlayer. If a file fails to load or the backend has a problem, the error signal will fire and give you a human-readable message. Without it, failures can be completely silent, leaving you wondering why nothing is playing.
self.player.error.connect(self.handle_error)
def handle_error(self):
print(f"Error: {self.player.errorString()}")
This small addition can save you a lot of debugging time. For a deeper understanding of how Qt's signal and slot mechanism works — including connecting signals like error and durationChanged — see our signals, slots and events tutorial.
Summary
The incorrect duration reporting in QMediaPlayer on Windows is caused by the legacy DirectShow backend being selected by default. Setting the QT_MULTIMEDIA_PREFERRED_PLUGINS environment variable to windowsmediafoundation at the very top of your script — before any PyQt5 imports — switches Qt to the modern Windows Media Foundation backend, which gives you accurate durations and better format support.
If you want to build a complete multimedia application, take a look at our Python multimedia player example which demonstrates a full-featured audio and video player built with PyQt5.
Create GUI Applications with Python & Qt5 by Martin Fitzpatrick
(PyQt5 Edition) The hands-on guide to making apps with Python — Over 15,000 copies sold!