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
相关产品推荐
相关产品推荐

