Add -ffmpeg-video-opts and -ffmpeg-audio-opts

This commit is contained in:
dec05eba
2026-01-05 20:24:41 +01:00
parent cb9cb6c567
commit f1acb95cf3
5 changed files with 42 additions and 4 deletions

4
TODO
View File

@@ -387,3 +387,7 @@ Support camera controls, such as white balance. Otherwise tell user to use camer
Camera capture doesn't work perfectly. The image gets glitched, need to properly wait for image to be done.
Use one pipewire connection (pipewire video) instead of multiple ones when recording with portal multiple times (multiple sources).
Close pipewire links or maybe there are file descriptor leaks?
Make multiple capture sources work properly in regards to size. The size of the video should be the region size of each capture source.

View File

@@ -302,9 +302,25 @@ Script to run after saving video. Receives filepath and type ("regular", "replay
Portal session token file (default: ~/.config/gpu-screen-recorder/restore_token).
.TP
.BI \-ffmpeg-opts " options"
Additional arguments to pass to FFmpeg in a list of key-values pairs in the format "key=value;key=value",
Additional arguments to pass to FFmpeg for the file in a list of key-values pairs in the format "key=value;key=value",
.br
for example: -ffmpeg-opts "hls_list_size=3;hls_time=1;hls_flags=delete_segments".
.br
Note: this overwrites options set by GPU Screen Recorder with the same name.
.TP
.BI \-ffmpeg-video-opts " options"
Additional arguments to pass to FFmpeg for the video in a list of key-values pairs in the format "key=value;key=value",
.br
for example: -ffmpeg-video-opts "codec=cabac;rc_mode=CQP;qp=16".
.br
Note: this overwrites options set by GPU Screen Recorder with the same name.
.TP
.BI \-ffmpeg-audio-opts " options"
Additional arguments to pass to FFmpeg for the audio in a list of key-values pairs in the format "key=value;key=value",
.br
for example: -ffmpeg-audio-opts "aac_coder=fast;aac_pce=true".
.br
Note: this overwrites options set by GPU Screen Recorder with the same name.
.TP
.BI \-gl\-debug " yes|no"
OpenGL debug output (default: no).

View File

@@ -8,7 +8,7 @@
typedef struct gsr_egl gsr_egl;
#define NUM_ARGS 33
#define NUM_ARGS 35
typedef enum {
GSR_CAPTURE_SOURCE_TYPE_WINDOW,
@@ -86,6 +86,8 @@ typedef struct {
const char *portal_session_token_filepath;
const char *recording_saved_script;
const char *ffmpeg_opts;
const char *ffmpeg_video_opts;
const char *ffmpeg_audio_opts;
bool verbose;
bool gl_debug;
bool fallback_cpu_encoding;

View File

@@ -441,6 +441,8 @@ static bool args_parser_set_values(args_parser *self) {
}
self->ffmpeg_opts = args_get_value_by_key(self->args, NUM_ARGS, "-ffmpeg-opts");
self->ffmpeg_video_opts = args_get_value_by_key(self->args, NUM_ARGS, "-ffmpeg-video-opts");
self->ffmpeg_audio_opts = args_get_value_by_key(self->args, NUM_ARGS, "-ffmpeg-audio-opts");
return true;
}
@@ -532,6 +534,8 @@ bool args_parser_parse(args_parser *self, int argc, char **argv, const args_hand
self->args[arg_index++] = (Arg){ .key = "-replay-storage", .optional = true, .list = false, .type = ARG_TYPE_ENUM, .enum_values = replay_storage_enums, .num_enum_values = sizeof(replay_storage_enums)/sizeof(ArgEnum) };
self->args[arg_index++] = (Arg){ .key = "-p", .optional = true, .list = true, .type = ARG_TYPE_STRING };
self->args[arg_index++] = (Arg){ .key = "-ffmpeg-opts", .optional = true, .list = false, .type = ARG_TYPE_STRING };
self->args[arg_index++] = (Arg){ .key = "-ffmpeg-video-opts", .optional = true, .list = false, .type = ARG_TYPE_STRING };
self->args[arg_index++] = (Arg){ .key = "-ffmpeg-audio-opts", .optional = true, .list = false, .type = ARG_TYPE_STRING };
assert(arg_index == NUM_ARGS);
for(int i = 1; i < argc; i += 2) {

View File

@@ -528,10 +528,13 @@ static AVCodecContext *create_video_codec_context(AVPixelFormat pix_fmt, const A
return codec_context;
}
static void open_audio(AVCodecContext *audio_codec_context) {
static void open_audio(AVCodecContext *audio_codec_context, const char *ffmpeg_audio_opts) {
AVDictionary *options = nullptr;
av_dict_set(&options, "strict", "experimental", 0);
if(ffmpeg_audio_opts)
av_dict_parse_string(&options, ffmpeg_audio_opts, "=", ";", 0);
int ret;
ret = avcodec_open2(audio_codec_context, audio_codec_context->codec, &options);
if(ret < 0) {
@@ -678,6 +681,9 @@ static void open_video_software(AVCodecContext *codec_context, const args_parser
av_dict_set(&options, "strict", "experimental", 0);
if(arg_parser.ffmpeg_video_opts)
av_dict_parse_string(&options, arg_parser.ffmpeg_video_opts, "=", ";", 0);
int ret = avcodec_open2(codec_context, codec_context->codec, &options);
if (ret < 0) {
fprintf(stderr, "gsr error: Could not open video codec: %s\n", av_error_to_string(ret));
@@ -926,6 +932,9 @@ static void open_video_hardware(AVCodecContext *codec_context, bool low_power, c
av_dict_set(&options, "strict", "experimental", 0);
if(arg_parser.ffmpeg_video_opts)
av_dict_parse_string(&options, arg_parser.ffmpeg_video_opts, "=", ";", 0);
int ret = avcodec_open2(codec_context, codec_context->codec, &options);
if (ret < 0) {
fprintf(stderr, "gsr error: Could not open video codec: %s\n", av_error_to_string(ret));
@@ -1219,6 +1228,7 @@ static RecordingStartResult start_recording_create_streams(const char *filename,
AVDictionary *options = nullptr;
av_dict_set(&options, "strict", "experimental", 0);
if(args_parser.ffmpeg_opts)
av_dict_parse_string(&options, args_parser.ffmpeg_opts, "=", ";", 0);
@@ -2388,6 +2398,7 @@ static std::vector<VideoSource> create_video_sources(const args_parser &arg_pars
}
}
// TODO: Video size should be end pos - start pos, where start pos = pos and end pos = pos + size
video_size = {0, 0};
for(const VideoSource &video_source : video_sources) {
video_size.x = std::max(video_size.x, video_source.metadata.video_size.x);
@@ -3441,6 +3452,7 @@ static bool av_open_file_write_header(AVFormatContext *av_format_context, const
AVDictionary *options = nullptr;
av_dict_set(&options, "strict", "experimental", 0);
if(ffmpeg_opts)
av_dict_parse_string(&options, ffmpeg_opts, "=", ";", 0);
@@ -3934,7 +3946,7 @@ int main(int argc, char **argv) {
if(audio_stream && !merged_audio_inputs.track_name.empty())
av_dict_set(&audio_stream->metadata, "title", merged_audio_inputs.track_name.c_str(), 0);
open_audio(audio_codec_context);
open_audio(audio_codec_context, arg_parser.ffmpeg_audio_opts);
if(audio_stream)
avcodec_parameters_from_context(audio_stream->codecpar, audio_codec_context);