I am writing a program (using Qt 6.5.1, on M1 Mac) which need to play multiple mp3 files (one by one). I run into a bug with the following code:
void MainWindow::PlayMp3FileWithMediaPlayer(const QString &audio_file)
{
Q_ASSERT(audio_output_ != nullptr);
QMediaPlayer *player = new QMediaPlayer();
player->setAudioOutput(audio_output_);
connect(player, &QMediaPlayer::sourceChanged, this, [this, player]() {
player->play();
qDebug() << "Playing:" << player->source();
//QTimer::singleShot(player->duration(), this, [this]() { FinishWait(); });
});
connect(player, &QMediaPlayer::errorChanged, this, [this, player]() {
qDebug() << player->error() << player->errorString();
if (player->error() != QMediaPlayer::NoError)
{
FinishWait();
}
});
connect(player, &QMediaPlayer::mediaStatusChanged, this, [this, player](QMediaPlayer::MediaStatus status) {
qDebug() << status;
if (status == QMediaPlayer::EndOfMedia)
{
FinishWait();
}
});
QTimer::singleShot(0, this, [this, player, audio_file]() {
player->setSource(QUrl::fromLocalFile(audio_file));
});
qDebug() << "Going to play:" << audio_file;
StartWait();
// const int delay = 10000;
// QTimer::singleShot(delay, player, &QObject::deleteLater);
// QTimer::singleShot(delay, output, &QObject::deleteLater);
player->setAudioOutput(nullptr);
player->deleteLater();
}
When this func is called (multiple times), it quite often runs into problem that the player hangs and does not signal mediaStatusChanged(QMediaPlayer::EndOfMedia). The player is still in playing state, but it's not progressing. And no sound was from the computer (after a glitch). Then if I open a different program which plays a sound, I can hear that my program is repeating the sound (where it hangs, maybe the last 100 milliseconds).
And here's some output from my program, we can see that after QMediaPlayer::BufferedMedia, there's no QMediaPlayer::EndOfMedia (expected, as the player is hanging).
Going to play: "/Users/huafeng/Documents/GitHub/chesstools/GameEditor/move_voices/7.mp3"
QMediaPlayer::LoadingMedia
QMediaPlayer::BufferedMedia
Playing: QUrl("file:///Users/huafeng/Documents/GitHub/chesstools/GameEditor/move_voices/7.mp3")
[mp3float @ 0x1370d45e0] Could not update timestamps for skipped samples.
[mp3float @ 0x1370d45e0] Could not update timestamps for discarded samples.
QMediaPlayer::EndOfMedia
Going to play: "/Users/huafeng/Documents/GitHub/chesstools/GameEditor/move_voices/Nbd4.mp3"
QMediaPlayer::LoadingMedia
QMediaPlayer::BufferedMedia
Playing: QUrl("file:///Users/huafeng/Documents/GitHub/chesstools/GameEditor/move_voices/Nbd4.mp3")
[mp3float @ 0x137158430] Could not update timestamps for skipped samples.
[mp3float @ 0x137158430] Could not update timestamps for discarded samples.
QMediaPlayer::EndOfMedia
Going to play: "/Users/huafeng/Documents/GitHub/chesstools/GameEditor/move_voices/8.mp3"
QMediaPlayer::LoadingMedia
QMediaPlayer::BufferedMedia
Playing: QUrl("file:///Users/huafeng/Documents/GitHub/chesstools/GameEditor/move_voices/8.mp3")
[mp3float @ 0x1370d57f0] Could not update timestamps for skipped samples.
I have add code to check the player state and it's playing, but position() is not changing. I have tried avoiding new/delete QMediaPlayer, QAudioOutput, but no luck. Alternatively, I use the following code to play the mp3 file with python and everything works as expected.
void MainWindow::PlayAudioFile(const QString &unique_move_id, int sentence, const QString &audio_file)
{
PlayMp3FileWithMediaPlayer(audio_file);
//PlayMp3FileWithPython(audio_file);
}
void MainWindow::PlayMp3FileWithPython(const QString &audio_file)
{
QStringList arguments;
arguments << QString(_PROJECT_SRC_DIR_) + "/play_sound_file.py" << audio_file;
QProcess *python_process = new QProcess(this);
python_process->setProgram(python_program_);
python_process->setArguments(arguments);
connect(python_process, &QProcess::finished, this, &MainWindow::FinishWait);
QTimer::singleShot(0, this, [this, python_process]() { python_process->start(); });
StartWait();
python_process->deleteLater();
}
Any idea?
Instead of
I used
And it worked for me. Output looks like
After media playback is finished, the console displays the following
Qt 6.5, Windows 11