Qt QML 5.12 Video with transparency

185 views Asked by At

I would like to display a video in my Qt QML 5.12 application but a video with an alpha channel, which means that there will be other displayed QML components behind the video.

For example, the video could display an animated logo in front of QML buttons, texts, ...

I tried to do it but Qt replaces the transparent areas in the video by black areas, and so the elements behind the video are not visible.

I use a .mov video file with the following codec information:

Codec: Apple ProRes 4444 XQ (ap4x)
Decoded format: Planar YUV 4:4:4 Y:U:V:A 10bits
Color primaries: ITU-R BT.709
Color transfer function: ITU-R BT.709
Color space: ITU-R BT.709 Range

So, is it possible to use QML Video component (or other) to display a video with an alpha channel, with transparent areas.

Thanks.

1

There are 1 answers

0
Stephen Quan On

Firstly, if the transparent region is static (i.e. unchanging nor rotating) you could consider using OpacityMask. If it's more complex, such as a video with a specific chroma-key color you want transparent, consider using ShaderEffect.

In the following code, we treat "green" as the chroma-key by searching and replacing all "green" pixels with "transparent" with a tolerance of 10%. To make it convenient, I've refactored it as a ColorChanger component with properties from: "green" and to: "transparent".

Whilst the VideoOutput source is currently a MediaPlayer you can easily substitute it for Camera and it'll behave like a Zoom meeting with background video effects:

//..
Window {
    //..
    MediaPlayer {
        id: player
        source: "file:///C:/Temp/Video/sample.avi"
        autoPlay: true
    }
    VideoOutput {
        id: video
        anchors.fill: parent
        source: player
    }
    ColorChanger {
        source: ShaderEffectSource { sourceItem: video; hideSource: true }
        from: "green"
        to: "transparent"
        tolerance: 0.10
        anchors.fill: video
    }
    //...
}

// ColorChanger.qml
import QtQuick 2.15
import QtMultimedia 5.15
ShaderEffect {
    property variant source
    property color from: "green"
    property color to: "transparent"
    property double tolerance: 0.10
    fragmentShader: `
        varying highp vec2 qt_TexCoord0;
        uniform lowp sampler2D source;
        uniform lowp vec4 from;
        uniform lowp vec4 to;
        uniform lowp float tolerance;
        void main(void) {
            lowp vec4 tex = texture2D(source, qt_TexCoord0);
            if (   abs(tex.r - from.r) < tolerance
                && abs(tex.g - from.g) < tolerance
                && abs(tex.b - from.b) < tolerance
            ) {
                gl_FragColor = to;
            } else {
                gl_FragColor = tex;
            }
        }
`
}

References: