Making videos for the web with Godot 4’s Movie Writer
Normally I use OBS for screen recording, but there are cases where it makes sense to use Godot’s built-in movie writer that was recently announced.
For example, if you have a slow PC or really demanding game, OBS will skip frames. It makes sense since OBS is just recording what’s on the screen in real time, while Godot has to do most of the work running the game. Recording with Godot directly will slow down the action at recording time, and you cannot hear any audio while that happens. But the video playback will end up being buttery smooth at 60 fps and include audio. It will also result in huge files. 321MB for 8 seconds, at 1280x800px (also Steam Deck’s native 16:10 resolution). Still, that’s not a video file I want to embed into any webpage or wherever as-is.
The best tool for converting video from the command line or programmatically is still ffmpeg. I’m running this on Windows in WSL2, on Ubuntu 22.04.
The best option for .webm seems to be the VP9 codec. Their docs provide some examples. I’ve tested a few parameters. For two-pass targeting an average bitrate, the target bitrate is specified with the -b:v switch:
# will take longer but smaller fileffmpeg-itilemap.avi-c:vlibvpx-vp9-b:v2M-pass1-an-fnull/dev/null&&\ffmpeg-itilemap.avi-c:vlibvpx-vp9-b:v2M-pass2-c:alibopustilemap-average.webm
This is what the output looks like:
gray@Battlestation:/mnt/c/Users/gray/godot/arpg$ffmpeg-itilemap.avi-c:vlibvpx-vp9-b:v2M-pass1-an-fnull/dev/null&&\ffmpeg-itilemap.avi-c:vlibvpx-vp9-b:v2M-pass2-c:alibopustilemap-average.webmffmpegversion4.4.2-0ubuntu0.22.04.1Copyright (c) 2000-2021 the FFmpeg developersbuiltwithgcc11 (Ubuntu 11.2.0-19ubuntu1)configuration:--prefix=/usr--extra-version=0ubuntu0.22.04.1--toolchain=hardened--libdir=/usr/lib/x86_64-linux-gnu--incdir=/usr/include/x86_64-linux-gnu--arch=amd64--enable-gpl--disable-stripping--enable-gnutls--enable-ladspa--enable-libaom--enable-libass--enable-libbluray--enable-libbs2b--enable-libcaca--enable-libcdio--enable-libcodec2--enable-libdav1d--enable-libflite--enable-libfontconfig--enable-libfreetype--enable-libfribidi--enable-libgme--enable-libgsm--enable-libjack--enable-libmp3lame--enable-libmysofa--enable-libopenjpeg--enable-libopenmpt--enable-libopus--enable-libpulse--enable-librabbitmq--enable-librubberband--enable-libshine--enable-libsnappy--enable-libsoxr--enable-libspeex--enable-libsrt--enable-libssh--enable-libtheora--enable-libtwolame--enable-libvidstab--enable-libvorbis--enable-libvpx--enable-libwebp--enable-libx265--enable-libxml2--enable-libxvid--enable-libzimg--enable-libzmq--enable-libzvbi--enable-lv2--enable-omx--enable-openal--enable-opencl--enable-opengl--enable-sdl2--enable-pocketsphinx--enable-librsvg--enable-libmfx--enable-libdc1394--enable-libdrm--enable-libiec61883--enable-chromaprint--enable-frei0r--enable-libx264--enable-sharedWARNING:libraryconfigurationmismatchavcodecconfiguration:--prefix=/usr--extra-version=0ubuntu0.22.04.1--toolchain=hardened--libdir=/usr/lib/x86_64-linux-gnu--incdir=/usr/include/x86_64-linux-gnu--arch=amd64--enable-gpl--disable-stripping--enable-gnutls--enable-ladspa--enable-libaom--enable-libass--enable-libbluray--enable-libbs2b--enable-libcaca--enable-libcdio--enable-libcodec2--enable-libdav1d--enable-libflite--enable-libfontconfig--enable-libfreetype--enable-libfribidi--enable-libgme--enable-libgsm--enable-libjack--enable-libmp3lame--enable-libmysofa--enable-libopenjpeg--enable-libopenmpt--enable-libopus--enable-libpulse--enable-librabbitmq--enable-librubberband--enable-libshine--enable-libsnappy--enable-libsoxr--enable-libspeex--enable-libsrt--enable-libssh--enable-libtheora--enable-libtwolame--enable-libvidstab--enable-libvorbis--enable-libvpx--enable-libwebp--enable-libx265--enable-libxml2--enable-libxvid--enable-libzimg--enable-libzmq--enable-libzvbi--enable-lv2--enable-omx--enable-openal--enable-opencl--enable-opengl--enable-sdl2--enable-pocketsphinx--enable-librsvg--enable-libmfx--enable-libdc1394--enable-libdrm--enable-libiec61883--enable-chromaprint--enable-frei0r--enable-libx264--enable-shared--enable-version3--disable-doc--disable-programs--enable-libaribb24--enable-libopencore_amrnb--enable-libopencore_amrwb--enable-libtesseract--enable-libvo_amrwbenc--enable-libsmbclientlibavutil56.70.100/56.70.100libavcodec58.134.100/58.134.100libavformat58.76.100/58.76.100libavdevice58.13.100/58.13.100libavfilter7.110.100/7.110.100libswscale5.9.100/5.9.100libswresample3.9.100/3.9.100libpostproc55.9.100/55.9.100GuessedChannelLayoutforInputStream#0.1 : stereoInput#0, avi, from 'tilemap.avi':Duration:N/A,start:0.000000,bitrate:N/AStream#0:0: Video: mjpeg (Baseline) (MJPG / 0x47504A4D), yuvj420p(pc, bt470bg/unknown/unknown), 1280x800 [SAR 1:1 DAR 8:5], 60 fps, 60 tbr, 60 tbn, 60 tbcStream#0:1: Audio: pcm_s32le ([1][0][0][0] / 0x0001), 48000 Hz, stereo, s32, 3072 kb/sStreammapping:Stream#0:0 -> #0:0 (mjpeg (native) -> vp9 (libvpx-vp9))Press [q] to stop, [?]for help[swscaler @ 0x55932cefff40] deprecated pixel format used, make sure you did set range correctly[libvpx-vp9 @ 0x55932cee54c0] v1.11.0Output#0, null, to '/dev/null':Metadata:encoder:Lavf58.76.100Stream#0:0: Video: vp9, yuv420p(tv, bt470bg/unknown/unknown, progressive), 1280x800 [SAR 1:1 DAR 8:5], q=2-31, 2000 kb/s, 60 fps, 60 tbnMetadata:encoder:Lavc58.134.100libvpx-vp9Sidedata:cpb:bitratemax/min/avg:0/0/2000000buffersize:0vbv_delay:N/Aframe=533fps=35q=0.0Lsize=N/Atime=00:00:00.00bitrate=N/Aspeed=0xvideo:0kBaudio:0kBsubtitle:0kBotherstreams:0kBglobalheaders:0kBmuxingoverhead:unknownOutputfileisempty,nothingwasencodedffmpegversion4.4.2-0ubuntu0.22.04.1Copyright (c) 2000-2021 the FFmpeg developersbuiltwithgcc11 (Ubuntu 11.2.0-19ubuntu1)configuration:--prefix=/usr--extra-version=0ubuntu0.22.04.1--toolchain=hardened--libdir=/usr/lib/x86_64-linux-gnu--incdir=/usr/include/x86_64-linux-gnu--arch=amd64--enable-gpl--disable-stripping--enable-gnutls--enable-ladspa--enable-libaom--enable-libass--enable-libbluray--enable-libbs2b--enable-libcaca--enable-libcdio--enable-libcodec2--enable-libdav1d--enable-libflite--enable-libfontconfig--enable-libfreetype--enable-libfribidi--enable-libgme--enable-libgsm--enable-libjack--enable-libmp3lame--enable-libmysofa--enable-libopenjpeg--enable-libopenmpt--enable-libopus--enable-libpulse--enable-librabbitmq--enable-librubberband--enable-libshine--enable-libsnappy--enable-libsoxr--enable-libspeex--enable-libsrt--enable-libssh--enable-libtheora--enable-libtwolame--enable-libvidstab--enable-libvorbis--enable-libvpx--enable-libwebp--enable-libx265--enable-libxml2--enable-libxvid--enable-libzimg--enable-libzmq--enable-libzvbi--enable-lv2--enable-omx--enable-openal--enable-opencl--enable-opengl--enable-sdl2--enable-pocketsphinx--enable-librsvg--enable-libmfx--enable-libdc1394--enable-libdrm--enable-libiec61883--enable-chromaprint--enable-frei0r--enable-libx264--enable-sharedWARNING:libraryconfigurationmismatchavcodecconfiguration:--prefix=/usr--extra-version=0ubuntu0.22.04.1--toolchain=hardened--libdir=/usr/lib/x86_64-linux-gnu--incdir=/usr/include/x86_64-linux-gnu--arch=amd64--enable-gpl--disable-stripping--enable-gnutls--enable-ladspa--enable-libaom--enable-libass--enable-libbluray--enable-libbs2b--enable-libcaca--enable-libcdio--enable-libcodec2--enable-libdav1d--enable-libflite--enable-libfontconfig--enable-libfreetype--enable-libfribidi--enable-libgme--enable-libgsm--enable-libjack--enable-libmp3lame--enable-libmysofa--enable-libopenjpeg--enable-libopenmpt--enable-libopus--enable-libpulse--enable-librabbitmq--enable-librubberband--enable-libshine--enable-libsnappy--enable-libsoxr--enable-libspeex--enable-libsrt--enable-libssh--enable-libtheora--enable-libtwolame--enable-libvidstab--enable-libvorbis--enable-libvpx--enable-libwebp--enable-libx265--enable-libxml2--enable-libxvid--enable-libzimg--enable-libzmq--enable-libzvbi--enable-lv2--enable-omx--enable-openal--enable-opencl--enable-opengl--enable-sdl2--enable-pocketsphinx--enable-librsvg--enable-libmfx--enable-libdc1394--enable-libdrm--enable-libiec61883--enable-chromaprint--enable-frei0r--enable-libx264--enable-shared--enable-version3--disable-doc--disable-programs--enable-libaribb24--enable-libopencore_amrnb--enable-libopencore_amrwb--enable-libtesseract--enable-libvo_amrwbenc--enable-libsmbclientlibavutil56.70.100/56.70.100libavcodec58.134.100/58.134.100libavformat58.76.100/58.76.100libavdevice58.13.100/58.13.100libavfilter7.110.100/7.110.100libswscale5.9.100/5.9.100libswresample3.9.100/3.9.100libpostproc55.9.100/55.9.100GuessedChannelLayoutforInputStream#0.1 : stereoInput#0, avi, from 'tilemap.avi':Duration:N/A,start:0.000000,bitrate:N/AStream#0:0: Video: mjpeg (Baseline) (MJPG / 0x47504A4D), yuvj420p(pc, bt470bg/unknown/unknown), 1280x800 [SAR 1:1 DAR 8:5], 60 fps, 60 tbr, 60 tbn, 60 tbcStream#0:1: Audio: pcm_s32le ([1][0][0][0] / 0x0001), 48000 Hz, stereo, s32, 3072 kb/sStreammapping:Stream#0:0 -> #0:0 (mjpeg (native) -> vp9 (libvpx-vp9))Stream#0:1 -> #0:1 (pcm_s32le (native) -> opus (libopus))Press [q] to stop, [?]for help[swscaler @ 0x562739e33040] deprecated pixel format used, make sure you did set range correctly[libvpx-vp9 @ 0x562739e14040] v1.11.0[libopus @ 0x562739e165c0] No bit rate set. Defaulting to 96000 bps.Output#0, webm, to 'tilemap-average.webm':Metadata:encoder:Lavf58.76.100Stream#0:0: Video: vp9, yuv420p(tv, bt470bg/unknown/unknown, progressive), 1280x800 [SAR 1:1 DAR 8:5], q=2-31, 2000 kb/s, 60 fps, 1k tbnMetadata:encoder:Lavc58.134.100libvpx-vp9Sidedata:cpb:bitratemax/min/avg:0/0/2000000buffersize:0vbv_delay:N/AStream#0:1: Audio: opus, 48000 Hz, stereo, flt, 96 kb/sMetadata:encoder:Lavc58.134.100libopusframe=533fps=3.2q=0.0Lsize=2600kBtime=00:00:08.86bitrate=2401.8kbits/sspeed=0.054xvideo:2479kBaudio:114kBsubtitle:0kBotherstreams:0kBglobalheaders:0kBmuxingoverhead:0.289294%
And on this ancient i7-4790K, it runs dog slow. It processed the 8.86-second-long video at 5% speed, dragging it out to almost three minutes. But the payoff is worth it. Instead of 321MB, the video file is down to 2.6MB:
A new version of the Inventory System is available with more multiplayer-related features. The Multiplayer Interaction Demo can now run in multiple modes, through two separate implementations of the Character scene: The simple character scene leverages the MultiplayerSynchronizer and can either let the client have authority and move the character, or have the client send …
Ever had the problem where you’re firing a bullet or some kind of projectile at high speeds, and it just goes right through the collision object, instead of hitting it? Here’s a weapon that fires a bullet at random velocities, to demonstrate the issue: The bullets impact the character in various places, rather than at …
Per feedback, we’ve exposed more inventory user interface component signals to make it easier to react to slot/item interactions with custom logic. New features: In addition, these bug fixes are included:
Making videos for the web with Godot 4’s Movie Writer
Normally I use OBS for screen recording, but there are cases where it makes sense to use Godot’s built-in movie writer that was recently announced.
For example, if you have a slow PC or really demanding game, OBS will skip frames. It makes sense since OBS is just recording what’s on the screen in real time, while Godot has to do most of the work running the game. Recording with Godot directly will slow down the action at recording time, and you cannot hear any audio while that happens. But the video playback will end up being buttery smooth at 60 fps and include audio. It will also result in huge files. 321MB for 8 seconds, at 1280x800px (also Steam Deck’s native 16:10 resolution). Still, that’s not a video file I want to embed into any webpage or wherever as-is.
The best tool for converting video from the command line or programmatically is still ffmpeg. I’m running this on Windows in WSL2, on Ubuntu 22.04.
The best option for .webm seems to be the VP9 codec. Their docs provide some examples. I’ve tested a few parameters. For two-pass targeting an average bitrate, the target bitrate is specified with the -b:v switch:
This is what the output looks like:
And on this ancient i7-4790K, it runs dog slow. It processed the 8.86-second-long video at 5% speed, dragging it out to almost three minutes. But the payoff is worth it. Instead of 321MB, the video file is down to 2.6MB:
Related Posts
Inventory System v1.14 available
A new version of the Inventory System is available with more multiplayer-related features. The Multiplayer Interaction Demo can now run in multiple modes, through two separate implementations of the Character scene: The simple character scene leverages the MultiplayerSynchronizer and can either let the client have authority and move the character, or have the client send …
Projectiles going through collision objects
Ever had the problem where you’re firing a bullet or some kind of projectile at high speeds, and it just goes right through the collision object, instead of hitting it? Here’s a weapon that fires a bullet at random velocities, to demonstrate the issue: The bullets impact the character in various places, rather than at …
Inventory System v1.6 available
Per feedback, we’ve exposed more inventory user interface component signals to make it easier to react to slot/item interactions with custom logic. New features: In addition, these bug fixes are included:
Inventory System v1.1 available
Hot on the heels of 1.0, version 1.1 allows for gaps in the inventory. This release also correctly bakes the release version into the PDF Guide.