You need to enable JavaScript to run this app. QML中单个Camera源绑定多个VideoOutput仅单个显示的解决方案
优惠活动
大模型
产品
解决方案
定价
更多

QML中单个Camera源绑定多个VideoOutput仅单个显示的解决方案

原因说明

Qt 5.x 版本的Qt Multimedia模块中,Camera作为视频源底层采用单消费者管线设计,同一时间仅支持绑定一个VideoOutput作为视频帧的输出sink。直接给两个VideoOutput设置同一个Camera源时,后绑定的组件会覆盖前一个的sink连接,因此只会有一个能正常显示内容。

可行实现方案

轻量纯QML方案(适配原始/预处理双显示需求)

不需要额外绑定多个VideoOutput到Camera,只需要保留一个隐藏的VideoOutput接收摄像头帧,通过ShaderEffectSource共享纹理后,分别做原始显示和预处理后显示即可,全程纯QML实现,无C++侵入。

示例代码:

import QtQuick 2.9
import QtMultimedia 5.9

Item {
    width: 800
    height: 600

    Camera {
        id: camera
        active: true
    }

    // 仅用于接收Camera帧的隐藏VideoOutput,不参与显示
    VideoOutput {
        id: hiddenOutput
        source: camera
        visible: false
        autoOrientation: true
    }

    // 捕获隐藏Output的纹理,作为全局共享的视频源纹理
    ShaderEffectSource {
        id: sharedVideoTexture
        sourceItem: hiddenOutput
        hideSource: true
        live: true
    }

    // 左侧显示原始视频
    Rectangle {
        id: originalDisplay
        width: 380
        height: 580
        anchors.left: parent.left
        anchors.top: parent.top
        anchors.margins: 10

        ShaderEffect {
            anchors.fill: parent
            texture: sharedVideoTexture
            vertexShader: "
                uniform highp mat4 qt_Matrix;
                attribute highp vec4 qt_Vertex;
                attribute highp vec2 qt_MultiTexCoord0;
                varying highp vec2 texCoord;
                void main() {
                    texCoord = qt_MultiTexCoord0;
                    gl_Position = qt_Matrix * qt_Vertex;
                }
            "
            fragmentShader: "
                varying highp vec2 texCoord;
                uniform sampler2D texture;
                void main() {
                    gl_FragColor = texture2D(texture, texCoord);
                }
            "
        }
    }

    // 右侧显示预处理后视频,此处以灰度化为例
    Rectangle {
        id: processedDisplay
        width: 380
        height: 580
        anchors.right: parent.right
        anchors.top: parent.top
        anchors.margins: 10

        ShaderEffect {
            anchors.fill: parent
            texture: sharedVideoTexture
            vertexShader: "
                uniform highp mat4 qt_Matrix;
                attribute highp vec4 qt_Vertex;
                attribute highp vec2 qt_MultiTexCoord0;
                varying highp vec2 texCoord;
                void main() {
                    texCoord = qt_MultiTexCoord0;
                    gl_Position = qt_Matrix * qt_Vertex;
                }
            "
            fragmentShader: "
                varying highp vec2 texCoord;
                uniform sampler2D texture;
                void main() {
                    vec4 rawColor = texture2D(texture, texCoord);
                    // 自定义预处理逻辑可替换此处代码
                    float gray = dot(rawColor.rgb, vec3(0.299, 0.587, 0.114));
                    gl_FragColor = vec4(gray, gray, gray, 1.0);
                }
            "
        }
    }
}

需要多独立VideoOutput的场景

如果必须使用两个独立的VideoOutput组件(例如有其他逻辑绑定了VideoOutput的接口),则需要自定义继承自QAbstractVideoSurface的C++中介类:

  • 将Camera的输出绑定到这个中介surface,而非直接绑定到VideoOutput
  • 中介类收到摄像头帧后,将帧包装为可复用的纹理或数据,分发给两个下游的VideoOutput对应的sink
  • 该方案需要C++扩展开发,性能开销略高于纯QML纹理共享方案
注意事项
  • 上述纯QML方案适配Qt 5.9及以上版本,利用GPU纹理复用,避免了重复的帧拷贝和摄像头管线重复初始化,性能最优
  • 预处理逻辑完全在Shader中实现,可灵活替换为任意图像算法,不需要修改底层管线

内容的提问来源于stack exchange,提问作者LeXela-ED

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.04 12:36:05