本页内容

QML 视频示例

对视频和相机取景器内容进行变换。

QML 视频示例演示了可应用于 QML `VideoOutput ` 和 `Camera ` 类型的各种变换(移动、调整大小、旋转、更改宽高比)。

它还展示了如何将原生代码与 QML 结合以实现更高级的功能——在此示例中,使用 C++ 代码来计算 QML 的帧率。该值在 QML 中以半透明项的形式渲染,并叠加在视频内容之上。

下图展示了应用程序执行视频叠加场景的过程:该场景创建了一个虚拟叠加项(仅为一个半透明的Rectangle ),该项在VideoOutput 项上移动。

带有半透明覆盖层的视频播放器

运行示例

您可以通过以下方式运行示例:

应用程序结构

Main.qml 文件会创建一个包含以下元素的用户界面:

  • 两个Button 实例,每个实例均显示一个文件名,并可用于启动FileDialog 。
  • 一个退出用的Button 。
  • 一个SceneSelectionPanel ,这是一个可滑动的列表,用于显示可用的场景。
  • 左下角有一个显示 QML 重绘速率的控件——上方的数值为瞬时帧率,下方的数值为过去一秒内的平均帧率。

场景选择面板,显示视频和相机模式场景列表

可滑动列表中的每个场景都在各自的 QML 文件中实现——例如,video-basic 场景(仅在屏幕中央显示一个静态的VideoOutput )就在VideoBasic.qml 文件中实现。从代码中可以看出,这利用了一种继承机制;一个VideoBasic 项……

SceneBasic {
    contentType: "video"
}

……的类型是SceneBasic ……

import QtQuick
import QtQuick.Controls

Scene {
    id: root
    property string contentType
    ...
    Content {
        id: content
    ...
    }

    Label {
        anchors {
            horizontalCenter: parent.horizontalCenter
            bottom: parent.bottom
            margins: 20
        }
        text: content.started ? qsTr("Tap the screen to stop content")
                              : qsTr("Tap the screen to start content")
        z: 2.0
    }

    MouseArea {
        anchors.fill: parent
        onClicked: {
            if (content.started)
                content.stop()
            else
                content.start()
        }
    }

    Component.onCompleted: root.content = content
}

……而该项本身是Scene :

import QtQuick
import QtQuick.Controls

Rectangle {
    id: root
    ...
    property QtObject content
    ...
    Button {
        id: closeButton
        anchors {
            top: parent.top
            right: parent.right
            margins: root.margins
        }
        z: 2.0
        text: qsTr("Back")
        onClicked: root.close()
    }
}

SceneBasic 描述了场景的结构和行为,但与将要显示的内容类型无关——这一点由Content 进行了抽象。

这种模式使我们能够定义一个特定的用例(在本例中,即简单地显示一段静态内容),然后分别针对视频内容(VideoBasic )和摄像头内容({CameraBasic}) 实例化该用例。 许多其他场景都是采用这种方法实现的——例如,“将内容从左向右反复滑动,然后又滑回原处”是由SceneMove 实现的,而 VideoMove 和CameraMove 正是基于该实现的。

根据顶级场景实例中 contentType 属性的值,嵌入的Content 项会创建MediaPlayer 或Camera 项。

计算和显示 QML 绘制速率

QML 绘制速率由 FrequencyMonitor 类计算得出,该类将事件流(通过 notify() 槽接收)转换为瞬时频率和平均频率:

class FrequencyMonitor : public QObject
{
    Q_OBJECT
    QML_ELEMENT
    Q_PROPERTY(qreal instantaneousFrequency READ instantaneousFrequency NOTIFY
                       instantaneousFrequencyChanged)
    Q_PROPERTY(qreal averageFrequency READ averageFrequency NOTIFY averageFrequencyChanged)
    ...
public slots:
    Q_INVOKABLE void notify();
};

通过如上所示在类声明中添加宏QML_ELEMENT ,将 FrequencyMonitor 类暴露给 QML;并通过定义名为 FrequencyItem 的 QML 项来显示其数据,如下所示:

import frequencymonitor

Rectangle {
    id: root
    ...
    function notify() {
        monitor.notify()
    }

    FrequencyMonitor {
        id: monitor
        onAverageFrequencyChanged: {
            averageFrequencyText.text = monitor.averageFrequency.toFixed(2)
        }
    }

    Text {
        id: labelText
        anchors {
            left: parent.left
            top: parent.top
            margins: 10
        }
        color: root.textColor
        font.pixelSize: 0.6 * root.textSize
        text: root.label
        width: root.width - 2*anchors.margins
        elide: Text.ElideRight
    }

    Text {
        id: averageFrequencyText
        anchors {
            right: parent.right
            bottom: parent.bottom
            margins: 10
        }
        color: root.textColor
        font.pixelSize: root.textSize
    }
}

显示效果如下:

62.5 Hz 的瞬时频率和 53.15 Hz 的平均频率

最后只需将QQuickView 对象的 afterRendering() 信号连接到一个 JavaScript 函数,该函数最终会调用frequencyItem.notify() :

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    ...
    QQuickView viewer;
    ...
    QQuickItem *rootObject = viewer.rootObject();
    ...
    QObject::connect(&viewer, SIGNAL(afterRendering()), rootObject, SLOT(qmlFramePainted()));

示例项目 @ code.qt.io

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.