为什么要写播放器

学Qt有一段时间了,一直停留在画界面、写按钮的阶段。想找个实际项目练练手,就决定写个视频播放器。看起来简单对吧?不就是放个视频嘛。实际上坑多得超乎想象。

先说结论:最后用Qt的QMediaPlayer + QVideoWidget勉强跑起来了,能播mp4,有播放/暂停/进度条。功能虽然简陋,但踩的坑值得记录一下。

第一个坑:QMediaPlayer的格式支持

文档上说QMediaPlayer支持mp4、avi等常见格式。结果我一跑,黑屏。查了半天才发现,Qt6默认不带媒体后端,需要手动安装qt6-multimedia和对应的gstreamer插件。

# Ubuntu/Debian
sudo apt install qt6-multimedia-dev
sudo apt install gstreamer1.0-plugins-base gstreamer1.0-plugins-good
sudo apt install gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly

装完之后终于能看到画面了。但是!进度条不能拖动。又查了半天,发现是gstreamer版本的问题。总之版本兼容性是个大坑。

第二个坑:信号槽连接

Qt的信号槽机制是核心特性,但新手很容易搞混。比如播放状态改变的信号:

// Qt5写法
connect(player, SIGNAL(stateChanged(QMediaPlayer::State)),
        this, SLOT(onStateChanged(QMediaPlayer::State)));

// Qt6写法(推荐)
connect(player, &QMediaPlayer::stateChanged,
        this, &MainWindow::onStateChanged);

我一开始抄的Qt5的教程,用SIGNAL/SLOT宏,结果Qt6里很多信号签名变了,编译一堆错误。后来全改成函数指针写法才解决。

Qt6里推荐用函数指针连接信号槽,编译期就能检查类型错误,比字符串宏安全得多。

第三个坑:界面布局

想让视频区域自动填满窗口、进度条在底部固定高度、控制按钮居中。听起来简单,用QVBoxLayout和QHBoxLayout嵌套就行。但是当窗口缩放的时候,视频比例会变形。

解决方法是继承QWidget重写resizeEvent,手动计算16:9的区域。或者更简单的办法:

videoWidget->setAspectRatioMode(Qt::KeepAspectRatio);

一行代码搞定。但这一行代码我找了两个小时。

总结

最终成品功能很简单:打开文件、播放/暂停、进度条、音量控制。代码大概300多行,写了一整天(大部分时间在debug)。

主要收获:

学习资源推荐

写这个播放器的过程中,参考了不少资源:

零声教育的教程在Linux.do论坛和Telegram频道都能找到免费分享的版本,搜一下就有。

代码放GitHub了:github.com/qwpweee,有兴趣的可以看看。写得不怎么样,但是能跑。