Skip to content

Commit

Permalink
UI: Use fragmented MOV/MP4 recording by default
Browse files Browse the repository at this point in the history
Implements RFC obsproject#51
  • Loading branch information
derrod committed Oct 23, 2022
1 parent 42ecdef commit cfb9bc1
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 27 deletions.
2 changes: 2 additions & 0 deletions UI/data/locale/en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -912,6 +912,8 @@ Basic.Settings.Stream.Recommended.MaxFPS="Maximum FPS: %1"
# basic mode 'output' settings
Basic.Settings.Output="Output"
Basic.Settings.Output.Format="Recording Format"
Basic.Settings.Output.FragmentMP4="Fragment MP4/MOV files"
Basic.Settings.Output.FragmentMP4.TT="Fragmented MP4/MOV writes the recording in chunks and does not require the same finalisation as traditional MP4/MOV files.\nThis ensures the file remains playable even if writing to disk is interrupted e.g. as a result of a BSOD or power loss.\n\nThis may not be compatible with all players and editors. Use File → Remux Recordings to convert the file into a more compatible format if necessary."
Basic.Settings.Output.Encoder="Encoder"
Basic.Settings.Output.SelectDirectory="Select Recording Directory"
Basic.Settings.Output.SelectFile="Select Recording File"
Expand Down
60 changes: 41 additions & 19 deletions UI/forms/OBSBasicSettings.ui
Original file line number Diff line number Diff line change
Expand Up @@ -1872,7 +1872,17 @@
</item>
</widget>
</item>
<item row="4" column="0">
<item row="4" column="1">
<widget class="QCheckBox" name="simpleOutFragment">
<property name="toolTip">
<string>Basic.Settings.Output.FragmentMP4.TT</string>
</property>
<property name="text">
<string>Basic.Settings.Output.FragmentMP4</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="simpleOutRecEncoderLabel">
<property name="text">
<string>Basic.Settings.Output.Encoder</string>
Expand All @@ -1882,10 +1892,10 @@
</property>
</widget>
</item>
<item row="4" column="1">
<item row="5" column="1">
<widget class="QComboBox" name="simpleOutRecEncoder"/>
</item>
<item row="5" column="0">
<item row="6" column="0">
<widget class="QLabel" name="label_420">
<property name="text">
<string>Basic.Settings.Output.CustomMuxerSettings</string>
Expand All @@ -1895,10 +1905,10 @@
</property>
</widget>
</item>
<item row="5" column="1">
<item row="6" column="1">
<widget class="QLineEdit" name="simpleOutMuxCustom"/>
</item>
<item row="6" column="1">
<item row="7" column="1">
<widget class="QCheckBox" name="simpleReplayBuf">
<property name="text">
<string>Basic.Settings.Output.UseReplayBuffer</string>
Expand Down Expand Up @@ -2642,14 +2652,24 @@
</item>
</widget>
</item>
<item row="3" column="0">
<item row="3" column="1">
<widget class="QCheckBox" name="advOutFragment">
<property name="toolTip">
<string>Basic.Settings.Output.FragmentMP4.TT</string>
</property>
<property name="text">
<string>Basic.Settings.Output.FragmentMP4</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_29">
<property name="text">
<string>Basic.Settings.Output.Adv.AudioTrack</string>
</property>
</widget>
</item>
<item row="3" column="1">
<item row="4" column="1">
<widget class="QStackedWidget" name="advRecTrackWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
Expand Down Expand Up @@ -2850,14 +2870,14 @@
</widget>
</widget>
</item>
<item row="4" column="0">
<item row="5" column="0">
<widget class="QLabel" name="advOutRecEncLabel">
<property name="text">
<string>Basic.Settings.Output.Encoder</string>
</property>
</widget>
</item>
<item row="4" column="1">
<item row="5" column="1">
<widget class="QComboBox" name="advOutRecEncoder">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
Expand All @@ -2867,7 +2887,7 @@
</property>
</widget>
</item>
<item row="5" column="0">
<item row="6" column="0">
<widget class="QCheckBox" name="advOutRecUseRescale">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
Expand All @@ -2883,7 +2903,7 @@
</property>
</widget>
</item>
<item row="5" column="1">
<item row="6" column="1">
<widget class="QFrame" name="advOutRecRescaleContainer">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="leftMargin">
Expand Down Expand Up @@ -2917,14 +2937,14 @@
</layout>
</widget>
</item>
<item row="6" column="0">
<item row="7" column="0">
<widget class="QLabel" name="label_9001">
<property name="text">
<string>Basic.Settings.Output.CustomMuxerSettings</string>
</property>
</widget>
</item>
<item row="6" column="1">
<item row="7" column="1">
<widget class="QLineEdit" name="advOutMuxCustom">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
Expand All @@ -2934,7 +2954,7 @@
</property>
</widget>
</item>
<item row="7" column="0">
<item row="8" column="0">
<widget class="QCheckBox" name="advOutSplitFile">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
Expand All @@ -2950,7 +2970,7 @@
</property>
</widget>
</item>
<item row="7" column="1">
<item row="8" column="1">
<widget class="QComboBox" name="advOutSplitFileType">
<property name="enabled">
<bool>false</bool>
Expand All @@ -2972,14 +2992,14 @@
</item>
</widget>
</item>
<item row="8" column="0">
<item row="9" column="0">
<widget class="QLabel" name="advOutSplitFileTimeLabel">
<property name="text">
<string>Basic.Settings.Output.SplitFile.Time</string>
</property>
</widget>
</item>
<item row="8" column="1">
<item row="9" column="1">
<widget class="QSpinBox" name="advOutSplitFileTime">
<property name="suffix">
<string> min</string>
Expand All @@ -2995,14 +3015,14 @@
</property>
</widget>
</item>
<item row="9" column="0">
<item row="10" column="0">
<widget class="QLabel" name="advOutSplitFileSizeLabel">
<property name="text">
<string>Basic.Settings.Output.SplitFile.Size</string>
</property>
</widget>
</item>
<item row="9" column="1">
<item row="10" column="1">
<widget class="QSpinBox" name="advOutSplitFileSize">
<property name="suffix">
<string> MB</string>
Expand Down Expand Up @@ -7536,6 +7556,7 @@
<tabstop>simpleNoSpace</tabstop>
<tabstop>simpleOutRecQuality</tabstop>
<tabstop>simpleOutRecFormat</tabstop>
<tabstop>simpleOutFragment</tabstop>
<tabstop>simpleOutRecEncoder</tabstop>
<tabstop>simpleOutMuxCustom</tabstop>
<tabstop>simpleReplayBuf</tabstop>
Expand All @@ -7556,6 +7577,7 @@
<tabstop>advOutRecPathBrowse</tabstop>
<tabstop>advOutNoSpace</tabstop>
<tabstop>advOutRecFormat</tabstop>
<tabstop>advOutFragment</tabstop>
<tabstop>advOutRecTrack1</tabstop>
<tabstop>advOutRecTrack2</tabstop>
<tabstop>advOutRecTrack3</tabstop>
Expand Down
48 changes: 46 additions & 2 deletions UI/window-basic-main-outputs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1011,6 +1011,8 @@ bool SimpleOutput::ConfigureRecording(bool updateReplayBuffer)
config_get_string(main->Config(), "SimpleOutput", "FilePath");
const char *format =
config_get_string(main->Config(), "SimpleOutput", "RecFormat");
bool fragment = config_get_string(main->Config(), "SimpleOutput",
"RecFragment");
const char *mux = config_get_string(main->Config(), "SimpleOutput",
"MuxerCustom");
bool noSpace = config_get_bool(main->Config(), "SimpleOutput",
Expand All @@ -1028,6 +1030,9 @@ bool SimpleOutput::ConfigureRecording(bool updateReplayBuffer)
int rbSize =
config_get_int(main->Config(), "SimpleOutput", "RecRBSize");

bool is_fragmentable = strcmp(format, "mp4") == 0 ||
strcmp(format, "mov") == 0;

string f;
string strPath;

Expand All @@ -1054,7 +1059,24 @@ bool SimpleOutput::ConfigureRecording(bool updateReplayBuffer)
strPath.c_str());
}

obs_data_set_string(settings, "muxer_settings", mux);
// Use fragmented MOV/MP4 if user has not already specified custom movflags
if (is_fragmentable && fragment &&
(!mux || strstr(mux, "movflags") == NULL)) {
string mux_fmp4 =
"movflags=frag_keyframe+empty_moov+delay_moov";
if (mux) {
mux_fmp4 += " ";
mux_fmp4 += mux;
}
obs_data_set_string(settings, "muxer_settings",
mux_fmp4.c_str());
} else {
if (is_fragmentable && fragment)
blog(LOG_WARNING,
"User enabled fragmented recording, "
"but custom muxer settings contained movflags.");
obs_data_set_string(settings, "muxer_settings", mux);
}

if (updateReplayBuffer)
obs_output_update(replayBuffer, settings);
Expand Down Expand Up @@ -1471,7 +1493,11 @@ inline void AdvancedOutput::SetupRecording()

const char *recFormat =
config_get_string(main->Config(), "AdvOut", "RecFormat");
bool fragment =
config_get_string(main->Config(), "AdvOut", "RecFragment");

bool is_fragmentable = strcmp(recFormat, "mp4") == 0 ||
strcmp(recFormat, "mov") == 0;
bool flv = strcmp(recFormat, "flv") == 0;

