diff --git a/build/data/obs-studio/locale/en.txt b/build/data/obs-studio/locale/en.txt index cc3b892f7..fe1af33b0 100644 --- a/build/data/obs-studio/locale/en.txt +++ b/build/data/obs-studio/locale/en.txt @@ -34,6 +34,10 @@ Output.ConnectFail.InvalidStream="Could not access the specified channel or stre Output.ConnectFail.Error="An unexpected error occurred when trying to connect to the server. More information in the log file." Output.ConnectFail.Disconnected="Disconnected from server." +# output recording messages +Output.BadPath.Title="Bad File Path" +Output.BadPath.Text="The configured file output path is invalid. Please check your settings to confirm that a valid file path has been set." + # log upload dialog text and messages LogReturnDialog="Log Upload Successful" LogReturnDialog.CopyURL="Copy URL" @@ -106,7 +110,7 @@ Basic.Settings.Output="Output" Basic.Settings.Output.Mode="Output Mode" Basic.Settings.Output.Mode.Simple="Simple (Stream and/or record)" Basic.Settings.Output.Mode.Advanced="Advanced (Custom output type)" -Basic.Settings.Output.Simple.SavePath="Recording Path" +Basic.Settings.Output.Simple.SavePath="FLV Recording Path" Basic.Settings.Output.Simple.VideoBitrate="Video Bitrate" Basic.Settings.output.Simple.AudioBitrate="Audio Bitrate" diff --git a/obs/forms/OBSBasic.ui b/obs/forms/OBSBasic.ui index 163227f5a..1637c29a4 100644 --- a/obs/forms/OBSBasic.ui +++ b/obs/forms/OBSBasic.ui @@ -401,7 +401,7 @@ - false + true Basic.Main.StartRecording diff --git a/obs/forms/OBSBasicSettings.ui b/obs/forms/OBSBasicSettings.ui index 4ff253f15..4c4df69cd 100644 --- a/obs/forms/OBSBasicSettings.ui +++ b/obs/forms/OBSBasicSettings.ui @@ -383,14 +383,14 @@ - false + true - false + true Browse diff --git a/obs/window-basic-main.cpp b/obs/window-basic-main.cpp index 448a11d52..086d8db5b 100644 --- a/obs/window-basic-main.cpp +++ b/obs/window-basic-main.cpp @@ -54,14 +54,16 @@ Q_DECLARE_METATYPE(OBSSceneItem); Q_DECLARE_METATYPE(order_movement); OBSBasic::OBSBasic(QWidget *parent) - : OBSMainWindow (parent), + : OBSMainWindow (parent), properties (nullptr), + fileOutput (nullptr), streamOutput (nullptr), service (nullptr), aac (nullptr), x264 (nullptr), sceneChanging (false), resizeTimer (0), + activeRefs (0), ui (new Ui::OBSBasic) { ui->setupUi(this); @@ -243,6 +245,14 @@ static void OBSStopStreaming(void *data, calldata_t params) "StreamingStop", Q_ARG(int, code)); } +static void OBSStopRecording(void *data, calldata_t params) +{ + UNUSED_PARAMETER(params); + + QMetaObject::invokeMethod(static_cast(data), + "RecordingStop"); +} + #define SERVICE_PATH "obs-studio/basic/service.json" void OBSBasic::SaveService() @@ -297,6 +307,10 @@ bool OBSBasic::LoadService() bool OBSBasic::InitOutputs() { + fileOutput = obs_output_create("flv_output", "default", nullptr); + if (!fileOutput) + return false; + streamOutput = obs_output_create("rtmp_output", "default", nullptr); if (!streamOutput) return false; @@ -306,6 +320,9 @@ bool OBSBasic::InitOutputs() signal_handler_connect(obs_output_signalhandler(streamOutput), "stop", OBSStopStreaming, this); + signal_handler_connect(obs_output_signalhandler(fileOutput), + "stop", OBSStopRecording, this); + return true; } @@ -357,7 +374,8 @@ bool OBSBasic::InitBasicConfigDefaults() uint32_t cy = monitors[0].cy; /* TODO: temporary */ - config_set_default_string(basicConfig, "SimpleOutput", "path", ""); + config_set_default_string(basicConfig, "SimpleOutput", "FilePath", + GetDefaultVideoSavePath().c_str()); config_set_default_uint (basicConfig, "SimpleOutput", "VBitrate", 2500); config_set_default_uint (basicConfig, "SimpleOutput", "ABitrate", 128); @@ -1355,6 +1373,8 @@ void OBSBasic::StreamingStop(int code) errorMessage = Str("Output.ConnectFail.Disconnected"); } + activeRefs--; + ui->streamButton->setText(QTStr("Basic.Main.StartStreaming")); ui->streamButton->setEnabled(true); @@ -1364,12 +1384,15 @@ void OBSBasic::StreamingStop(int code) QT_UTF8(errorMessage)); } -void OBSBasic::on_streamButton_clicked() +void OBSBasic::RecordingStop() { - if (obs_output_active(streamOutput)) { - obs_output_stop(streamOutput); + activeRefs--; + ui->recordButton->setText(QTStr("Basic.Main.StartRecording")); +} - } else { +void OBSBasic::SetupEncoders() +{ + if (activeRefs == 0) { obs_data_t x264Settings = obs_data_create(); obs_data_t aacSettings = obs_data_create(); @@ -1378,11 +1401,6 @@ void OBSBasic::on_streamButton_clicked() int audioBitrate = config_get_uint(basicConfig, "SimpleOutput", "ABitrate"); - ui->streamButton->setEnabled(false); - ui->streamButton->setText(QTStr("Basic.Main.Connecting")); - - SaveService(); - obs_data_setint(x264Settings, "bitrate", videoBitrate); obs_data_setbool(x264Settings, "cbr", true); @@ -1396,10 +1414,79 @@ void OBSBasic::on_streamButton_clicked() obs_encoder_set_video(x264, obs_video()); obs_encoder_set_audio(aac, obs_audio()); + } +} + +void OBSBasic::on_streamButton_clicked() +{ + if (obs_output_active(streamOutput)) { + obs_output_stop(streamOutput); + } else { + + SaveService(); + SetupEncoders(); + obs_output_set_video_encoder(streamOutput, x264); obs_output_set_audio_encoder(streamOutput, aac); obs_output_set_service(streamOutput, service); - obs_output_start(streamOutput); + + if (obs_output_start(streamOutput)) { + activeRefs++; + + ui->streamButton->setEnabled(false); + ui->streamButton->setText( + QTStr("Basic.Main.Connecting")); + } + } +} + +void OBSBasic::on_recordButton_clicked() +{ + if (obs_output_active(fileOutput)) { + obs_output_stop(fileOutput); + } else { + + const char *path = config_get_string(basicConfig, + "SimpleOutput", "FilePath"); + + os_dir_t dir = path ? os_opendir(path) : nullptr; + + if (!dir) { + QMessageBox::information(this, + QTStr("Output.BadPath.Title"), + QTStr("Output.BadPath.Text")); + return; + } + + os_closedir(dir); + + string strPath; + strPath += path; + + char lastChar = strPath.back(); + if (lastChar != '/' && lastChar != '\\') + strPath += "/"; + + strPath += GenerateTimeDateFilename("flv"); + + SetupEncoders(); + + obs_output_set_video_encoder(fileOutput, x264); + obs_output_set_audio_encoder(fileOutput, aac); + + obs_data_t settings = obs_data_create(); + obs_data_setstring(settings, "path", strPath.c_str()); + + obs_output_update(fileOutput, settings); + + obs_data_release(settings); + + if (obs_output_start(fileOutput)) { + activeRefs++; + + ui->recordButton->setText( + QTStr("Basic.Main.StopRecording")); + } } } diff --git a/obs/window-basic-main.hpp b/obs/window-basic-main.hpp index de1122731..91c29445a 100644 --- a/obs/window-basic-main.hpp +++ b/obs/window-basic-main.hpp @@ -58,6 +58,7 @@ private: QNetworkReply *logUploadReply; QByteArray logUploadReturnData; + obs_output_t fileOutput; obs_output_t streamOutput; obs_service_t service; obs_encoder_t aac; @@ -71,6 +72,10 @@ private: ConfigFile basicConfig; + int activeRefs; + + void SetupEncoders(); + void CreateDefaultScene(); void ClearVolumeControls(); @@ -112,6 +117,8 @@ public slots: void StreamingStart(); void StreamingStop(int errorcode); + void RecordingStop(); + private slots: void AddSceneItem(OBSSceneItem item); void RemoveSceneItem(OBSSceneItem item); @@ -190,6 +197,7 @@ private slots: void on_actionUploadCurrentLog_triggered(); void on_actionUploadLastLog_triggered(); void on_streamButton_clicked(); + void on_recordButton_clicked(); void on_settingsButton_clicked(); void logUploadRead(); diff --git a/obs/window-basic-settings.cpp b/obs/window-basic-settings.cpp index 4e8bbd4a2..25174b58e 100644 --- a/obs/window-basic-settings.cpp +++ b/obs/window-basic-settings.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include "obs-app.hpp" #include "platform.hpp" @@ -372,7 +373,7 @@ void OBSBasicSettings::LoadVideoSettings() void OBSBasicSettings::LoadSimpleOutputSettings() { const char *path = config_get_string(main->Config(), "SimpleOutput", - "path"); + "FilePath"); int videoBitrate = config_get_uint(main->Config(), "SimpleOutput", "VBitrate"); int audioBitrate = config_get_uint(main->Config(), "SimpleOutput", @@ -557,7 +558,7 @@ void OBSBasicSettings::SaveOutputSettings() videoBitrate); config_set_string(main->Config(), "SimpleOutput", "ABitrate", QT_TO_UTF8(audioBitrate)); - config_set_string(main->Config(), "SimpleOutput", "path", + config_set_string(main->Config(), "SimpleOutput", "FilePath", QT_TO_UTF8(path)); } @@ -693,6 +694,19 @@ void OBSBasicSettings::on_streamType_currentIndexChanged(int idx) LoadServiceInfo(); } +void OBSBasicSettings::on_simpleOutputBrowse_clicked() +{ + QString dir = QFileDialog::getExistingDirectory(this, + QTStr("OpenDirectory"), + ui->simpleOutputPath->text(), + QFileDialog::ShowDirsOnly | + QFileDialog::DontResolveSymlinks); + if (dir.isEmpty()) + return; + + ui->simpleOutputPath->setText(dir); +} + static inline bool StreamExists(const char *name) { return obs_get_service_by_name(name) != nullptr; diff --git a/obs/window-basic-settings.hpp b/obs/window-basic-settings.hpp index 937e1dd72..f4c351fbf 100644 --- a/obs/window-basic-settings.hpp +++ b/obs/window-basic-settings.hpp @@ -108,6 +108,7 @@ private slots: void on_buttonBox_clicked(QAbstractButton *button); void on_streamType_currentIndexChanged(int idx); + void on_simpleOutputBrowse_clicked(); void on_baseResolution_editTextChanged(const QString &text);