[C++] QT6 媒体正常播放但是没有声音的解决方式

Qt6.9 是目前在线安装包能安装的最新完整版本,最近在用该版本开发一个音频播放器,遇到了声音异常的问题。为了探究问题的原因,这里结合不同Qt版本进行分析,最后给出解决方案。

1. 问题

1.1 源代码

在这里我构建一个简单的MainWindow案例,通过拖拽音频文件 (如mp3文件) 到软件上触发音频播放。首先,直接上完整代码,基于QMainWindow建立的三个文件:

  • AudioPlayTest.h
#pragma once
#include <QtWidgets>
#include <QMediaPlayer>
#include <QAudioOutput>

#include <QtWidgets/QMainWindow>
#include "ui_AudioPlayTest.h"

class AudioPlayTest : public QMainWindow
{
    Q_OBJECT

public:
    AudioPlayTest(QWidget *parent = nullptr);

protected:
    void dragEnterEvent(QDragEnterEvent* event) override;
    void dropEvent(QDropEvent* event) override;

private:
    Ui::AudioPlayTestClass ui;
    QMediaPlayer* mediaPlayer;
    QAudioOutput* audioOutput;
};
  • AudioPlayTest.cpp
#include "AudioPlayTest.h"

AudioPlayTest::AudioPlayTest(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    setAcceptDrops(true);
    mediaPlayer = new QMediaPlayer(this);
    audioOutput = new QAudioOutput(this);
    mediaPlayer->setAudioOutput(audioOutput);
    audioOutput->setVolume(0.5);
}

void AudioPlayTest::dragEnterEvent(QDragEnterEvent * event)
{
    if (event->mimeData()->hasUrls())
        event->acceptProposedAction();
}

void AudioPlayTest::dropEvent(QDropEvent* event)
{
    const auto urls = event->mimeData()->urls();
    if (!urls.isEmpty()) {
        const QString filePath = urls[0].toLocalFile();
        mediaPlayer->setSource(QUrl::fromLocalFile(filePath));
        mediaPlayer->play();
    }
}

  • main.cpp
#include "AudioPlayTest.h"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    AudioPlayTest w;
    w.show();
    return a.exec();
}
1.2 问题表现

在上述代码生成可执行文件并运行后,我们可以发现并没有声音出现。此外,如果打开了CMD调试窗口,可以发现错误警告如下:
音频播放警告

2. 分析

查阅参考资料1时,我发现Qt6相对于Qt5的媒体模块有了调整。Qt 6多媒体模块完全放弃了Qt5基于插件的基础结构,它只有一个后端,后端只与操作系统有关,且后端对用户是隐藏的。因此上述的错误,很可能是后端(ffmpeg库)不兼容导致的。为了验证这个猜想,我用另外两个不同的Qt版本进行测试。

2.1 Qt5.15.2 版本测试

为了验证环境没问题,首先回到Qt5。Qt5生成时不需要指定QAudioOutput,也无法指定声音,AudioPlayTest.cpp中的代码修改为

#include "AudioPlayTest.h"
AudioPlayTest::AudioPlayTest(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    setAcceptDrops(true);
    mediaPlayer = new QMediaPlayer(this);
}

void AudioPlayTest::dragEnterEvent(QDragEnterEvent * event)
{
    if (event->mimeData()->hasUrls())
        event->acceptProposedAction();
}

void AudioPlayTest::dropEvent(QDropEvent* event)
{
    const auto urls = event->mimeData()->urls();
    if (!urls.isEmpty()) {
        const QString filePath = urls[0].toLocalFile();
		mediaPlayer->setMedia(QUrl::fromLocalFile(filePath));
        mediaPlayer->play();
    }
}

运行程序,将音频文件拖入软件,声音正常,测试通过!

2.2 Qt6.5.3 版本测试

以上说明环境没问题,应该就是Qt版本的问题。但是卸载重装Qt6.9.0后,依然如此。网上也找了很多解决方案,比如认为Qt 依赖系统可用的音频后端(如 WASAPI)指定失败,需要加上代码"qputenv(“QT_AUDIO_BACKEND”, “wasapi”)"强行指定,又或者用其他音频格式文件(如wav格式)进行测试等等,均未解决。最后干脆,我这边将版本后退一些,以6.5.3为例,结果发现,代码不修改的情况下,测试通过!

2.3 三个不同Qt版本的媒体依赖库对比

对于用到的三个不同版本,用windeployqt工具对依赖库进行打包对比,可以发现三个不同版本软件的差异
三个版本对比
可以发现,Qt6确实把audio里的库封装起来了,Qt6.5.3相较于Qt5.15.2简洁了一些。但是,到了Qt6.9.0版本后,ffmpeg底层等库暴露出来了,软件再度臃肿。

3. 解决方案

根据上述分析,目前最佳的解决方案便是放弃6.9.0版本,直接回退到6.5.3 (其他旧版本还未测试,欢迎朋友们留言交流)。回退到Qt5的代价是需要改动大量代码,不太推荐。另外,我也将这个bug反馈给官方平台了,希望后面的版本能够得到修复。


  1. 《Qt6 C++开发指南》王维波等人著 ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值