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:
