Below is an example of capturing 5 seconds of an application at 10fps (i.e. 50 frames in total) and using an external tool (e.g. FFmpeg) to produce an animated GIF.
First, the application uses Timer combined with grabToImage to capture frames at a regular intervals. When we got 5 seconds worth, i.e. 50 frames, we stop the Timer.
Page {
id: page
width: 400
height: 600
Frame {
id: frame
anchors.centerIn: parent
width: 200
height: 200
background: Rectangle { color: "#848895" }
Node {
id: standAloneScene
DirectionalLight { ambientColor: Qt.rgba(1.0, 1.0, 1.0, 1.0) }
Node {
id: node
Model {
source: "#Cube"
materials: [
DefaultMaterial {
diffuseMap: Texture {
sourceItem: Image {
source: "https://stephenquan.github.io/images/qt/madewithqt.png"
}
}
}
]
}
}
OrthographicCamera {
id: cameraOrthographicFront
y: 800; z: 1000
Component.onCompleted: lookAt(node)
}
}
View3D {
anchors.fill: parent
importScene: standAloneScene
camera: cameraOrthographicFront
}
NumberAnimation {
target: node
property: "eulerRotation.y"
loops: Animation.Infinite
running: true
from: 720; to: 0
duration: 10000
}
}
Button {
y: parent.height * 3 / 4
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("Record (%1)").arg(recordTimer.frame)
enabled: !recordTimer.running
onClicked: {
recordTimer.stop();
recordTimer.frame = 0;
recordTimer.interval = 100; // 100ms === 10fps
recordTimer.maxFrames = 50; // number of frames (total 5 seconds)
recordTimer.start();
}
}
Timer {
id: recordTimer
property int frame: -1
property int maxFrames: 100
interval: 100
running: false
repeat: true
onTriggered: frame.grabToImage(function (result) {
result.saveToFile(`C:/Temp/record${recordTimer.frame}.png`);
if (++recordTimer.frame >= recordTimer.maxFrames) recordTimer.stop();
} );
}
}
Next, I use FFMPEG which I've installed the binaries to C:\ffmpeg\bin. With a bit of Google-fu, you can find where to download (e.g. https://ffmpeg.org/download.html).
Then, I can produce an MP4 using the following script:
-y - means overwrite any previous output file
-f image2 - means the source may be a series of images
-r 10 - specifies 10fps
-i record%%d.png - supplies the wildcard match for the source images
-vb 3000k - means allow high resolution video frames
-an - means we are not interested in including audio in our output
-vcodec mpeg4 - change the output MP4 video codec from x264 (default) to MPEG4
screengrab.mp4 - specifies the name of the output MPEG4 file
REM MAKEMP4.BAT
set path=%PATH%;C:\ffmpeg\bin
ffmpeg -y -f image2 -r 10 -i "C:/Temp/record%%d.png" -vb 3000k -an -vcodec mpeg4 C:/Temp/screengrab.mp4
If I want to produce an 8-bit animating GIF, I need to produce a palette.png which can be done by doing a preliminary pass:
REM MAKEGIF.BAT
set path=%PATH%;C:\ffmpeg\bin
ffmpeg -y -f image2 -r 10 -i "C:/Temp/record%%d.png" -vf "palettegen" C:/Temp/palette.png
ffmpeg -y -f image2 -r 10 -i "C:/Temp/record%%d.png" -i C:/Temp/palette.png -lavfi "paletteuse" C:/Temp/screengrab.gif
The following animated GIF was generated using the above command:
