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.

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 unFileDialog. - 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.

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

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()));
© 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.