if (flv)
Expand Down Expand Up @@ -1528,8 +1554,26 @@ inline void AdvancedOutput::SetupRecording()
aacTrack[tracks - 1], idx);
}

// Use fragmented MOV/MP4 if user has not already specified custom movflags
if (is_fragmentable && fragment &&
(!mux || strstr(mux, "movflags") == NULL)) {
string mux_fmp4 =
"movflags=frag_keyframe+empty_moov+delay_moov";
if (mux) {
mux_fmp4 += " ";
mux_fmp4 += mux;
}
obs_data_set_string(settings, "muxer_settings",
mux_fmp4.c_str());
} else {
if (is_fragmentable && fragment)
blog(LOG_WARNING,
"User enabled fragmented recording, "
"but custom muxer settings contained movflags.");
obs_data_set_string(settings, "muxer_settings", mux);
}

obs_data_set_string(settings, "path", path);
obs_data_set_string(settings, "muxer_settings", mux);
obs_output_update(fileOutput, settings);
if (replayBuffer)
obs_output_update(replayBuffer, settings);
Expand Down
3 changes: 3 additions & 0 deletions UI/window-basic-main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1392,6 +1392,8 @@ bool OBSBasic::InitBasicConfigDefaults()
GetDefaultVideoSavePath().c_str());
config_set_default_string(basicConfig, "SimpleOutput", "RecFormat",
"mkv");
config_set_default_bool(basicConfig, "SimpleOutput", "RecFragment",
true);
config_set_default_uint(basicConfig, "SimpleOutput", "VBitrate", 2500);
config_set_default_uint(basicConfig, "SimpleOutput", "ABitrate", 160);
config_set_default_bool(basicConfig, "SimpleOutput", "UseAdvanced",
Expand Down Expand Up @@ -1420,6 +1422,7 @@ bool OBSBasic::InitBasicConfigDefaults()
config_set_default_string(basicConfig, "AdvOut", "RecFilePath",
GetDefaultVideoSavePath().c_str());
config_set_default_string(basicConfig, "AdvOut", "RecFormat", "mkv");
config_set_default_bool(basicConfig, "AdvOut", "RecFragment", true);
config_set_default_bool(basicConfig, "AdvOut", "RecUseRescale", false);
config_set_default_uint(basicConfig, "AdvOut", "RecTracks", (1 << 0));
config_set_default_string(basicConfig, "AdvOut", "RecEncoder", "none");
Expand Down
Loading

0 comments on commit cfb9bc1

Please sign in to comment.