You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中GStreamer与WPEWebKit开发问题:视频文字叠加及wpesrc缺失

视频叠加可编辑文字(WPEWebKit作为叠加层)问题解决方案

1. 修复wpesrc找不到的报错

wpesrc并非包含在gstreamer1.0-plugins-bad中,它属于单独的WPEWebKit GStreamer插件包,不同发行版安装命令如下:

  • Debian/Ubuntu系:
    sudo apt install gstreamer1.0-wpe gstreamer1.0-wpe-webkit
    
  • Fedora系:
    sudo dnf install gstreamer1-plugins-wpe gstreamer1-wpe-webkit
    

安装完成后重新运行官方示例命令,即可正常加载网页内容。

2. Python中实现视频与WPE网页叠加的代码扩展

基于你现有GStreamer代码,通过videomixer将原始视频流和WPE网页流叠加,实现文字层的显示与移动:

import threading
import time

import gi

gi.require_version("Gst", "1.0")
gi.require_version("GstVideo", "1.0")

from gi.repository import Gst, GLib, GstVideo

Gst.init()

main_loop = GLib.MainLoop()
thread = threading.Thread(target=main_loop.run)
thread.start()

# 构建带叠加逻辑的管道:底层视频 + 上层WPE网页
pipeline_str = """
videotestsrc name=videosrc ! decodebin ! videoconvert ! video/x-raw,format=RGBA ! queue ! videomixer.sink_0
wpesrc location="file:///path/to/your/editable-text-page.html" ! videoconvert ! video/x-raw,format=RGBA ! queue ! videomixer.sink_1
videomixer name=videomixer ! videoconvert ! autovideosink
"""
pipeline = Gst.parse_launch(pipeline_str)

# 配置网页层的初始位置(示例为右上角)
mixer = pipeline.get_by_name("videomixer")
sink1_pad = mixer.get_static_pad("sink_1")
if sink1_pad:
    caps = sink1_pad.get_current_caps()
    if caps:
        struct = caps.get_structure(0)
        web_width = struct.get_int("width").value
        web_height = struct.get_int("height").value
        # 设置叠加位置:x=视频宽度-网页宽度,y=0
        overlay = GstVideo.VideoOverlayComposition.new()
        rect = GstVideo.VideoOverlayRectangle.new()
        rect.set_position(GstVideo.VideoOverlayRectangleFlags.POSITION_ABSOLUTE,
                          800 - web_width, 0, web_width, web_height)
        overlay.add_rectangle(rect)
        sink1_pad.set_property("overlay-composition", overlay)

pipeline.set_state(Gst.State.PLAYING)

try:
    while True:
        time.sleep(0.1)
except KeyboardInterrupt:
    pass

pipeline.set_state(Gst.State.NULL)
main_loop.quit()
  • 需提前创建本地HTML页面,用contenteditable属性实现文字可编辑,结合JS实现拖动逻辑
  • 可通过动态修改VideoOverlayRectangle的位置参数,实现网页层的实时移动

3. 整合到GTK应用的优化方案

直接用GTK控件层级实现叠加比通过GStreamer混合更灵活,核心思路是用WebKitWebView作为顶层可编辑文字层,GStreamer视频渲染到底层DrawingArea:

import gi

gi.require_version("Gst", "1.0")
gi.require_version("Gtk", "3.0")
gi.require_version("WebKit2", "4.0")

from gi.repository import Gst, Gtk, WebKit2, Gdk

Gst.init()
Gtk.init()

class VideoTextOverlay(Gtk.Window):
    def __init__(self):
        super().__init__(title="视频文字叠加")
        self.set_default_size(800, 600)
        self.connect("destroy", Gtk.main_quit)

        # 固定布局容器,用于放置视频控件和Web文字层
        self.fixed = Gtk.Fixed()
        self.add(self.fixed)

        # 视频渲染控件
        self.drawing_area = Gtk.DrawingArea()
        self.fixed.put(self.drawing_area, 0, 0)
        self.drawing_area.set_size_request(800, 600)

        # WebKitWebView作为可编辑文字层
        self.web_view = WebKit2.WebView()
        self.fixed.put(self.web_view, 100, 100)
        self.web_view.set_size_request(400, 200)
        # 加载本地可编辑页面
        self.web_view.load_uri("file:///path/to/your/editable-text-page.html")
        # 设置透明背景
        self.web_view.set_background_color(Gdk.RGBA(0,0,0,0))

        # 初始化GStreamer管道
        self.pipeline = Gst.parse_launch("videotestsrc ! decodebin ! videoconvert ! gtksink name=sink")
        self.sink = self.pipeline.get_by_name("sink")
        self.sink.set_property("widget", self.drawing_area)
        self.pipeline.set_state(Gst.State.PLAYING)

        # 绑定WebView拖动事件
        self.dragging = False
        self.drag_start_x = 0
        self.drag_start_y = 0
        self.web_view.connect("button-press-event", self.on_press)
        self.web_view.connect("button-release-event", self.on_release)
        self.web_view.connect("motion-notify-event", self.on_motion)

    def on_press(self, widget, event):
        if event.button == 1:
            self.dragging = True
            self.drag_start_x = event.x
            self.drag_start_y = event.y

    def on_release(self, widget, event):
        if event.button == 1:
            self.dragging = False

    def on_motion(self, widget, event):
        if self.dragging:
            x = widget.get_allocation().x + (event.x - self.drag_start_x)
            y = widget.get_allocation().y + (event.y - self.drag_start_y)
            self.fixed.move(widget, x, y)

win = VideoTextOverlay()
win.show_all()
Gtk.main()
  • 此方案无需GStreamer混合流,直接通过GTK控件层级实现叠加,更易控制文字编辑和移动
  • 需确保安装WPE后端的WebKit2GTK包(如webkit2gtk-wpe)

内容的提问来源于stack exchange,提问作者chocolateimage

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 17:48:30