QMediaPlayer 无法播放 mp3 文件并且不发出 mediaStatusChanged(QMediaPlayer::EndOfMedia) 信号

问题描述 投票:0回答:1

我正在编写一个程序(使用Qt 6.5.1,在M1 Mac上),需要播放多个mp3文件(一个接一个)。我使用以下代码遇到了错误:

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();
}

当这个函数被调用(多次)时,经常会遇到

player
挂起并且不发出 mediaStatusChanged(QMediaPlayer::EndOfMedia) 信号的问题。
player
仍处于
playing
状态,但没有进展。计算机没有声音(出现故障后)。然后,如果我打开另一个播放声音的程序,我可以听到我的程序正在重复声音(它挂起的位置,可能是最后 100 毫秒)。

这是我的程序的一些输出,我们可以看到在

QMediaPlayer::BufferedMedia
之后,没有
QMediaPlayer::EndOfMedia
(预期,因为播放器挂起)。

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.

我添加了代码来检查播放器状态并且它正在播放,但position() 没有改变。 我尝试避免新建/删除 QMediaPlayer、QAudioOutput,但没有成功。 或者,我使用以下代码用 python 播放 mp3 文件,一切都按预期工作。


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();
}

有什么想法吗?

qt mp3 qmediaplayer
1个回答
0
投票

而不是

connect(player, &QMediaPlayer::mediaStatusChanged, this, [this, player](QMediaPlayer::MediaStatus status) {
    qDebug() << status;
    if (status == QMediaPlayer::EndOfMedia)
    {
        FinishWait();
    }
});

我用过

connect(player, &QMediaPlayer::mediaStatusChanged, player, [this](QMediaPlayer::MediaStatus status) {
    qDebug() << status;
    if (status == QMediaPlayer::EndOfMedia)
    {
        FinishWait();
    }
});

这对我有用。 输出看起来像

QMediaPlayer::LoadingMedia
QMediaPlayer::BufferedMedia
QMediaPlayer::LoadedMedia

媒体播放完毕后,控制台显示如下

QMediaPlayer::EndOfMedia

Qt 6.5、Windows 11

© www.soinside.com 2019 - 2024. All rights reserved.