You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Qt 6.5.1(M1 Mac)QMediaPlayer播放MP3无EndOfMedia信号异常

问题分析与解决方案

核心问题:对象生命周期管理错误

你的PlayMp3FileWithMediaPlayer函数存在致命的对象生命周期问题:函数末尾直接调用player->setAudioOutput(nullptr);和player->deleteLater();,导致QMediaPlayer对象在播放流程尚未完成时就被标记销毁。后续的播放状态回调、音频输出都会因为对象被提前回收而出现异常,这是卡顿、无法触发EndOfMedia信号的直接原因。

解决方案步骤

1. 修正播放器对象的生命周期

修改代码,仅在播放完成或出错时销毁QMediaPlayer,确保播放流程完整执行:

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, [player]() {
        player->play();
        qDebug() << "Playing:" << player->source();
    });

    connect(player, &QMediaPlayer::errorChanged, this, [this, player]() {
        qDebug() << player->error() << player->errorString();
        FinishWait();
        player->setAudioOutput(nullptr);
        player->deleteLater();
    });

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

    QTimer::singleShot(0, this, [player, audio_file]() {
        player->setSource(QUrl::fromLocalFile(audio_file));
    });

    qDebug() << "Going to play:" << audio_file;
    StartWait();
}

2. 修复MP3文件的时间戳异常

日志中出现的[mp3float @ ...] Could not update timestamps for skipped samples提示MP3文件存在时间戳错误,这会导致Qt媒体解析器无法正确识别播放结束点。可以用ffmpeg重新编码修复:

ffmpeg -i 原文件.mp3 -c:a libmp3lame -q:a 2 修复后文件.mp3

3. 指定M1 Mac专属音频后端

Qt 6.5.1在M1 Mac上的默认音频后端可能存在兼容性问题,可强制指定CoreAudio后端:
在程序启动时添加以下代码:

#include <QMediaDevices>

void SetupAudioBackend() {
    QMediaDevices::setAudioBackend("coreaudio");
}

4. 正确复用播放器对象(可选优化)

如果需要复用QMediaPlayer和QAudioOutput,确保每次播放前重置状态:

// 成员变量声明:QMediaPlayer *player_; QAudioOutput *audio_output_;

void MainWindow::InitPlayer() {
    audio_output_ = new QAudioOutput(this);
    player_ = new QMediaPlayer(this);
    player_->setAudioOutput(audio_output_);

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

    connect(player_, &QMediaPlayer::errorChanged, this, [this]() {
        qDebug() << player_->error() << player_->errorString();
        FinishWait();
    });
}

void MainWindow::PlayMp3FileWithMediaPlayer(const QString &audio_file) {
    if (player_->playbackState() == QMediaPlayer::PlayingState) {
        player_->stop();
    }
    player_->setSource(QUrl::fromLocalFile(audio_file));
    player_->play();
    qDebug() << "Playing:" << audio_file;
    StartWait();
}

内容的提问来源于stack exchange,提问作者Huafeng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 02:02:08