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);