diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini
index e22375bb9..d3dd27224 100644
--- a/UI/data/locale/en-US.ini
+++ b/UI/data/locale/en-US.ini
@@ -760,6 +760,8 @@ Basic.Settings.Advanced.Network.BindToIP="Bind to IP"
Basic.Settings.Advanced.Network.EnableNewSocketLoop="Enable new networking code"
Basic.Settings.Advanced.Network.EnableLowLatencyMode="Low latency mode"
Basic.Settings.Advanced.Hotkeys.DisableHotkeysInFocus="Disable hotkeys when main window is in focus"
+Basic.Settings.Advanced.AutoRemux="Automatically remux to mp4"
+Basic.Settings.Advanced.AutoRemux.MP4="(record as mkv)"
# advanced audio properties
Basic.AdvAudio="Advanced Audio Properties"
diff --git a/UI/forms/OBSBasicSettings.ui b/UI/forms/OBSBasicSettings.ui
index 2ed99db0f..9aaf6249b 100644
--- a/UI/forms/OBSBasicSettings.ui
+++ b/UI/forms/OBSBasicSettings.ui
@@ -145,8 +145,8 @@
0
0
- 801
- 836
+ 804
+ 1072
@@ -797,8 +797,8 @@
0
0
- 818
- 697
+ 813
+ 770
@@ -1389,7 +1389,7 @@
-
- 0
+ 1
true
@@ -1680,6 +1680,270 @@
0
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ QFormLayout::AllNonFixedFieldsGrow
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 170
+ 0
+
+
+
+ Basic.Settings.Output.Simple.SavePath
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ advOutRecPath
+
+
+
+ -
+
+
-
+
+
+ true
+
+
+
+ -
+
+
+ true
+
+
+ Browse
+
+
+
+
+
+ -
+
+
+ Basic.Settings.Output.NoSpaceFileName
+
+
+ true
+
+
+
+ -
+
+
+ Basic.Settings.Output.Format
+
+
+ advOutRecFormat
+
+
+
+ -
+
+
-
+
+ flv
+
+
+ -
+
+ mp4
+
+
+ -
+
+ mov
+
+
+ -
+
+ mkv
+
+
+ -
+
+ ts
+
+
+ -
+
+ m3u8
+
+
+
+
+ -
+
+
+ Basic.Settings.Output.Adv.AudioTrack
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ 1
+
+
+
+ -
+
+
+ 2
+
+
+
+ -
+
+
+ 3
+
+
+
+ -
+
+
+ 4
+
+
+
+ -
+
+
+ 5
+
+
+
+ -
+
+
+ 6
+
+
+
+
+
+
+ -
+
+
+ Basic.Settings.Output.Encoder
+
+
+ advOutRecEncoder
+
+
+
+ -
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Qt::RightToLeft
+
+
+ Basic.Settings.Output.Adv.Rescale
+
+
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ false
+
+
+ true
+
+
+
+
+
+
+ -
+
+
+ Basic.Settings.Output.CustomMuxerSettings
+
+
+ advOutMuxCustom
+
+
+
+ -
+
+
+
+
+
-
@@ -1695,270 +1959,6 @@
0
-
-
-
-
-
- 0
- 0
-
-
-
-
- QFormLayout::AllNonFixedFieldsGrow
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
- 0
-
-
-
-
-
-
- 0
- 0
-
-
-
-
- 170
- 0
-
-
-
- Basic.Settings.Output.Simple.SavePath
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
- advOutRecPath
-
-
-
- -
-
-
-
-
-
- true
-
-
-
- -
-
-
- true
-
-
- Browse
-
-
-
-
-
- -
-
-
- Basic.Settings.Output.NoSpaceFileName
-
-
- true
-
-
-
- -
-
-
- Basic.Settings.Output.Format
-
-
- advOutRecFormat
-
-
-
- -
-
-
-
-
- flv
-
-
- -
-
- mp4
-
-
- -
-
- mov
-
-
- -
-
- mkv
-
-
- -
-
- ts
-
-
- -
-
- m3u8
-
-
-
-
- -
-
-
- Basic.Settings.Output.Adv.AudioTrack
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
- 1
-
-
-
- -
-
-
- 2
-
-
-
- -
-
-
- 3
-
-
-
- -
-
-
- 4
-
-
-
- -
-
-
- 5
-
-
-
- -
-
-
- 6
-
-
-
-
-
-
- -
-
-
- Basic.Settings.Output.Encoder
-
-
- advOutRecEncoder
-
-
-
- -
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Qt::RightToLeft
-
-
- Basic.Settings.Output.Adv.Rescale
-
-
-
- -
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
- false
-
-
- true
-
-
-
-
-
-
- -
-
-
- Basic.Settings.Output.CustomMuxerSettings
-
-
- advOutMuxCustom
-
-
-
- -
-
-
-
-
-
@@ -3498,8 +3498,8 @@
0
0
- 800
- 69
+ 98
+ 28
@@ -4265,7 +4265,7 @@
- -
+
-
0
@@ -4297,7 +4297,7 @@
- -
+
-
Basic.Settings.Output.ReplayBuffer.Prefix
@@ -4320,6 +4320,26 @@
+ -
+
+
+ Basic.Settings.Advanced.AutoRemux
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
diff --git a/UI/obs-app.cpp b/UI/obs-app.cpp
index 52c731984..a03c2e4bb 100644
--- a/UI/obs-app.cpp
+++ b/UI/obs-app.cpp
@@ -77,6 +77,9 @@ string opt_starting_collection;
string opt_starting_profile;
string opt_starting_scene;
+bool remuxAfterRecord = false;
+string remuxFilename;
+
// GPU hint exports for AMD/NVIDIA laptops
#ifdef _MSC_VER
extern "C" __declspec(dllexport) DWORD NvOptimusEnablement = 1;
@@ -1493,8 +1496,18 @@ string GenerateTimeDateFilename(const char *extension, bool noSpace)
string GenerateSpecifiedFilename(const char *extension, bool noSpace,
const char *format)
{
+ OBSBasic *main = reinterpret_cast(App()->GetMainWindow());
+ bool autoRemux = config_get_bool(main->Config(), "Video", "AutoRemux");
+
+ if ((strcmp(extension, "mp4") == 0) && autoRemux)
+ extension = "mkv";
+
BPtr filename = os_generate_formatted_filename(extension,
!noSpace, format);
+
+ remuxFilename = string(filename);
+ remuxAfterRecord = autoRemux;
+
return string(filename);
}
diff --git a/UI/obs-app.hpp b/UI/obs-app.hpp
index 9fd7448a4..27b6cc3e7 100644
--- a/UI/obs-app.hpp
+++ b/UI/obs-app.hpp
@@ -197,6 +197,10 @@ static inline int GetProfilePath(char *path, size_t size, const char *file)
}
extern bool portable_mode;
+
+extern bool remuxAfterRecord;
+extern std::string remuxFilename;
+
extern bool opt_start_streaming;
extern bool opt_start_recording;
extern bool opt_start_replaybuffer;
diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp
index 7942af880..ab1520094 100644
--- a/UI/window-basic-main.cpp
+++ b/UI/window-basic-main.cpp
@@ -5018,6 +5018,23 @@ void OBSBasic::StreamingStop(int code, QString last_error)
}
}
+void OBSBasic::AutoRemux()
+{
+ const char *mode = config_get_string(basicConfig, "Output", "Mode");
+ const char *path = strcmp(mode, "Advanced") ?
+ config_get_string(basicConfig, "SimpleOutput", "FilePath") :
+ config_get_string(basicConfig, "AdvOut", "RecFilePath");
+ std::string s(path);
+ s += "/";
+ s += remuxFilename;
+ const QString &str = QString::fromStdString(s);
+ QString file = str.section(".", 0, 0);
+
+ OBSRemux *remux = new OBSRemux(path, this, true);
+ remux->show();
+ remux->AutoRemux(str, file + ".mp4");
+}
+
void OBSBasic::StartRecording()
{
if (outputHandler->RecordingActive())
@@ -5116,6 +5133,9 @@ void OBSBasic::RecordingStop(int code)
if (api)
api->on_event(OBS_FRONTEND_EVENT_RECORDING_STOPPED);
+ if (remuxAfterRecord)
+ AutoRemux();
+
OnDeactivate();
}
diff --git a/UI/window-basic-main.hpp b/UI/window-basic-main.hpp
index 58ca98cc5..27377622a 100644
--- a/UI/window-basic-main.hpp
+++ b/UI/window-basic-main.hpp
@@ -507,6 +507,8 @@ private:
static void HotkeyTriggered(void *data, obs_hotkey_id id, bool pressed);
+ void AutoRemux();
+
public:
OBSSource GetProgramSource();
OBSScene GetCurrentScene();
diff --git a/UI/window-basic-settings.cpp b/UI/window-basic-settings.cpp
index c6390adaf..8d7441730 100644
--- a/UI/window-basic-settings.cpp
+++ b/UI/window-basic-settings.cpp
@@ -448,6 +448,7 @@ OBSBasicSettings::OBSBasicSettings(QWidget *parent)
HookWidget(ui->enableNewSocketLoop, CHECK_CHANGED, ADV_CHANGED);
HookWidget(ui->enableLowLatencyMode, CHECK_CHANGED, ADV_CHANGED);
HookWidget(ui->disableFocusHotkeys, CHECK_CHANGED, ADV_CHANGED);
+ HookWidget(ui->autoRemux, CHECK_CHANGED, ADV_CHANGED);
#if !defined(_WIN32) && !defined(__APPLE__)
delete ui->enableAutoUpdates;
@@ -2236,6 +2237,8 @@ void OBSBasicSettings::LoadAdvancedSettings()
"RecRBTime");
int rbSize = config_get_int(main->Config(), "AdvOut",
"RecRBSize");
+ bool autoRemux = config_get_bool(main->Config(), "Video",
+ "AutoRemux");
loading = true;
@@ -2262,6 +2265,7 @@ void OBSBasicSettings::LoadAdvancedSettings()
ui->streamDelaySec->setValue(delaySec);
ui->streamDelayPreserve->setChecked(preserveDelay);
ui->streamDelayEnable->setChecked(enableDelay);
+ ui->autoRemux->setChecked(autoRemux);
SetComboByName(ui->colorFormat, videoColorFormat);
@@ -2935,6 +2939,7 @@ void OBSBasicSettings::SaveAdvancedSettings()
SaveSpinBox(ui->reconnectRetryDelay, "Output", "RetryDelay");
SaveSpinBox(ui->reconnectMaxRetries, "Output", "MaxRetries");
SaveComboData(ui->bindToIP, "Output", "BindIP");
+ SaveCheckBox(ui->autoRemux, "Video", "AutoRemux");
#if defined(_WIN32) || defined(__APPLE__) || HAVE_PULSEAUDIO
QString newDevice = ui->monitoringDevice->currentData().toString();
@@ -3914,6 +3919,13 @@ void OBSBasicSettings::AdvOutRecCheckWarnings()
if (!warningMsg.isEmpty())
warningMsg += "\n\n";
warningMsg += QTStr("OutputWarnings.MP4Recording");
+ ui->autoRemux->setText(
+ QTStr("Basic.Settings.Advanced.AutoRemux")
+ + " " +
+ QTStr("Basic.Settings.Advanced.AutoRemux.MP4"));
+ } else {
+ ui->autoRemux->setText(
+ QTStr("Basic.Settings.Advanced.AutoRemux"));
}
delete advOutRecWarning;
@@ -4370,6 +4382,13 @@ void OBSBasicSettings::SimpleRecordingEncoderChanged()
if (!warning.isEmpty())
warning += "\n\n";
warning += QTStr("OutputWarnings.MP4Recording");
+ ui->autoRemux->setText(
+ QTStr("Basic.Settings.Advanced.AutoRemux")
+ + " " +
+ QTStr("Basic.Settings.Advanced.AutoRemux.MP4"));
+ } else {
+ ui->autoRemux->setText(
+ QTStr("Basic.Settings.Advanced.AutoRemux"));
}
if (warning.isEmpty())
diff --git a/UI/window-remux.cpp b/UI/window-remux.cpp
index b3e35f936..4e900f6bb 100644
--- a/UI/window-remux.cpp
+++ b/UI/window-remux.cpp
@@ -31,6 +31,7 @@
#include
#include
#include
+#include
#include "qt-wrappers.hpp"
@@ -632,12 +633,13 @@ void RemuxQueueModel::finishEntry(bool success)
The actual remux window implementation
**********************************************************/
-OBSRemux::OBSRemux(const char *path, QWidget *parent)
+OBSRemux::OBSRemux(const char *path, QWidget *parent, bool autoRemux_)
: QDialog (parent),
queueModel(new RemuxQueueModel),
worker (new RemuxWorker()),
ui (new Ui::OBSRemux),
- recPath (path)
+ recPath (path),
+ autoRemux (autoRemux_)
{
setAcceptDrops(true);
@@ -651,6 +653,13 @@ OBSRemux::OBSRemux(const char *path, QWidget *parent)
ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)->
setEnabled(false);
+ if (autoRemux) {
+ resize(280, 40);
+ ui->tableView->hide();
+ ui->buttonBox->hide();
+ ui->label->hide();
+ }
+
ui->progressBar->setMinimum(0);
ui->progressBar->setMaximum(1000);
ui->progressBar->setValue(0);
@@ -862,7 +871,14 @@ void OBSRemux::beginRemux()
setAcceptDrops(false);
remuxNextEntry();
+}
+void OBSRemux::AutoRemux(QString inFile, QString outFile)
+{
+ if (inFile != "" && outFile != "" && autoRemux) {
+ emit remux(inFile, outFile);
+ autoRemuxFile = inFile;
+ }
}
void OBSRemux::remuxNextEntry()
@@ -875,12 +891,15 @@ void OBSRemux::remuxNextEntry()
} else {
queueModel->endProcessing();
- OBSMessageBox::information(this, QTStr("Remux.FinishedTitle"),
- queueModel->checkForErrors()
- ? QTStr("Remux.FinishedError")
- : QTStr("Remux.Finished"));
+ if (!autoRemux) {
+ OBSMessageBox::information(this,
+ QTStr("Remux.FinishedTitle"),
+ queueModel->checkForErrors()
+ ? QTStr("Remux.FinishedError")
+ : QTStr("Remux.Finished"));
+ }
- ui->progressBar->setVisible(false);
+ ui->progressBar->setVisible(autoRemux);
ui->buttonBox->button(QDialogButtonBox::Ok)->
setText(QTStr("Remux.Remux"));
ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)->
@@ -914,7 +933,16 @@ void OBSRemux::updateProgress(float percent)
void OBSRemux::remuxFinished(bool success)
{
+ ui->buttonBox->button(QDialogButtonBox::Ok)->
+ setEnabled(true);
+
queueModel->finishEntry(success);
+
+ if (autoRemux && autoRemuxFile != "") {
+ QFile::remove(autoRemuxFile);
+ QTimer::singleShot(3000, this, SLOT(close()));
+ }
+
remuxNextEntry();
}
diff --git a/UI/window-remux.hpp b/UI/window-remux.hpp
index 69ec6451a..e37976917 100644
--- a/UI/window-remux.hpp
+++ b/UI/window-remux.hpp
@@ -56,12 +56,18 @@ class OBSRemux : public QDialog {
virtual void closeEvent(QCloseEvent *event) override;
virtual void reject() override;
+ bool autoRemux;
+ QString autoRemuxFile;
+
public:
- explicit OBSRemux(const char *recPath, QWidget *parent = nullptr);
+ explicit OBSRemux(const char *recPath, QWidget *parent = nullptr,
+ bool autoRemux = false);
virtual ~OBSRemux() override;
using job_t = std::shared_ptr;
+ void AutoRemux(QString inFile, QString outFile);
+
protected:
void dropEvent(QDropEvent *ev);
void dragEnterEvent(QDragEnterEvent *ev);