En esta página

Ejemplo de vídeo QML

Transformación de contenido de vídeo y visor de cámara.

QML Video demuestra las diversas transformaciones (mover; redimensionar; rotar; cambiar relación de aspecto) que pueden aplicarse a los tipos QML VideoOutput y Camera.

También muestra cómo puede combinarse código nativo con QML para implementar funciones más avanzadas: en este caso, se utiliza código C++ para calcular la frecuencia de imagen QML. Este valor se renderiza en QML en un elemento semitransparente superpuesto sobre el contenido del vídeo.

La siguiente imagen muestra la aplicación ejecutando la escena de superposición de vídeo, que crea un elemento de superposición ficticio (sólo un Rectangle semitransparente), que se mueve a través del elemento VideoOutput.

Reproductor de vídeo con superposición semitransparente

Ejecutar el ejemplo

Para ejecutar el ejemplo desde Qt Creatorabra el modo Welcome y seleccione el ejemplo de Examples. Para más información, consulte Qt Creator: Tutorial: Construir y ejecutar.

Estructura de la aplicación

El archivo Main.qml crea una interfaz de usuario que incluye los siguientes elementos:

  • Dos instancias Button, cada una de las cuales muestra un nombre de archivo y puede utilizarse para lanzar un FileDialog.
  • Una salida Button.
  • Un SceneSelectionPanel, que es una lista desplegable que muestra las escenas disponibles.
  • En la parte inferior izquierda, un elemento que muestra la velocidad de repintado QML: el número superior es la velocidad de fotogramas instantánea y el número inferior es la media del último segundo.

Panel de selección de escenas que muestra la lista de escenas de vídeo y del modo cámara

Cada escena de la lista flickable se implementa en su propio archivo QML - por ejemplo la escena video-basic (que sólo muestra un VideoOutput estático en el centro de la pantalla) se implementa en el archivo VideoBasic.qml. Como puedes ver en el código, esto hace uso de un tipo de herencia; un elemento VideoBasic...

SceneBasic {
    contentType: "video"
}

... es de tipo 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
}

... que a su vez es un 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 describe la estructura y el comportamiento de la escena, pero es agnóstico del tipo de contenido que se mostrará - esto es abstraído por Content.

Este patrón nos permite definir un caso de uso particular (en este caso, simplemente mostrar un contenido estático), y luego instanciar ese caso de uso tanto para contenido de vídeo (VideoBasic) como para contenido de cámara ({CameraBasic}). Este enfoque se utiliza para implementar muchas de las otras escenas - por ejemplo, "deslizar repetidamente el contenido de izquierda a derecha y viceversa" es implementado por SceneMove, en el que se basan VideoMove y CameraMove.

Dependiendo del valor de la propiedad contentType en la instancia de escena de nivel superior, el elemento Content incrustado crea un elemento MediaPlayer o Camera.

Cálculo y visualización de la tasa de pintura QML

La tasa de pintura QML se calcula mediante la clase FrequencyMonitor, que convierte un flujo de eventos (recibidos a través de la ranura notify()), en una frecuencia instantánea y otra promediada:

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();
};

La clase FrequencyMonitor se expone a QML añadiendo la macro QML_ELEMENT a la declaración de la clase, como se muestra arriba, y sus datos se muestran definiendo un elemento QML llamado FrequencyItem, así:

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
    }
}

El resultado es el siguiente

62,5 Hz de frecuencia instantánea y 53,15 Hz de frecuencia media

Sólo queda conectar la señal afterRendering() del objeto QQuickView a una función JavaScript, que finalmente llamará a 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()));

Proyecto de ejemplo @ 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.