Sur cette page

Exemple de vidéo QML

Transformer le contenu d'une vidéo et d'un viseur de caméra.

QML Video démontre les diverses transformations (déplacement, redimensionnement, rotation, modification du rapport hauteur/largeur) qui peuvent être appliquées aux types QML VideoOutput et Camera.

Il montre également comment le code natif peut être combiné avec QML pour mettre en œuvre des fonctionnalités plus avancées - dans ce cas, le code C++ est utilisé pour calculer la fréquence d'images QML. Cette valeur est rendue en QML dans un élément semi-transparent superposé au contenu vidéo.

L'image suivante montre l'application exécutant la scène de superposition vidéo, qui crée un élément de superposition fictif (juste un Rectangle semi-transparent), qui se déplace sur l'élément VideoOutput.

Lecteur vidéo avec incrustation semi-transparente

Exécution de l'exemple

Pour exécuter l'exemple à partir de Qt CreatorOuvrez le mode Welcome et sélectionnez l'exemple à partir de Examples. Pour plus d'informations, voir Qt Creator: Tutoriel : Construire et exécuter.

Structure de l'application

Le fichier Main.qml crée une interface utilisateur qui comprend les éléments suivants :

  • Deux instances Button, chacune affichant un nom de fichier et pouvant être utilisée pour lancer une application FileDialog.
  • Une sortie Button.
  • Un SceneSelectionPanel, qui est une liste déroulante affichant les scènes disponibles.
  • En bas à gauche, un élément qui affiche le taux de repeintures QML - le nombre supérieur est le taux d'images instantané et le nombre inférieur est la moyenne sur la dernière seconde.

Panneau de sélection des scènes affichant la liste des scènes en mode vidéo et en mode caméra

Chaque scène de la liste flickable est implémentée dans son propre fichier QML - par exemple, la scène video-basic (qui affiche simplement un VideoOutput statique au centre de l'écran) est implémentée dans le fichier VideoBasic.qml. Comme vous pouvez le voir dans le code, cela fait appel à un type d'héritage ; un élément VideoBasic...

SceneBasic {
    contentType: "video"
}

... est de type 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
}

... qui est lui-même de type 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 décrit la structure et le comportement de la scène, mais ne tient pas compte du type de contenu qui sera affiché - celui-ci est abstrait par Content.

Ce modèle nous permet de définir un cas d'utilisation particulier (dans ce cas, afficher simplement un élément de contenu statique), puis d'instancier ce cas d'utilisation à la fois pour le contenu vidéo (VideoBasic) et le contenu de la caméra ({CameraBasic}). Cette approche est utilisée pour mettre en œuvre de nombreuses autres scènes - par exemple, "faire glisser le contenu de gauche à droite et inversement de manière répétée" est mis en œuvre par SceneMove, sur lequel VideoMove et CameraMove sont basés.

En fonction de la valeur de la propriété contentType dans l'instance de scène de niveau supérieur, l'élément Content intégré crée un élément MediaPlayer ou Camera.

Calcul et affichage du taux de peinture QML

Le taux de peinture QML est calculé par la classe FrequencyMonitor, qui transforme un flux d'événements (reçus via le slot notify()) en une fréquence instantanée et une fréquence moyenne :

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 classe FrequencyMonitor est exposée à QML en ajoutant la macro QML_ELEMENT à la déclaration de la classe, comme indiqué ci-dessus, et ses données sont affichées en définissant un élément QML appelé FrequencyItem, comme ceci :

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

Le résultat ressemble à ceci :

Fréquence instantanée de 62,5 Hz et fréquence moyenne de 53,15 Hz

Il ne reste plus qu'à connecter le signal afterRendering() de l'objet QQuickView à une fonction JavaScript, qui appellera finalement 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()));

Exemple de projet @ 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.