如何在QtWidget中正确使用Gstreamer实现视频播放
问题根因
你碰到的报错核心是两个逻辑误用,和Gstreamer本身功能无关:
- 日志里出现
DirectShowPlayerService字段,直接证明当前Qt Multimedia加载的是Windows默认的DirectShow播放后端,根本没有调用你链接的Gstreamer库,你写的Gstreamer相关逻辑完全没生效。 QMediaPlayer::setMedia()只接受标准媒体资源URL作为参数,直接把gst-launch-1.0开头的管道命令字符串塞给QUrl,会被DirectShow后端当成非法文件路径解析,自然抛出资源解析失败的错误。另外你注释里写的gst-pipeline开头的传参格式是Qt早期版本的非标准用法,目前已经完全废弃,不要参考。
可落地实现方案
根据自定义Gstreamer管道嵌入QVideoWidget的需求,推荐直接用原生Gstreamer API绑定Qt窗口句柄的方案,完全绕开Qt Multimedia的后端适配坑,可控性最高,步骤如下:
- 首先修正.pro配置,除了链接Gstreamer核心库,还要补充视频overlay相关依赖:
CONFIG += link_pkgconfig PKGCONFIG += gstreamer-1.0 gstreamer-video-1.0 QT += core gui widgets multimedia multimediawidgets
- 代码里不要通过QMediaPlayer传入Gstreamer管道,手动解析管道、绑定QVideoWidget的窗口句柄到Gstreamer的视频sink即可,可运行的最小示例代码如下:
#include <QApplication> #include <QVideoWidget> #include <gst/gst.h> #include <gst/video/videooverlay.h> int main(int argc, char *argv[]) { QApplication a(argc, argv); // 初始化Gstreamer gst_init(&argc, &argv); QVideoWidget *videoWidget = new QVideoWidget; videoWidget->resize(800, 600); videoWidget->show(); // 解析自定义Gstreamer管道,注意sink用qtvideosink适配Qt渲染 GstElement *pipeline = gst_parse_launch( "videotestsrc ! videoconvert ! qtvideosink name=vsink", nullptr ); GstElement *vsink = gst_bin_get_by_name(GST_BIN(pipeline), "vsink"); // 把视频sink的渲染窗口绑定到QVideoWidget的句柄 gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(vsink), (std::size_t)videoWidget->winId()); gst_object_unref(vsink); // 启动管道播放 gst_element_set_state(pipeline, GST_STATE_PLAYING); int ret = a.exec(); // 退出前清理Gstreamer资源 gst_element_set_state(pipeline, GST_STATE_NULL); gst_object_unref(pipeline); return ret; }
- 如果要播放本地文件,只要把管道里的
videotestsrc替换成filesrc location=你的文件绝对路径 ! decodebin即可;如果要播放UDP/RTP流,直接替换成你注释里写的UDP源、解码相关的管道片段就行,注意最后必须接qtvideosink作为渲染sink,不要用autovideosink、ximagesink这类会弹出独立窗口的sink。
避坑提醒
- Windows环境下必须保证你安装的Gstreamer库和Qt编译器的ABI一致:比如用MSVC2019 64bit编译Qt程序,就要装64位MSVC版本的Gstreamer;用MinGW编译的Qt就装对应版本MinGW编译的Gstreamer,否则会出现崩溃、找不到元素的问题。
- 部署程序的时候,需要把Gstreamer安装目录下bin文件夹里的dll、以及lib/gstreamer-1.0目录下的插件文件夹,全部复制到exe同级目录,否则运行时会找不到
qtvideosink、videoconvert这些插件。 - 如果你坚持要用QMediaPlayer接口操作,必须先部署Qt的Gstreamer多媒体后端插件,并且设置环境变量
QT_MULTIMEDIA_PREFERRED_PLUGINS=gstreamer切换后端,否则永远会走DirectShow后端报同样的错,这种方案自定义管道的灵活性很差,不推荐。
内容的提问来源于stack exchange,提问作者MH.AI.eAgLe
相关产品推荐
相关产品推荐

