Implement Running Godot as Movie Writer
* Allows running the game in "movie writer" mode.
* It ensures entirely stable framerate, so your run can be saved stable and with proper sound (which is impossible if your CPU/GPU can't sustain doing this in real-time).
* If disabling vsync, it can save movies faster than the game is run, but if you want to control the interaction it can get difficult.
* Implements a simple, default MJPEG writer.
This new features has two main use cases, which have high demand:
* Saving game videos in high quality and ensuring the frame rate is *completely* stable, always.
* Using Godot as a tool to make movies and animations (which is ideal if you want interaction, or creating them procedurally. No other software is as good for this).
**Note**: This feature **IS NOT** for capturing real-time footage. Use something like OBS, SimpleScreenRecorder or FRAPS to achieve that, as they do a much better job at intercepting the compositor than Godot can probably do using Vulkan or OpenGL natively. If your game runs near real-time when capturing, you can still use this feature but it will play no sound (sound will be saved directly).
Usage:
$ godot --write-movie movie.avi [scene_file.tscn]
Missing:
* Options for configuring video writing via GLOBAL_DEF
* UI Menu for launching with this mode from the editor.
* Add to list of command line options.
* Add a feature tag to override configurations when movie writing (fantastic for saving videos with highest quality settings).
2022-06-17 00:55:19 +02:00
/*************************************************************************/
/* movie_writer.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
# include "movie_writer.h"
# include "core/config/project_settings.h"
2022-06-26 02:06:58 +02:00
# include "core/io/dir_access.h"
2022-06-26 01:38:20 +02:00
# include "core/os/time.h"
2022-06-26 02:06:58 +02:00
# include "servers/display_server.h"
Implement Running Godot as Movie Writer
* Allows running the game in "movie writer" mode.
* It ensures entirely stable framerate, so your run can be saved stable and with proper sound (which is impossible if your CPU/GPU can't sustain doing this in real-time).
* If disabling vsync, it can save movies faster than the game is run, but if you want to control the interaction it can get difficult.
* Implements a simple, default MJPEG writer.
This new features has two main use cases, which have high demand:
* Saving game videos in high quality and ensuring the frame rate is *completely* stable, always.
* Using Godot as a tool to make movies and animations (which is ideal if you want interaction, or creating them procedurally. No other software is as good for this).
**Note**: This feature **IS NOT** for capturing real-time footage. Use something like OBS, SimpleScreenRecorder or FRAPS to achieve that, as they do a much better job at intercepting the compositor than Godot can probably do using Vulkan or OpenGL natively. If your game runs near real-time when capturing, you can still use this feature but it will play no sound (sound will be saved directly).
Usage:
$ godot --write-movie movie.avi [scene_file.tscn]
Missing:
* Options for configuring video writing via GLOBAL_DEF
* UI Menu for launching with this mode from the editor.
* Add to list of command line options.
* Add a feature tag to override configurations when movie writing (fantastic for saving videos with highest quality settings).
2022-06-17 00:55:19 +02:00
MovieWriter * MovieWriter : : writers [ MovieWriter : : MAX_WRITERS ] ;
uint32_t MovieWriter : : writer_count = 0 ;
void MovieWriter : : add_writer ( MovieWriter * p_writer ) {
ERR_FAIL_COND ( writer_count = = MAX_WRITERS ) ;
writers [ writer_count + + ] = p_writer ;
}
MovieWriter * MovieWriter : : find_writer_for_file ( const String & p_file ) {
for ( int32_t i = writer_count - 1 ; i > = 0 ; i - - ) { // More recent last, to have override ability.
if ( writers [ i ] - > handles_file ( p_file ) ) {
return writers [ i ] ;
}
}
return nullptr ;
}
uint32_t MovieWriter : : get_audio_mix_rate ( ) const {
uint32_t ret = 0 ;
if ( GDVIRTUAL_REQUIRED_CALL ( _get_audio_mix_rate , ret ) ) {
return ret ;
}
return 48000 ;
}
AudioServer : : SpeakerMode MovieWriter : : get_audio_speaker_mode ( ) const {
AudioServer : : SpeakerMode ret = AudioServer : : SPEAKER_MODE_STEREO ;
if ( GDVIRTUAL_REQUIRED_CALL ( _get_audio_speaker_mode , ret ) ) {
return ret ;
}
return AudioServer : : SPEAKER_MODE_STEREO ;
}
Error MovieWriter : : write_begin ( const Size2i & p_movie_size , uint32_t p_fps , const String & p_base_path ) {
Error ret = OK ;
if ( GDVIRTUAL_REQUIRED_CALL ( _write_begin , p_movie_size , p_fps , p_base_path , ret ) ) {
return ret ;
}
return ERR_UNCONFIGURED ;
}
Error MovieWriter : : write_frame ( const Ref < Image > & p_image , const int32_t * p_audio_data ) {
Error ret = OK ;
if ( GDVIRTUAL_REQUIRED_CALL ( _write_frame , p_image , p_audio_data , ret ) ) {
return ret ;
}
return ERR_UNCONFIGURED ;
}
void MovieWriter : : write_end ( ) {
GDVIRTUAL_REQUIRED_CALL ( _write_end ) ;
}
bool MovieWriter : : handles_file ( const String & p_path ) const {
bool ret = false ;
if ( GDVIRTUAL_REQUIRED_CALL ( _handles_file , p_path , ret ) ) {
return ret ;
}
return false ;
}
void MovieWriter : : get_supported_extensions ( List < String > * r_extensions ) const {
Vector < String > exts ;
if ( GDVIRTUAL_REQUIRED_CALL ( _get_supported_extensions , exts ) ) {
for ( int i = 0 ; i < exts . size ( ) ; i + + ) {
r_extensions - > push_back ( exts [ i ] ) ;
}
}
}
void MovieWriter : : begin ( const Size2i & p_movie_size , uint32_t p_fps , const String & p_base_path ) {
2022-06-26 02:06:58 +02:00
project_name = GLOBAL_GET ( " application/config/name " ) ;
2022-06-26 02:56:31 +02:00
print_line ( vformat ( " Movie Maker mode enabled, recording movie at %d FPS... " , p_fps ) ) ;
// Check for available disk space and warn the user if needed.
Ref < DirAccess > dir = DirAccess : : create ( DirAccess : : ACCESS_FILESYSTEM ) ;
String path = p_base_path . get_basename ( ) ;
if ( path . is_relative_path ( ) ) {
path = " res:// " + path ;
}
dir - > open ( path ) ;
if ( dir - > get_space_left ( ) < 10 * Math : : pow ( 1024.0 , 3.0 ) ) {
// Less than 10 GiB available.
WARN_PRINT ( vformat ( " Current available space on disk is low (%s). MovieWriter will fail during movie recording if the disk runs out of available space. " , String : : humanize_size ( dir - > get_space_left ( ) ) ) ) ;
}
Implement Running Godot as Movie Writer
* Allows running the game in "movie writer" mode.
* It ensures entirely stable framerate, so your run can be saved stable and with proper sound (which is impossible if your CPU/GPU can't sustain doing this in real-time).
* If disabling vsync, it can save movies faster than the game is run, but if you want to control the interaction it can get difficult.
* Implements a simple, default MJPEG writer.
This new features has two main use cases, which have high demand:
* Saving game videos in high quality and ensuring the frame rate is *completely* stable, always.
* Using Godot as a tool to make movies and animations (which is ideal if you want interaction, or creating them procedurally. No other software is as good for this).
**Note**: This feature **IS NOT** for capturing real-time footage. Use something like OBS, SimpleScreenRecorder or FRAPS to achieve that, as they do a much better job at intercepting the compositor than Godot can probably do using Vulkan or OpenGL natively. If your game runs near real-time when capturing, you can still use this feature but it will play no sound (sound will be saved directly).
Usage:
$ godot --write-movie movie.avi [scene_file.tscn]
Missing:
* Options for configuring video writing via GLOBAL_DEF
* UI Menu for launching with this mode from the editor.
* Add to list of command line options.
* Add a feature tag to override configurations when movie writing (fantastic for saving videos with highest quality settings).
2022-06-17 00:55:19 +02:00
mix_rate = get_audio_mix_rate ( ) ;
AudioDriverDummy : : get_dummy_singleton ( ) - > set_mix_rate ( mix_rate ) ;
AudioDriverDummy : : get_dummy_singleton ( ) - > set_speaker_mode ( AudioDriver : : SpeakerMode ( get_audio_speaker_mode ( ) ) ) ;
fps = p_fps ;
if ( ( mix_rate % fps ) ! = 0 ) {
2022-06-24 23:37:59 +02:00
WARN_PRINT ( " MovieWriter's audio mix rate ( " + itos ( mix_rate ) + " ) can not be divided by the recording FPS ( " + itos ( fps ) + " ). Audio may go out of sync over time. " ) ;
Implement Running Godot as Movie Writer
* Allows running the game in "movie writer" mode.
* It ensures entirely stable framerate, so your run can be saved stable and with proper sound (which is impossible if your CPU/GPU can't sustain doing this in real-time).
* If disabling vsync, it can save movies faster than the game is run, but if you want to control the interaction it can get difficult.
* Implements a simple, default MJPEG writer.
This new features has two main use cases, which have high demand:
* Saving game videos in high quality and ensuring the frame rate is *completely* stable, always.
* Using Godot as a tool to make movies and animations (which is ideal if you want interaction, or creating them procedurally. No other software is as good for this).
**Note**: This feature **IS NOT** for capturing real-time footage. Use something like OBS, SimpleScreenRecorder or FRAPS to achieve that, as they do a much better job at intercepting the compositor than Godot can probably do using Vulkan or OpenGL natively. If your game runs near real-time when capturing, you can still use this feature but it will play no sound (sound will be saved directly).
Usage:
$ godot --write-movie movie.avi [scene_file.tscn]
Missing:
* Options for configuring video writing via GLOBAL_DEF
* UI Menu for launching with this mode from the editor.
* Add to list of command line options.
* Add a feature tag to override configurations when movie writing (fantastic for saving videos with highest quality settings).
2022-06-17 00:55:19 +02:00
}
audio_channels = AudioDriverDummy : : get_dummy_singleton ( ) - > get_channels ( ) ;
audio_mix_buffer . resize ( mix_rate * audio_channels / fps ) ;
write_begin ( p_movie_size , p_fps , p_base_path ) ;
}
void MovieWriter : : _bind_methods ( ) {
ClassDB : : bind_static_method ( " MovieWriter " , D_METHOD ( " add_writer " , " writer " ) , & MovieWriter : : add_writer ) ;
GDVIRTUAL_BIND ( _get_audio_mix_rate )
GDVIRTUAL_BIND ( _get_audio_speaker_mode )
GDVIRTUAL_BIND ( _handles_file , " path " )
GDVIRTUAL_BIND ( _write_begin , " movie_size " , " fps " , " base_path " )
GDVIRTUAL_BIND ( _write_frame , " frame_image " , " audio_frame_block " )
GDVIRTUAL_BIND ( _write_end )
2022-06-24 23:37:59 +02:00
GLOBAL_DEF ( " editor/movie_writer/mix_rate " , 48000 ) ;
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " editor/movie_writer/mix_rate " , PropertyInfo ( Variant : : INT , " editor/movie_writer/mix_rate " , PROPERTY_HINT_RANGE , " 8000,192000,1,suffix:Hz " ) ) ;
Implement Running Godot as Movie Writer
* Allows running the game in "movie writer" mode.
* It ensures entirely stable framerate, so your run can be saved stable and with proper sound (which is impossible if your CPU/GPU can't sustain doing this in real-time).
* If disabling vsync, it can save movies faster than the game is run, but if you want to control the interaction it can get difficult.
* Implements a simple, default MJPEG writer.
This new features has two main use cases, which have high demand:
* Saving game videos in high quality and ensuring the frame rate is *completely* stable, always.
* Using Godot as a tool to make movies and animations (which is ideal if you want interaction, or creating them procedurally. No other software is as good for this).
**Note**: This feature **IS NOT** for capturing real-time footage. Use something like OBS, SimpleScreenRecorder or FRAPS to achieve that, as they do a much better job at intercepting the compositor than Godot can probably do using Vulkan or OpenGL natively. If your game runs near real-time when capturing, you can still use this feature but it will play no sound (sound will be saved directly).
Usage:
$ godot --write-movie movie.avi [scene_file.tscn]
Missing:
* Options for configuring video writing via GLOBAL_DEF
* UI Menu for launching with this mode from the editor.
* Add to list of command line options.
* Add a feature tag to override configurations when movie writing (fantastic for saving videos with highest quality settings).
2022-06-17 00:55:19 +02:00
GLOBAL_DEF ( " editor/movie_writer/speaker_mode " , 0 ) ;
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " editor/movie_writer/speaker_mode " , PropertyInfo ( Variant : : INT , " editor/movie_writer/speaker_mode " , PROPERTY_HINT_ENUM , " Stereo,3.1,5.1,7.1 " ) ) ;
GLOBAL_DEF ( " editor/movie_writer/mjpeg_quality " , 0.75 ) ;
2022-06-24 23:37:59 +02:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " editor/movie_writer/mjpeg_quality " , PropertyInfo ( Variant : : FLOAT , " editor/movie_writer/mjpeg_quality " , PROPERTY_HINT_RANGE , " 0.01,1.0,0.01 " ) ) ;
Implement Running Godot as Movie Writer
* Allows running the game in "movie writer" mode.
* It ensures entirely stable framerate, so your run can be saved stable and with proper sound (which is impossible if your CPU/GPU can't sustain doing this in real-time).
* If disabling vsync, it can save movies faster than the game is run, but if you want to control the interaction it can get difficult.
* Implements a simple, default MJPEG writer.
This new features has two main use cases, which have high demand:
* Saving game videos in high quality and ensuring the frame rate is *completely* stable, always.
* Using Godot as a tool to make movies and animations (which is ideal if you want interaction, or creating them procedurally. No other software is as good for this).
**Note**: This feature **IS NOT** for capturing real-time footage. Use something like OBS, SimpleScreenRecorder or FRAPS to achieve that, as they do a much better job at intercepting the compositor than Godot can probably do using Vulkan or OpenGL natively. If your game runs near real-time when capturing, you can still use this feature but it will play no sound (sound will be saved directly).
Usage:
$ godot --write-movie movie.avi [scene_file.tscn]
Missing:
* Options for configuring video writing via GLOBAL_DEF
* UI Menu for launching with this mode from the editor.
* Add to list of command line options.
* Add a feature tag to override configurations when movie writing (fantastic for saving videos with highest quality settings).
2022-06-17 00:55:19 +02:00
// used by the editor
GLOBAL_DEF_BASIC ( " editor/movie_writer/movie_file " , " " ) ;
GLOBAL_DEF_BASIC ( " editor/movie_writer/disable_vsync " , false ) ;
GLOBAL_DEF_BASIC ( " editor/movie_writer/fps " , 60 ) ;
2022-06-24 23:37:59 +02:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " editor/movie_writer/fps " , PropertyInfo ( Variant : : INT , " editor/movie_writer/fps " , PROPERTY_HINT_RANGE , " 1,300,1,suffix:FPS " ) ) ;
Implement Running Godot as Movie Writer
* Allows running the game in "movie writer" mode.
* It ensures entirely stable framerate, so your run can be saved stable and with proper sound (which is impossible if your CPU/GPU can't sustain doing this in real-time).
* If disabling vsync, it can save movies faster than the game is run, but if you want to control the interaction it can get difficult.
* Implements a simple, default MJPEG writer.
This new features has two main use cases, which have high demand:
* Saving game videos in high quality and ensuring the frame rate is *completely* stable, always.
* Using Godot as a tool to make movies and animations (which is ideal if you want interaction, or creating them procedurally. No other software is as good for this).
**Note**: This feature **IS NOT** for capturing real-time footage. Use something like OBS, SimpleScreenRecorder or FRAPS to achieve that, as they do a much better job at intercepting the compositor than Godot can probably do using Vulkan or OpenGL natively. If your game runs near real-time when capturing, you can still use this feature but it will play no sound (sound will be saved directly).
Usage:
$ godot --write-movie movie.avi [scene_file.tscn]
Missing:
* Options for configuring video writing via GLOBAL_DEF
* UI Menu for launching with this mode from the editor.
* Add to list of command line options.
* Add a feature tag to override configurations when movie writing (fantastic for saving videos with highest quality settings).
2022-06-17 00:55:19 +02:00
}
void MovieWriter : : set_extensions_hint ( ) {
RBSet < String > found ;
for ( uint32_t i = 0 ; i < writer_count ; i + + ) {
List < String > extensions ;
writers [ i ] - > get_supported_extensions ( & extensions ) ;
for ( const String & ext : extensions ) {
found . insert ( ext ) ;
}
}
String ext_hint ;
for ( const String & S : found ) {
if ( ext_hint ! = " " ) {
ext_hint + = " , " ;
}
ext_hint + = " *. " + S ;
}
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " editor/movie_writer/movie_file " , PropertyInfo ( Variant : : STRING , " editor/movie_writer/movie_file " , PROPERTY_HINT_GLOBAL_SAVE_FILE , ext_hint ) ) ;
}
void MovieWriter : : add_frame ( const Ref < Image > & p_image ) {
2022-06-26 02:06:58 +02:00
const int movie_time_seconds = Engine : : get_singleton ( ) - > get_frames_drawn ( ) / fps ;
const String movie_time = vformat ( " %s:%s:%s " ,
String : : num ( movie_time_seconds / 3600 ) . pad_zeros ( 2 ) ,
String : : num ( ( movie_time_seconds % 3600 ) / 60 ) . pad_zeros ( 2 ) ,
String : : num ( movie_time_seconds % 60 ) . pad_zeros ( 2 ) ) ;
# ifdef DEBUG_ENABLED
DisplayServer : : get_singleton ( ) - > window_set_title ( vformat ( " MovieWriter: Frame %d (time: %s) - %s (DEBUG) " , Engine : : get_singleton ( ) - > get_frames_drawn ( ) , movie_time , project_name ) ) ;
# else
DisplayServer : : get_singleton ( ) - > window_set_title ( vformat ( " MovieWriter: Frame %d (time: %s) - %s " , Engine : : get_singleton ( ) - > get_frames_drawn ( ) , movie_time , project_name ) ) ;
# endif
Implement Running Godot as Movie Writer
* Allows running the game in "movie writer" mode.
* It ensures entirely stable framerate, so your run can be saved stable and with proper sound (which is impossible if your CPU/GPU can't sustain doing this in real-time).
* If disabling vsync, it can save movies faster than the game is run, but if you want to control the interaction it can get difficult.
* Implements a simple, default MJPEG writer.
This new features has two main use cases, which have high demand:
* Saving game videos in high quality and ensuring the frame rate is *completely* stable, always.
* Using Godot as a tool to make movies and animations (which is ideal if you want interaction, or creating them procedurally. No other software is as good for this).
**Note**: This feature **IS NOT** for capturing real-time footage. Use something like OBS, SimpleScreenRecorder or FRAPS to achieve that, as they do a much better job at intercepting the compositor than Godot can probably do using Vulkan or OpenGL natively. If your game runs near real-time when capturing, you can still use this feature but it will play no sound (sound will be saved directly).
Usage:
$ godot --write-movie movie.avi [scene_file.tscn]
Missing:
* Options for configuring video writing via GLOBAL_DEF
* UI Menu for launching with this mode from the editor.
* Add to list of command line options.
* Add a feature tag to override configurations when movie writing (fantastic for saving videos with highest quality settings).
2022-06-17 00:55:19 +02:00
AudioDriverDummy : : get_dummy_singleton ( ) - > mix_audio ( mix_rate / fps , audio_mix_buffer . ptr ( ) ) ;
write_frame ( p_image , audio_mix_buffer . ptr ( ) ) ;
}
void MovieWriter : : end ( ) {
write_end ( ) ;
2022-06-26 01:38:20 +02:00
// Print a report with various statistics.
print_line ( " ---------------- " ) ;
String movie_path = Engine : : get_singleton ( ) - > get_write_movie_path ( ) ;
if ( movie_path . is_relative_path ( ) ) {
// Print absolute path to make finding the file easier,
// and to make it clickable in terminal emulators that support this.
2022-08-30 02:34:01 +02:00
movie_path = ProjectSettings : : get_singleton ( ) - > globalize_path ( " res:// " ) . path_join ( movie_path ) ;
2022-06-26 01:38:20 +02:00
}
print_line ( vformat ( " Done recording movie at path: %s " , movie_path ) ) ;
const int movie_time_seconds = Engine : : get_singleton ( ) - > get_frames_drawn ( ) / fps ;
const String movie_time = vformat ( " %s:%s:%s " ,
String : : num ( movie_time_seconds / 3600 ) . pad_zeros ( 2 ) ,
String : : num ( ( movie_time_seconds % 3600 ) / 60 ) . pad_zeros ( 2 ) ,
String : : num ( movie_time_seconds % 60 ) . pad_zeros ( 2 ) ) ;
const int real_time_seconds = Time : : get_singleton ( ) - > get_ticks_msec ( ) / 1000 ;
const String real_time = vformat ( " %s:%s:%s " ,
String : : num ( real_time_seconds / 3600 ) . pad_zeros ( 2 ) ,
String : : num ( ( real_time_seconds % 3600 ) / 60 ) . pad_zeros ( 2 ) ,
String : : num ( real_time_seconds % 60 ) . pad_zeros ( 2 ) ) ;
print_line ( vformat ( " %d frames at %d FPS (movie length: %s), recorded in %s (%d%% of real-time speed). " , Engine : : get_singleton ( ) - > get_frames_drawn ( ) , fps , movie_time , real_time , ( float ( movie_time_seconds ) / real_time_seconds ) * 100 ) ) ;
print_line ( " ---------------- " ) ;
Implement Running Godot as Movie Writer
* Allows running the game in "movie writer" mode.
* It ensures entirely stable framerate, so your run can be saved stable and with proper sound (which is impossible if your CPU/GPU can't sustain doing this in real-time).
* If disabling vsync, it can save movies faster than the game is run, but if you want to control the interaction it can get difficult.
* Implements a simple, default MJPEG writer.
This new features has two main use cases, which have high demand:
* Saving game videos in high quality and ensuring the frame rate is *completely* stable, always.
* Using Godot as a tool to make movies and animations (which is ideal if you want interaction, or creating them procedurally. No other software is as good for this).
**Note**: This feature **IS NOT** for capturing real-time footage. Use something like OBS, SimpleScreenRecorder or FRAPS to achieve that, as they do a much better job at intercepting the compositor than Godot can probably do using Vulkan or OpenGL natively. If your game runs near real-time when capturing, you can still use this feature but it will play no sound (sound will be saved directly).
Usage:
$ godot --write-movie movie.avi [scene_file.tscn]
Missing:
* Options for configuring video writing via GLOBAL_DEF
* UI Menu for launching with this mode from the editor.
* Add to list of command line options.
* Add a feature tag to override configurations when movie writing (fantastic for saving videos with highest quality settings).
2022-06-17 00:55:19 +02:00
}