diff --git a/obs/data/locale/en-US.ini b/obs/data/locale/en-US.ini
index bf35c1c5a..ef4741c66 100644
--- a/obs/data/locale/en-US.ini
+++ b/obs/data/locale/en-US.ini
@@ -326,6 +326,9 @@ Basic.Settings.Output.Adv.Recording.Type="Type"
Basic.Settings.Output.Adv.Recording.Type.Standard="Standard"
Basic.Settings.Output.Adv.Recording.Type.FFmpegOutput="Custom Output (FFmpeg)"
Basic.Settings.Output.Adv.Recording.UseStreamEncoder="(Use stream encoder)"
+Basic.Settings.Output.Adv.FFmpeg.Type="FFmpeg Output Type"
+Basic.Settings.Output.Adv.FFmpeg.Type.URL="Output to URL"
+Basic.Settings.Output.Adv.FFmpeg.Type.RecordToFile="Output to File"
Basic.Settings.Output.Adv.FFmpeg.SaveFilter.Common="Common recording formats"
Basic.Settings.Output.Adv.FFmpeg.SaveFilter.All="All Files"
Basic.Settings.Output.Adv.FFmpeg.SavePathURL="File path or URL"
diff --git a/obs/forms/OBSBasicSettings.ui b/obs/forms/OBSBasicSettings.ui
index 33fd51f96..646628996 100644
--- a/obs/forms/OBSBasicSettings.ui
+++ b/obs/forms/OBSBasicSettings.ui
@@ -7,7 +7,7 @@
0
0
895
- 602
+ 614
@@ -1293,7 +1293,7 @@
0
- -
+
-
@@ -1315,42 +1315,104 @@
- -
-
-
-
-
-
- true
+
-
+
+
+ 0
+
+
+
+
+ 3
-
-
- -
-
-
- true
+
+ 0
-
- Browse
+
+ 0
-
-
-
+
+ 0
+
+
+ 0
+
+ -
+
+
+ true
+
+
+
+ -
+
+
+ Browse
+
+
+
+
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ true
+
+
+
+
+
+
- -
+
-
Basic.Settings.Output.Adv.FFmpeg.Format
+ -
+
+
-
+
+
+ Basic.Settings.Output.Adv.FFmpeg.FormatDesc
+
+
+
+ -
+
+
+
+
+
+
+ -
Basic.Settings.Output.VideoBitrate
- -
+
-
0
@@ -1363,7 +1425,7 @@
- -
+
-
@@ -1379,7 +1441,7 @@
- -
+
-
false
@@ -1389,34 +1451,34 @@
- -
+
-
Basic.Settings.Output.Adv.FFmpeg.VEncoder
- -
+
-
- -
+
-
Basic.Settings.Output.Adv.FFmpeg.VEncoderSettings
- -
+
-
- -
+
-
Basic.Settings.Output.AudioBitrate
- -
+
-
32
@@ -1432,14 +1494,14 @@
- -
+
-
Basic.Settings.Output.Adv.AudioTrack
- -
+
-
@@ -1494,43 +1556,62 @@
- -
+
-
Basic.Settings.Output.Adv.FFmpeg.AEncoder
- -
+
-
+
+
+ -
Basic.Settings.Output.Adv.FFmpeg.AEncoderSettings
- -
+
-
- -
-
-
- -
-
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 170
+ 0
+
+
-
+ Basic.Settings.Output.Adv.FFmpeg.Type
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
- -
-
-
- Basic.Settings.Output.Adv.FFmpeg.FormatDesc
-
+
-
+
+
-
+
+ Basic.Settings.Output.Adv.FFmpeg.Type.RecordToFile
+
+
+ -
+
+ Basic.Settings.Output.Adv.FFmpeg.Type.URL
+
+
- -
-
-
@@ -2171,8 +2252,8 @@
0
0
- 98
- 28
+ 67
+ 16
@@ -2559,8 +2640,8 @@
0
0
- 325
- 229
+ 428
+ 287
@@ -2789,8 +2870,8 @@
setCurrentIndex(int)
- 310
- 29
+ 159
+ 34
241
@@ -2821,12 +2902,12 @@
setEnabled(bool)
- 422
- 168
+ 875
+ 254
- 420
- 188
+ 875
+ 291
@@ -2837,12 +2918,12 @@
setEnabled(bool)
- 503
- 160
+ 875
+ 254
- 501
- 209
+ 875
+ 328
@@ -2853,12 +2934,12 @@
setVisible(bool)
- 439
- 240
+ 875
+ 360
- 750
- 295
+ 875
+ 427
@@ -2869,12 +2950,12 @@
setVisible(bool)
- 482
- 241
+ 875
+ 360
- 367
- 295
+ 466
+ 427
@@ -2885,12 +2966,12 @@
setVisible(bool)
- 459
- 234
+ 875
+ 360
- 750
- 347
+ 875
+ 503
@@ -2901,12 +2982,12 @@
setVisible(bool)
- 554
- 236
+ 875
+ 360
- 367
- 347
+ 466
+ 503
@@ -2917,12 +2998,12 @@
setVisible(bool)
- 398
- 241
+ 871
+ 360
- 410
- 261
+ 875
+ 392
@@ -2933,12 +3014,12 @@
setEnabled(bool)
- 318
- 312
+ 466
+ 464
- 473
- 311
+ 875
+ 464
@@ -2949,12 +3030,12 @@
setVisible(bool)
- 456
- 241
+ 875
+ 360
- 260
- 315
+ 457
+ 464
@@ -2965,12 +3046,12 @@
setVisible(bool)
- 525
- 238
+ 875
+ 360
- 519
- 317
+ 875
+ 464
@@ -2981,12 +3062,12 @@
setCurrentIndex(int)
- 259
- 101
+ 705
+ 144
- 243
- 106
+ 396
+ 245
@@ -2997,12 +3078,12 @@
setEnabled(bool)
- 259
- 113
+ 514
+ 344
- 230
- 125
+ 748
+ 344
@@ -3013,12 +3094,12 @@
setEnabled(bool)
- 468
- 110
+ 864
+ 141
- 362
- 136
+ 427
+ 178
@@ -3029,12 +3110,12 @@
setEnabled(bool)
- 468
- 110
+ 864
+ 141
- 468
- 136
+ 864
+ 178
@@ -3045,12 +3126,12 @@
setEnabled(bool)
- 468
- 110
+ 864
+ 141
- 299
- 162
+ 427
+ 215
@@ -3061,12 +3142,12 @@
setEnabled(bool)
- 468
- 110
+ 864
+ 141
- 468
- 162
+ 864
+ 215
@@ -3077,12 +3158,12 @@
setEnabled(bool)
- 270
- 237
+ 427
+ 355
- 437
- 237
+ 862
+ 355
@@ -3093,12 +3174,12 @@
setEnabled(bool)
- 259
- 113
+ 424
+ 331
- 230
- 125
+ 658
+ 331
@@ -3109,12 +3190,12 @@
setEnabled(bool)
- 444
- 162
+ 875
+ 254
- 298
- 190
+ 466
+ 291
@@ -3125,12 +3206,28 @@
setEnabled(bool)
- 475
- 161
+ 875
+ 254
- 350
- 218
+ 466
+ 328
+
+
+
+
+ advOutFFType
+ currentIndexChanged(int)
+ stackedWidget_2
+ setCurrentIndex(int)
+
+
+ 732
+ 179
+
+
+ 777
+ 206
diff --git a/obs/window-basic-main-outputs.cpp b/obs/window-basic-main-outputs.cpp
index a35bd0456..591f3f9bf 100644
--- a/obs/window-basic-main-outputs.cpp
+++ b/obs/window-basic-main-outputs.cpp
@@ -298,6 +298,7 @@ struct AdvancedOutput : BasicOutputHandler {
OBSEncoder h264Streaming;
OBSEncoder h264Recording;
+ bool ffmpegOutput;
bool ffmpegRecording;
bool useStreamEncoder;
@@ -351,7 +352,9 @@ AdvancedOutput::AdvancedOutput(OBSBasic *main_) : BasicOutputHandler(main_)
const char *recordEncoder = config_get_string(main->Config(), "AdvOut",
"RecEncoder");
- ffmpegRecording = astrcmpi(recType, "FFmpeg") == 0;
+ ffmpegOutput = astrcmpi(recType, "FFmpeg") == 0;
+ ffmpegRecording = ffmpegOutput &&
+ config_get_bool(main->Config(), "AdvOut", "FFOutputToFile");
useStreamEncoder = astrcmpi(recordEncoder, "none") == 0;
OBSData streamEncSettings = GetDataFromJsonFile("streamEncoder.json");
@@ -363,7 +366,7 @@ AdvancedOutput::AdvancedOutput(OBSBasic *main_) : BasicOutputHandler(main_)
throw "Failed to create stream output (advanced output)";
obs_output_release(streamOutput);
- if (ffmpegRecording) {
+ if (ffmpegOutput) {
fileOutput = obs_output_create("ffmpeg_output",
"adv_ffmpeg_output", nullptr, nullptr);
if (!fileOutput)
@@ -447,7 +450,7 @@ inline void AdvancedOutput::UpdateRecordingSettings()
void AdvancedOutput::Update()
{
UpdateStreamSettings();
- if (!useStreamEncoder && !ffmpegRecording)
+ if (!useStreamEncoder && !ffmpegOutput)
UpdateRecordingSettings();
UpdateAudioSettings();
}
@@ -649,7 +652,7 @@ void AdvancedOutput::SetupOutputs()
SetupStreaming();
- if (ffmpegRecording)
+ if (ffmpegOutput)
SetupFFmpeg();
else
SetupRecording();
@@ -667,7 +670,7 @@ int AdvancedOutput::GetAudioBitrate(size_t i) const
bool AdvancedOutput::StartStreaming(obs_service_t *service)
{
if (!useStreamEncoder ||
- (!ffmpegRecording && !obs_output_active(fileOutput))) {
+ (!ffmpegOutput && !obs_output_active(fileOutput))) {
UpdateStreamSettings();
}
@@ -697,8 +700,11 @@ bool AdvancedOutput::StartStreaming(obs_service_t *service)
bool AdvancedOutput::StartRecording()
{
+ const char *path;
+ const char *format;
+
if (!useStreamEncoder) {
- if (!ffmpegRecording) {
+ if (!ffmpegOutput) {
UpdateRecordingSettings();
}
} else if (!obs_output_active(streamOutput)) {
@@ -710,11 +716,11 @@ bool AdvancedOutput::StartRecording()
if (!Active())
SetupOutputs();
- if (!ffmpegRecording) {
- const char *path = config_get_string(main->Config(),
- "AdvOut", "RecFilePath");
- const char *format = config_get_string(main->Config(),
- "AdvOut", "RecFormat");
+ if (!ffmpegOutput || ffmpegRecording) {
+ path = config_get_string(main->Config(), "AdvOut",
+ ffmpegRecording ? "FFFilePath" : "RecFilePath");
+ format = config_get_string(main->Config(), "AdvOut",
+ ffmpegRecording ? "FFExtension" : "RecFormat");
os_dir_t *dir = path ? os_opendir(path) : nullptr;
@@ -737,7 +743,9 @@ bool AdvancedOutput::StartRecording()
strPath += GenerateTimeDateFilename(format);
obs_data_t *settings = obs_data_create();
- obs_data_set_string(settings, "path", strPath.c_str());
+ obs_data_set_string(settings,
+ ffmpegRecording ? "url" : "path",
+ strPath.c_str());
obs_output_update(fileOutput, settings);
diff --git a/obs/window-basic-main.cpp b/obs/window-basic-main.cpp
index c3b40056b..f0e1c718e 100644
--- a/obs/window-basic-main.cpp
+++ b/obs/window-basic-main.cpp
@@ -681,6 +681,11 @@ bool OBSBasic::InitBasicConfigDefaults()
config_set_default_string(basicConfig, "AdvOut", "RecEncoder",
"none");
+ config_set_default_bool (basicConfig, "AdvOut", "FFOutputToFile",
+ true);
+ config_set_default_string(basicConfig, "AdvOut", "FFFilePath",
+ GetDefaultVideoSavePath().c_str());
+ config_set_default_string(basicConfig, "AdvOut", "FFExtension", "mp4");
config_set_default_uint (basicConfig, "AdvOut", "FFVBitrate", 2500);
config_set_default_bool (basicConfig, "AdvOut", "FFUseRescale",
false);
diff --git a/obs/window-basic-settings.cpp b/obs/window-basic-settings.cpp
index 3814e13c4..96a1fb09b 100644
--- a/obs/window-basic-settings.cpp
+++ b/obs/window-basic-settings.cpp
@@ -300,6 +300,8 @@ OBSBasicSettings::OBSBasicSettings(QWidget *parent)
HookWidget(ui->advOutRecTrack2, CHECK_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutRecTrack3, CHECK_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutRecTrack4, CHECK_CHANGED, OUTPUTS_CHANGED);
+ HookWidget(ui->advOutFFType, COMBO_CHANGED, OUTPUTS_CHANGED);
+ HookWidget(ui->advOutFFRecPath, EDIT_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFURL, EDIT_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFFormat, COMBO_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutFFVBitrate, SCROLL_CHANGED, OUTPUTS_CHANGED);
@@ -1172,6 +1174,10 @@ static void SelectEncoder(QComboBox *combo, const char *name, int id)
void OBSBasicSettings::LoadAdvOutputFFmpegSettings()
{
+ bool saveFile = config_get_bool(main->Config(), "AdvOut",
+ "FFOutputToFile");
+ const char *path = config_get_string(main->Config(), "AdvOut",
+ "FFFilePath");
const char *url = config_get_string(main->Config(), "AdvOut", "FFURL");
const char *format = config_get_string(main->Config(), "AdvOut",
"FFFormat");
@@ -1200,7 +1206,9 @@ void OBSBasicSettings::LoadAdvOutputFFmpegSettings()
const char *aEncCustom = config_get_string(main->Config(), "AdvOut",
"FFACustom");
- ui->advOutFFURL->setText(url);
+ ui->advOutFFType->setCurrentIndex(saveFile ? 0 : 1);
+ ui->advOutFFRecPath->setText(QT_UTF8(path));
+ ui->advOutFFURL->setText(QT_UTF8(url));
SelectFormat(ui->advOutFFFormat, format, mimeType);
ui->advOutFFVBitrate->setValue(videoBitrate);
ui->advOutFFUseRescale->setChecked(rescale);
@@ -2008,11 +2016,23 @@ void OBSBasicSettings::SaveFormat(QComboBox *combo)
desc.name);
config_set_string(main->Config(), "AdvOut", "FFFormatMimeType",
desc.mimeType);
+
+ const char *ext = ff_format_desc_extensions(desc.desc);
+ string extStr = ext;
+
+ char *comma = strchr(&extStr[0], ',');
+ if (comma)
+ comma = 0;
+
+ config_set_string(main->Config(), "AdvOut", "FFExtension",
+ extStr.c_str());
} else {
config_set_string(main->Config(), "AdvOut", "FFFormat",
nullptr);
config_set_string(main->Config(), "AdvOut", "FFFormatMimeType",
nullptr);
+
+ config_remove_value(main->Config(), "AdvOut", "FFExtension");
}
}
@@ -2078,6 +2098,9 @@ void OBSBasicSettings::SaveOutputSettings()
(ui->advOutRecTrack3->isChecked() ? (1<<2) : 0) |
(ui->advOutRecTrack4->isChecked() ? (1<<3) : 0));
+ config_set_bool(main->Config(), "AdvOut", "FFOutputToFile",
+ ui->advOutFFType->currentIndex() == 0 ? true : false);
+ SaveEdit(ui->advOutFFRecPath, "AdvOut", "FFFilePath");
SaveEdit(ui->advOutFFURL, "AdvOut", "FFURL");
SaveFormat(ui->advOutFFFormat);
SaveSpinBox(ui->advOutFFVBitrate, "AdvOut", "FFVBitrate");
@@ -2387,19 +2410,15 @@ void OBSBasicSettings::on_advOutRecPathBrowse_clicked()
void OBSBasicSettings::on_advOutFFPathBrowse_clicked()
{
- QString filter;
- filter += QTStr("Basic.Settings.Output.Adv.FFmpeg.SaveFilter.Common");
- filter += " (*.avi *.mp4 *.flv *.ts *.mkv *.wav *.aac);;";
- filter += QTStr("Basic.Settings.Output.Adv.FFmpeg.SaveFilter.All");
- filter += " (*.*)";
-
- QString file = QFileDialog::getSaveFileName(this,
- QTStr("Basic.Settings.Output.SelectFile"),
- ui->simpleOutputPath->text(), filter);
- if (file.isEmpty())
+ QString dir = QFileDialog::getExistingDirectory(this,
+ QTStr("Basic.Settings.Output.SelectDirectory"),
+ ui->advOutRecPath->text(),
+ QFileDialog::ShowDirsOnly |
+ QFileDialog::DontResolveSymlinks);
+ if (dir.isEmpty())
return;
- ui->advOutFFURL->setText(file);
+ ui->advOutFFRecPath->setText(dir);
}
void OBSBasicSettings::on_advOutEncoder_currentIndexChanged(int idx)