diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini
index 8e781b05c..93994c4ad 100644
--- a/UI/data/locale/en-US.ini
+++ b/UI/data/locale/en-US.ini
@@ -707,6 +707,11 @@ Basic.Settings.Stream.StreamSettingsWarning="Open Settings"
Basic.Settings.Stream.MissingUrlAndApiKey="URL and Stream Key are missing.\n\nOpen settings to enter the URL and Stream Key in the 'stream' tab."
Basic.Settings.Stream.MissingUrl="Stream URL is missing.\n\nOpen settings to enter the URL in the 'Stream' tab."
Basic.Settings.Stream.MissingStreamKey="Stream key is missing.\n\nOpen settings to enter the stream key in the 'Stream' tab."
+Basic.Settings.Stream.IgnoreRecommended="Ignore streaming service setting recommendations"
+Basic.Settings.Stream.IgnoreRecommended.Warn.Title="Override Recommended Settings"
+Basic.Settings.Stream.IgnoreRecommended.Warn.Text="Warning: Ignoring the service's limitations may result in degraded stream quality or prevent you from streaming.\n\nContinue?"
+Basic.Settings.Stream.Recommended.MaxVideoBitrate="Maximum Video Bitrate: %1 kbps"
+Basic.Settings.Stream.Recommended.MaxAudioBitrate="Maximum Audio Bitrate: %1 kbps"
# basic mode 'output' settings
Basic.Settings.Output="Output"
@@ -714,7 +719,6 @@ Basic.Settings.Output.Format="Recording Format"
Basic.Settings.Output.Encoder="Encoder"
Basic.Settings.Output.SelectDirectory="Select Recording Directory"
Basic.Settings.Output.SelectFile="Select Recording File"
-Basic.Settings.Output.EnforceBitrate="Enforce streaming service bitrate limits"
Basic.Settings.Output.DynamicBitrate="Dynamically change bitrate to manage congestion"
Basic.Settings.Output.DynamicBitrate.Beta="Dynamically change bitrate to manage congestion (Beta)"
Basic.Settings.Output.DynamicBitrate.TT="Instead of dropping frames to reduce congestion, dynamically changes bitrate on the fly.\n\nNote that this can increase delay to viewers if there is significant sudden congestion.\nWhen the bitrate drops, it can take up to a few minutes to restore.\n\nCurrently only supported for RTMP."
@@ -735,8 +739,8 @@ Basic.Settings.Output.Simple.RecordingQuality.Stream="Same as stream"
Basic.Settings.Output.Simple.RecordingQuality.Small="High Quality, Medium File Size"
Basic.Settings.Output.Simple.RecordingQuality.HQ="Indistinguishable Quality, Large File Size"
Basic.Settings.Output.Simple.RecordingQuality.Lossless="Lossless Quality, Tremendously Large File Size"
-Basic.Settings.Output.Simple.Warn.VideoBitrate="Warning: The streaming video bitrate will be set to %1, which is the upper limit for the current streaming service. If you're sure you want to go above %1, enable advanced encoder options and uncheck \"Enforce streaming service bitrate limits\"."
-Basic.Settings.Output.Simple.Warn.AudioBitrate="Warning: The streaming audio bitrate will be set to %1, which is the upper limit for the current streaming service. If you're sure you want to go above %1, enable advanced encoder options and uncheck \"Enforce streaming service bitrate limits\"."
+Basic.Settings.Output.Simple.Warn.VideoBitrate="Warning: The streaming video bitrate will be set to %1, which is the upper limit for the current streaming service."
+Basic.Settings.Output.Simple.Warn.AudioBitrate="Warning: The streaming audio bitrate will be set to %1, which is the upper limit for the current streaming service."
Basic.Settings.Output.Simple.Warn.CannotPause="Warning: Recordings cannot be paused if the recording quality is set to \"Same as stream\"."
Basic.Settings.Output.Simple.Warn.Encoder="Warning: Recording with a software encoder at a different quality than the stream will require extra CPU usage if you stream and record at the same time."
Basic.Settings.Output.Simple.Warn.Lossless="Warning: Lossless quality generates tremendously large file sizes! Lossless quality can use upward of 7 gigabytes of disk space per minute at high resolutions and framerates. Lossless is not recommended for long recordings unless you have a very large amount of disk space available."
diff --git a/UI/forms/OBSBasicSettings.ui b/UI/forms/OBSBasicSettings.ui
index 83c6cd204..8aa0be24b 100644
--- a/UI/forms/OBSBasicSettings.ui
+++ b/UI/forms/OBSBasicSettings.ui
@@ -151,8 +151,8 @@
0
0
- 806
- 1254
+ 803
+ 1026
@@ -1245,6 +1245,20 @@
+ -
+
+
+ Basic.Settings.Stream.IgnoreRecommended
+
+
+
+ -
+
+
+
+
+
+
@@ -1281,8 +1295,8 @@
0
0
- 813
- 761
+ 601
+ 602
@@ -1427,6 +1441,19 @@
+ -
+
+
+ Basic.Settings.Output.Encoder
+
+
+ simpleOutRecEncoder
+
+
+
+ -
+
+
-
@@ -1509,10 +1536,7 @@
- -
-
-
- -
+
-
true
@@ -1525,7 +1549,10 @@
- -
+
-
+
+
+ -
Basic.Settings.Output.CustomEncoderSettings
@@ -1535,29 +1562,9 @@
- -
+
-
- -
-
-
- Basic.Settings.Output.EnforceBitrate
-
-
-
- -
-
-
- -
-
-
- Basic.Settings.Output.Encoder
-
-
- simpleOutRecEncoder
-
-
-
@@ -3776,8 +3783,8 @@
0
0
- 767
- 582
+ 555
+ 469
@@ -4632,8 +4639,8 @@
0
0
- 791
- 970
+ 599
+ 781
@@ -5507,7 +5514,6 @@
simpleOutStrEncoder
simpleOutputABitrate
simpleOutAdvanced
- simpleOutEnforce
simpleOutPreset
simpleOutCustom
simpleOutputPath
@@ -5834,22 +5840,6 @@
-
- simpleOutAdvanced
- toggled(bool)
- simpleOutEnforce
- setVisible(bool)
-
-
- 251
- 64
-
-
- 251
- 64
-
-
-
systemTrayEnabled
toggled(bool)
diff --git a/UI/window-basic-main-outputs.cpp b/UI/window-basic-main-outputs.cpp
index 7df2a2c95..42fdbecbe 100644
--- a/UI/window-basic-main-outputs.cpp
+++ b/UI/window-basic-main-outputs.cpp
@@ -482,8 +482,8 @@ void SimpleOutput::Update()
int audioBitrate = GetAudioBitrate();
bool advanced =
config_get_bool(main->Config(), "SimpleOutput", "UseAdvanced");
- bool enforceBitrate = config_get_bool(main->Config(), "SimpleOutput",
- "EnforceBitrate");
+ bool enforceBitrate = !config_get_bool(main->Config(), "Stream1",
+ "IgnoreRecommended");
const char *custom = config_get_string(main->Config(), "SimpleOutput",
"x264Settings");
const char *encoder = config_get_string(main->Config(), "SimpleOutput",
@@ -521,7 +521,7 @@ void SimpleOutput::Update()
obs_service_apply_encoder_settings(main->GetService(), h264Settings,
aacSettings);
- if (advanced && !enforceBitrate) {
+ if (!enforceBitrate) {
obs_data_set_int(h264Settings, "bitrate", videoBitrate);
obs_data_set_int(aacSettings, "bitrate", audioBitrate);
}
@@ -1250,6 +1250,8 @@ void AdvancedOutput::UpdateStreamSettings()
{
bool applyServiceSettings = config_get_bool(main->Config(), "AdvOut",
"ApplyServiceSettings");
+ bool enforceBitrate = !config_get_bool(main->Config(), "Stream1",
+ "IgnoreRecommended");
bool dynBitrate =
config_get_bool(main->Config(), "Output", "DynamicBitrate");
const char *streamEncoder =
@@ -1258,9 +1260,13 @@ void AdvancedOutput::UpdateStreamSettings()
OBSData settings = GetDataFromJsonFile("streamEncoder.json");
ApplyEncoderDefaults(settings, h264Streaming);
- if (applyServiceSettings)
+ if (applyServiceSettings) {
+ int bitrate = (int)obs_data_get_int(settings, "bitrate");
obs_service_apply_encoder_settings(main->GetService(), settings,
nullptr);
+ if (!enforceBitrate)
+ obs_data_set_int(settings, "bitrate", bitrate);
+ }
if (dynBitrate && astrcmpi(streamEncoder, "jim_nvenc") == 0)
obs_data_set_bool(settings, "lookahead", false);
@@ -1480,6 +1486,8 @@ inline void AdvancedOutput::UpdateAudioSettings()
{
bool applyServiceSettings = config_get_bool(main->Config(), "AdvOut",
"ApplyServiceSettings");
+ bool enforceBitrate = !config_get_bool(main->Config(), "Stream1",
+ "IgnoreRecommended");
int streamTrackIndex =
config_get_int(main->Config(), "AdvOut", "TrackIndex");
int vodTrackIndex =
@@ -1510,9 +1518,15 @@ inline void AdvancedOutput::UpdateAudioSettings()
if (track == streamTrackIndex || track == vodTrackIndex) {
if (applyServiceSettings) {
+ int bitrate = (int)obs_data_get_int(settings[i],
+ "bitrate");
obs_service_apply_encoder_settings(
main->GetService(), nullptr,
settings[i]);
+
+ if (!enforceBitrate)
+ obs_data_set_int(settings[i], "bitrate",
+ bitrate);
}
}
diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp
index 5f9f99d33..98ce9fb9e 100644
--- a/UI/window-basic-main.cpp
+++ b/UI/window-basic-main.cpp
@@ -1266,6 +1266,22 @@ bool OBSBasic::InitBasicConfigDefaults()
changed = true;
}
+ /* ----------------------------------------------------- */
+ /* move bitrate enforcement setting to new value */
+ if (config_has_user_value(basicConfig, "SimpleOutput",
+ "EnforceBitrate") &&
+ !config_has_user_value(basicConfig, "Stream1",
+ "IgnoreRecommended") &&
+ !config_has_user_value(basicConfig, "Stream1", "MovedOldEnforce")) {
+ bool enforce = config_get_bool(basicConfig, "SimpleOutput",
+ "EnforceBitrate");
+ config_set_bool(basicConfig, "Stream1", "IgnoreRecommended",
+ !enforce);
+ config_set_bool(basicConfig, "Stream1", "MovedOldEnforce",
+ true);
+ changed = true;
+ }
+
/* ----------------------------------------------------- */
if (changed)
@@ -1275,6 +1291,9 @@ bool OBSBasic::InitBasicConfigDefaults()
config_set_default_string(basicConfig, "Output", "Mode", "Simple");
+ config_set_default_bool(basicConfig, "Stream1", "IgnoreRecommended",
+ false);
+
config_set_default_string(basicConfig, "SimpleOutput", "FilePath",
GetDefaultVideoSavePath().c_str());
config_set_default_string(basicConfig, "SimpleOutput", "RecFormat",
@@ -1283,8 +1302,6 @@ bool OBSBasic::InitBasicConfigDefaults()
config_set_default_uint(basicConfig, "SimpleOutput", "ABitrate", 160);
config_set_default_bool(basicConfig, "SimpleOutput", "UseAdvanced",
false);
- config_set_default_bool(basicConfig, "SimpleOutput", "EnforceBitrate",
- true);
config_set_default_string(basicConfig, "SimpleOutput", "Preset",
"veryfast");
config_set_default_string(basicConfig, "SimpleOutput", "NVENCPreset",
diff --git a/UI/window-basic-settings-stream.cpp b/UI/window-basic-settings-stream.cpp
index 7a3b84976..c21aefbfb 100644
--- a/UI/window-basic-settings-stream.cpp
+++ b/UI/window-basic-settings-stream.cpp
@@ -73,8 +73,12 @@ void OBSBasicSettings::InitStreamPage()
SLOT(UpdateKeyLink()));
connect(ui->service, SIGNAL(currentIndexChanged(int)), this,
SLOT(UpdateVodTrackSetting()));
+ connect(ui->service, SIGNAL(currentIndexChanged(int)), this,
+ SLOT(UpdateServiceRecommendations()));
connect(ui->customServer, SIGNAL(textChanged(const QString &)), this,
SLOT(UpdateKeyLink()));
+ connect(ui->ignoreRecommended, SIGNAL(clicked(bool)), this,
+ SLOT(DisplayEnforceWarning(bool)));
connect(ui->customServer, SIGNAL(editingFinished(const QString &)),
this, SLOT(UpdateKeyLink()));
connect(ui->service, SIGNAL(currentIndexChanged(int)), this,
@@ -83,6 +87,9 @@ void OBSBasicSettings::InitStreamPage()
void OBSBasicSettings::LoadStream1Settings()
{
+ bool ignoreRecommended =
+ config_get_bool(main->Config(), "Stream1", "IgnoreRecommended");
+
obs_service_t *service_obj = main->GetService();
const char *type = obs_service_get_type(service_obj);
@@ -144,10 +151,13 @@ void OBSBasicSettings::LoadStream1Settings()
UpdateKeyLink();
UpdateMoreInfoLink();
UpdateVodTrackSetting();
+ UpdateServiceRecommendations();
bool streamActive = obs_frontend_streaming_active();
ui->streamPage->setEnabled(!streamActive);
+ ui->ignoreRecommended->setChecked(ignoreRecommended);
+
loading = false;
}
@@ -216,6 +226,8 @@ void OBSBasicSettings::SaveStream1Settings()
main->auth = auth;
if (!!main->auth)
main->auth->LoadUI();
+
+ SaveCheckBox(ui->ignoreRecommended, "Stream1", "IgnoreRecommended");
}
void OBSBasicSettings::UpdateMoreInfoLink()
@@ -655,3 +667,60 @@ OBSService OBSBasicSettings::GetStream1Service()
{
return stream1Changed ? SpawnTempService() : main->GetService();
}
+
+void OBSBasicSettings::UpdateServiceRecommendations()
+{
+ bool customServer = IsCustomService();
+ ui->ignoreRecommended->setVisible(!customServer);
+ ui->enforceSettingsLabel->setVisible(!customServer);
+
+ OBSService service = GetStream1Service();
+
+ int vbitrate, abitrate;
+ obs_service_get_max_bitrate(service, &vbitrate, &abitrate);
+
+ QString text;
+
+#define ENFORCE_TEXT(x) QTStr("Basic.Settings.Stream.Recommended." x)
+ if (vbitrate)
+ text += ENFORCE_TEXT("MaxVideoBitrate")
+ .arg(QString::number(vbitrate));
+ if (abitrate) {
+ if (!text.isEmpty())
+ text += "\n";
+ text += ENFORCE_TEXT("MaxAudioBitrate")
+ .arg(QString::number(abitrate));
+ }
+#undef ENFORCE_TEXT
+
+ ui->enforceSettingsLabel->setText(text);
+}
+
+void OBSBasicSettings::DisplayEnforceWarning(bool checked)
+{
+ if (IsCustomService())
+ return;
+
+ if (!checked) {
+ SimpleRecordingEncoderChanged();
+ return;
+ }
+
+ QMessageBox::StandardButton button;
+
+#define ENFORCE_WARNING(x) \
+ QTStr("Basic.Settings.Stream.IgnoreRecommended.Warn." x)
+
+ button = OBSMessageBox::question(this, ENFORCE_WARNING("Title"),
+ ENFORCE_WARNING("Text"));
+#undef ENFORCE_WARNING
+
+ if (button == QMessageBox::No) {
+ QMetaObject::invokeMethod(ui->ignoreRecommended, "setChecked",
+ Qt::QueuedConnection,
+ Q_ARG(bool, false));
+ return;
+ }
+
+ SimpleRecordingEncoderChanged();
+}
diff --git a/UI/window-basic-settings.cpp b/UI/window-basic-settings.cpp
index 884e9bb1b..e5757958d 100644
--- a/UI/window-basic-settings.cpp
+++ b/UI/window-basic-settings.cpp
@@ -425,6 +425,7 @@ OBSBasicSettings::OBSBasicSettings(QWidget *parent)
HookWidget(ui->useAuth, CHECK_CHANGED, STREAM1_CHANGED);
HookWidget(ui->authUsername, EDIT_CHANGED, STREAM1_CHANGED);
HookWidget(ui->authPw, EDIT_CHANGED, STREAM1_CHANGED);
+ HookWidget(ui->ignoreRecommended, CHECK_CHANGED, STREAM1_CHANGED);
HookWidget(ui->outputMode, COMBO_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->simpleOutputPath, EDIT_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->simpleNoSpace, CHECK_CHANGED, OUTPUTS_CHANGED);
@@ -433,7 +434,6 @@ OBSBasicSettings::OBSBasicSettings(QWidget *parent)
HookWidget(ui->simpleOutStrEncoder, COMBO_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->simpleOutputABitrate, COMBO_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->simpleOutAdvanced, CHECK_CHANGED, OUTPUTS_CHANGED);
- HookWidget(ui->simpleOutEnforce, CHECK_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->simpleOutPreset, COMBO_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->simpleOutCustom, EDIT_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->simpleOutRecQuality, COMBO_CHANGED, OUTPUTS_CHANGED);
@@ -755,7 +755,7 @@ OBSBasicSettings::OBSBasicSettings(QWidget *parent)
this, SLOT(SimpleRecordingEncoderChanged()));
connect(ui->simpleOutAdvanced, SIGNAL(toggled(bool)), this,
SLOT(SimpleRecordingEncoderChanged()));
- connect(ui->simpleOutEnforce, SIGNAL(toggled(bool)), this,
+ connect(ui->ignoreRecommended, SIGNAL(toggled(bool)), this,
SLOT(SimpleRecordingEncoderChanged()));
connect(ui->simpleReplayBuf, SIGNAL(toggled(bool)), this,
SLOT(SimpleReplayBufferChanged()));
@@ -1612,8 +1612,6 @@ void OBSBasicSettings::LoadSimpleOutputSettings()
config_get_uint(main->Config(), "SimpleOutput", "ABitrate");
bool advanced =
config_get_bool(main->Config(), "SimpleOutput", "UseAdvanced");
- bool enforceBitrate = config_get_bool(main->Config(), "SimpleOutput",
- "EnforceBitrate");
const char *preset =
config_get_string(main->Config(), "SimpleOutput", "Preset");
const char *qsvPreset =
@@ -1662,7 +1660,6 @@ void OBSBasicSettings::LoadSimpleOutputSettings()
std::to_string(audioBitrate).c_str());
ui->simpleOutAdvanced->setChecked(advanced);
- ui->simpleOutEnforce->setChecked(enforceBitrate);
ui->simpleOutCustom->setText(custom);
idx = ui->simpleOutRecQuality->findData(QString(recQual));
@@ -3304,7 +3301,6 @@ void OBSBasicSettings::SaveOutputSettings()
SaveCheckBox(ui->simpleNoSpace, "SimpleOutput", "FileNameWithoutSpace");
SaveCombo(ui->simpleOutRecFormat, "SimpleOutput", "RecFormat");
SaveCheckBox(ui->simpleOutAdvanced, "SimpleOutput", "UseAdvanced");
- SaveCheckBox(ui->simpleOutEnforce, "SimpleOutput", "EnforceBitrate");
SaveComboData(ui->simpleOutPreset, "SimpleOutput", presetType);
SaveEdit(ui->simpleOutCustom, "SimpleOutput", "x264Settings");
SaveComboData(ui->simpleOutRecQuality, "SimpleOutput", "RecQuality");
@@ -4602,8 +4598,7 @@ void OBSBasicSettings::SimpleRecordingEncoderChanged()
{
QString qual = ui->simpleOutRecQuality->currentData().toString();
QString warning;
- bool advanced = ui->simpleOutAdvanced->isChecked();
- bool enforceBitrate = ui->simpleOutEnforce->isChecked() || !advanced;
+ bool enforceBitrate = !ui->ignoreRecommended->isChecked();
OBSService service = GetStream1Service();
delete simpleOutRecWarning;
diff --git a/UI/window-basic-settings.hpp b/UI/window-basic-settings.hpp
index 5095e3b2b..5bb36c70f 100644
--- a/UI/window-basic-settings.hpp
+++ b/UI/window-basic-settings.hpp
@@ -245,7 +245,9 @@ private slots:
void UpdateServerList();
void UpdateKeyLink();
void UpdateVodTrackSetting();
+ void UpdateServiceRecommendations();
void UpdateMoreInfoLink();
+ void DisplayEnforceWarning(bool checked);
void on_show_clicked();
void on_authPwShow_clicked();
void on_connectAccount_clicked();