从 0 到 1 ,手搓一个自己的绿色版视频播放器
想看的视频格式太杂,Windows 自带播放器不认;装个播放器吧,总夹带广告、全家桶。不如自己动手,写一个干净、绿色、想加什么功能就加什么的播放器。本文全程记录我踩过的坑和实现细节。
一、为什么自己写一个播放器?
你有没有遇到过这些情况:
- 下载了一个 .mkv / .rmvb / .ts,系统自带播放器直接罢工;
- 主流播放器功能是强,但安装包捆绑、开机自启、各种弹窗;
- 想要"断点续播、自动连播下一集、双击全屏、倍速"这些贴心功能,却没一个完全贴合自己的习惯;
- 有的播放器连"打开文件就自动把同目录同格式的一起列出来"这种基本需求都做不到。
自己动手的好处:只保留你真正需要的功能,不想要的一行都不要。没有广告、没有捆绑、没有后台常驻,整个程序拷走就能用。

二、技术选型:为什么是 Qt + libVLC?
视频播放器的核心是解码。自己从零写解码器不现实,业界成熟方案是 FFmpeg,而 libVLC 正是基于 FFmpeg 的高层播放引擎,把解码、渲染、音频输出都封装好了,我们只需专注做界面。
方案
优点
缺点
C+ WPF
界面开发快、生态熟
音视频编解码要额外集成第三方库
Electron
跨平台、UI 漂亮
打包体积大(100MB+)、吃内存
C++ + Qt + libVLC(本文)
体积小、解码强、绿色便携
需要自己搭编译环境
libVLC 底层就是 FFmpeg,mp4 / mpeg / ts / mov / rm / rmvb / mkv / avi / flv 等格式通吃,rm 系列(RealVideo)也无需额外折腾,省心。
最关键是绿色部署:程序 = 你的 exe + libvlc.dll + libvlccore.dll + plugins/ 解码插件文件夹。整个目录拷走就能跑,无需安装、无注册表残留、无系统服务。
运行环境:基于 Qt 5.15 + MinGW 8.1 构建,兼容 Windows 7 / 8 / 8.1 / 10 / 11(64 位),解压即用,无需额外安装运行时。
为什么不直接用官方 VLC 或 FFplay?
官方 VLC 够用,但界面是别人定的,想加"断点续播、连播"要改它的逻辑;FFplay 是命令行工具,没有界面。自己写,界面和交互 100% 由你掌控。
三、搭建骨架
项目结构尽量清晰,每个类职责单一:
KzhPlayer/
├── CMakeLists.txt
# 自动探测 Qt(5/6) + VLC SDK
├── src/
│ ├── main.cpp
# 入口,开启高分屏缩放、支持命令行传参
│ ├── MainWindow.h/.cpp
# 主窗口 + 控制栏 + 播放列表界面
│ ├── Player.h/.cpp
# libVLC 封装(播放/进度/音量/倍速/事件)
│ ├── Playlist.h/.cpp
# 播放列表(上/下一集、循环)
│ ├── VideoWidget.h/.cpp
# 视频画面控件(绘制每帧)
│ └── SeekSlider.h/.cpp
# 点击进度条直接跳转
核心设计:把 libVLC 的 C 接口封装成 Qt 风格
Player 把所有 libVLC 调用封装起来,界面层完全不用碰 C 接口:
// 打开并播放
if
(!m_player->
open
(path))
return
;
m_player->play();
// 进度条跳转
m_player->setPosition(value /
1000.0f
);
// 倍速
m_player->setRate(rate);
// 音量
m_player->setVolume(volume);
// 播放结束自动下一集(事件回调)
connect(m_player, &Player::endReached,
this
, &MainWindow::onEndReached);
关键点 1:视频画面如何显示?
两种主流方式:
- set_hwnd 嵌入:让 VLC 直接把画面画进窗口控件。简单,但 VLC 会接管视频区域的鼠标事件,导致"双击全屏""点击进度条"等交互全部失效。
- 帧回调 + Qt 绘制(本文采用):让 libVLC 把解码出的每一帧 RGB 数据通过回调交给我们,Qt 自己画。鼠标事件完全由 Qt 处理,交互 100% 可控。
// 注册帧回调
libvlc_video_set_callbacks(m_player, lock, unlock, display,
this
);
libvlc_video_set_format(m_player, ”RV32”, width, height, width *
4
);
// 每一帧通过信号投递到 GUI 线程
connect(m_player, &Player::frameReady,
this
, [
this
]() {
m_videoWidget->setFrame(m_player->currentFrame());
});
关键点 2:进度条"点哪跳哪"
Qt 自带的 QSlider 点击轨道,默认只按 pageStep 挪一小步(不是跳到点击位置)。要实现"点哪跳哪",需要继承重写 mousePressEvent:
void
SeekSlider
::
mousePressEvent
(QMouseEvent *event) {
if
(event->
button
() ==
Qt
::
LeftButton
&&
orientation
() ==
Qt
::
Horizontal
) {
// 计算滑块句柄区域,若点在轨道空白处则直接跳到点击位置
QStyleOptionSlider opt;
initStyleOption
(&opt);
QRect handle =
style
()->
subControlRect
(
QStyle
::
CC_Slider
, &opt,
QStyle
::
SC_SliderHandle
, this);
if
(!handle.
contains
(event->
pos
())) {
double
ratio =
double
(event->
pos
().
x
()) /
width
();
setValue
(
minimum
() +
int
((
maximum
() -
minimum
()) * ratio));
emit
seekTo
(
value
());
// 触发跳转
return
;
}
}
QSlider
::
mousePressEvent
(event);
}
四、踩过的几个坑(真实经验)
坑 1:--plugin-path参数已废弃VLC 3.x 会自动在 exe 同级查找 plugins/ 目录。传这个参数反而报 option no longer exists,去掉即可。之前还因此踩了个内存 bug:QString::toUtf8().constData() 拿到的是临时对象的指针,语句结束就被销毁,导致插件路径是垃圾值。
坑 2:中文路径打不开libvlc_media_new_path 对非 ASCII 路径不可靠。改用 QUrl::fromLocalFile 转成 file:/// 形式,再交给 libvlc_media_new_location,中文文件名就正常了。
坑 3:进度条"点哪跳哪"不生效就是上面说的 pageStep 问题,用自定义 SeekSlider 解决。
坑 4:全屏界面要"磨砂悬浮"进全屏后控制栏做成半透明渐变 + 自动隐藏:鼠标一动显示,2.5 秒不动自动消失,和系统自带播放器一个体验。
坑 5:命令行黑窗CMake 里没设 WIN32_EXECUTABLE,exe 默认是控制台子系统,每次启动都弹黑窗。加一行 set_target_properties(KzhPlayer PROPERTIES WIN32_EXECUTABLE TRUE) 解决。
五、功能一览(详)
1. 播放与列表
- 打开文件 / 打开文件夹:工具栏两个按钮。打开一个文件后,自动把同目录下同格式的视频全加进播放列表,上/下集无缝切换(按文件名排序,且同一文件不会重复添加);
- 四种播放模式:顺序播放 / 单曲循环 / 列表循环 / 随机播放;
- 播放结束自动连播下一集:用 VLC 的 MediaPlayerEndReached 事件回调触发,无需轮询;
- 断点续播:用 QSettings 按文件路径哈希作键,记录每部视频的播放进度,下次打开自动接着播;开头/结尾位置不保存,避免误续播;
- 记忆上次会话:记住窗口位置/大小、上次播放列表、上次播放的文件,启动直接恢复并自动续播。
2. 全屏与界面
- 双击画面 = 全屏 / 退出全屏,Esc 也能退出,进全屏后自动隐藏鼠标;
- 全屏时控制栏为磨砂半透明(渐变半透明底 + 细边框高光),鼠标一动显示,2.5 秒无操作自动隐藏;
- 磨砂效果同样应用于顶部标题栏,界面统一。
3. 进度与倍速
- 进度条点哪跳哪:点击轨道任意位置直接跳到对应时间(重写 SeekSlider::mousePressEvent,绕开 QSlider 默认的 pageStep 步进);
- 拖拽进度条实时跳转,松开精确定位;
- 倍速:0.5x / 1.0x / 1.5x / 2.0x 可调。
4. 快捷键
按键
功能
空格
播放 / 暂停
← / →
快退 / 快进 5 秒
↑ / ↓
音量加 / 减
Esc
退出全屏
小键盘 4 / 6
画面左移 / 右移
小键盘 8 / 2
画面上移 / 下移
小键盘 + / -
画面放大 / 缩小(1~5 倍)
5. AB 段重复(重点新功能)
用于反复练习某一片段(比如学外语、练舞蹈、看教学视频):
- 播放到起点时点控制栏 A 按钮 → 记录 A 点,进度条上出现青绿色标记线;
- 播放到终点时点 B 按钮 → 记录 B 点并开启循环,进度条上出现橙色标记线;
- 之后播放到 B 点会自动跳回 A 点,在 A~B 之间循环播放;
- 再次点 A 可清除 AB 循环,两条标记线消失;
- 切换文件时自动清除上一部的 AB 状态。
实现要点:A/B 点以毫秒记录,放在 onTick 里判断——pos >= B 时用 set_time 跳回 A。用 m_abRewound 标志做"重新武装",避免跳回 A 后因 VLC 的 get_time 滞后而连续重复触发,保证每轮只跳一次、循环干净。
6. 画面平移 / 缩放
用小键盘可在播放时对画面进行平移和缩放(适合局部放大看细节、看画面边角):
- +放大、-缩小,以画面中心为基准,范围 1-5 倍
- 小键盘 4/6/8/2 左/右/上/下平移画面;
- 底层在 VideoWidget::paintEvent 中,先按窗口等比缩放,再叠加缩放倍数与平移偏移绘制,不影响播放控制。
// 断点续播:媒体就绪后跳到上次位置
void
MainWindow
::
onMediaPlaying
() {
if
(m_resumeFraction >
0.
001f) {
float f = m_resumeFraction;
m_resumeFraction = -
1.
0f;
// 只恢复一次
m_player->
setPosition
(f);
}
}
六、绿色版部署与瘦身
把下面内容放进同一个文件夹,拷走即绿色版:
KzhPlayer.exe
libvlc.dll
libvlccore.dll
plugins/ ← VLC 的解码插件
plugins/ 必须存在,否则无法解码。
瘦身:完整 VLC 插件默认占130 多 MB,其中很多我们用不到:
- 删 gui(我们有自己的界面)、access_output(不串流输出)、stream_out(不转码推流)、mux(不封装保存);
- access 只留本地文件模块 filesystem,删掉全部网络/光驱/抓屏模块;
- video_output 只留帧回调必需的 vmem,删掉 D3D/GL 显示模块;
- 删 visualization、meta_engine、services_discovery、control 等。
实测删除后plugins 从 132MB 降到 76MB,且 mp4 / mov / mkv 三种格式均正常解码播放。codec / demux 是支持各种格式的核心,不能动。
七、试试看
一键编译(推荐)
仓库内自带build.cmd,双击或命令行运行即可完成「CMake 配置 → 编译 → 复制 exe 到 dist\KzhPlayer\」:
build.cmd
脚本默认使用 D:\Qt\5.15.2\mingw81_64(Qt)与 D:\Qt\Tools\mingw810_64(MinGW 8.1),若路径不同,改脚本开头的 QT_ROOT / MINGW_ROOT 即可。脚本为纯 ASCII,避免 cmd 中文编码乱码问题。
编译产物在 dist\KzhPlayer\KzhPlayer.exe,若需打包 zip:
Compress-Archive -
Path
dist/KzhPlayer
/* -DestinationPath dist/KzhPlayer.zip -Force
手动构建
构建(需 CMake + Qt + VLC SDK):
cmake
-S . -B build -DCMAKE_PREFIX_PATH=”你的Qt安装路径”
cmake --build build
命令行直接播:
KzhPlayer.exe ”D:\视频\追剧.mp4”
打包好的播放器,直接解压即可使用:
https
://ydjy-
1369590239
.cos.ap-nanjing.myqcloud.com/uploads/
20260808
/
1786158445781522352
.zip
八、下一步还能做什么
- 自动加载字幕(.srt / .ass)并支持轨道切换;
- 截屏、画面比例/旋转调节;
- 硬件加速(GPU 硬解),4K 高码率更省 CPU;
- 更精细的倍速(0.1 步进)。
自己写播放器的乐趣在于:每个功能都长成你想要的样子。代码已开源,欢迎一起折腾。
仓库地址:https://gitee.com/ydxjyjkzh/kzhplayer
温馨提示
知识产权声明:本软件已获国家版权局软件著作权登记(登记号:2022SR0558725),受《计算机软件保护条例》保护。未经书面授权,严禁对本软件进行反向工程、反编译、破解或任何形式的篡改。侵权必究。
官方指引:本文档为官方安装部署说明,仅适用于当前发布版本,后续版本请以最新官方文档为准。
环境要求:安装前请确认操作系统版本、运行环境(如 .NET、Java 等)及硬件配置满足软件运行要求,避免因环境不兼容导致异常。
操作风险与免责:安装配置涉及防火墙、注册表或环境变量等系统级变更,建议由具备相关经验的技术人员操作。因用户未严格遵循本官方指引或操作不当导致的任何数据丢失、系统异常或其他损失,我方不承担相关责任。如遇问题,请及时联系技术支持。
反馈渠道:如有未覆盖的问题,欢迎通过客服反馈,我们将持续更新与改进。
版本记录:最后更新于 2026-08-22