Browse Source

UI: Allow generated filenames for FFmpeg output

This changes the way the advanced output section's FFmpeg output
settings work by allowing the user to select whether they want to output
to a file or output to a URL, and makes it so file names are
automatically generated like other recording outputs.

If they choose to output to a file, it'll only require an output
directory similarly to how other recording outputs work.  They can
select a directory to output to rather than being required to type in a
full path and filename; the filename is automatically generated.  The
extension is also automatically retrieved from libff depending on the
format selected.

Otherwise if they have Output to URL selected, it'll show a simple edit
box where they can type in the target URL.
jp9000 10 years ago
parent
commit
75dcd1ffa3

+ 3 - 0
obs/data/locale/en-US.ini

@@ -326,6 +326,9 @@ Basic.Settings.Output.Adv.Recording.Type="Type"
 Basic.Settings.Output.Adv.Recording.Type.Standard="Standard"
 Basic.Settings.Output.Adv.Recording.Type.FFmpegOutput="Custom Output (FFmpeg)"
 Basic.Settings.Output.Adv.Recording.UseStreamEncoder="(Use stream encoder)"
+Basic.Settings.Output.Adv.FFmpeg.Type="FFmpeg Output Type"
+Basic.Settings.Output.Adv.FFmpeg.Type.URL="Output to URL"
+Basic.Settings.Output.Adv.FFmpeg.Type.RecordToFile="Output to File"
 Basic.Settings.Output.Adv.FFmpeg.SaveFilter.Common="Common recording formats"
 Basic.Settings.Output.Adv.FFmpeg.SaveFilter.All="All Files"
 Basic.Settings.Output.Adv.FFmpeg.SavePathURL="File path or URL"

+ 231 - 134
obs/forms/OBSBasicSettings.ui

@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>895</width>
-    <height>602</height>
+    <height>614</height>
    </rect>
   </property>
   <property name="sizePolicy">
@@ -1293,7 +1293,7 @@
                      <property name="topMargin">
                       <number>0</number>
                      </property>
-                     <item row="0" column="0">
+                     <item row="1" column="0">
                       <widget class="QLabel" name="label_36">
                        <property name="sizePolicy">
                         <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
@@ -1315,42 +1315,104 @@
                        </property>
                       </widget>
                      </item>
-                     <item row="0" column="1">
-                      <layout class="QHBoxLayout" name="horizontalLayout_8">
-                       <item>
-                        <widget class="QLineEdit" name="advOutFFURL">
-                         <property name="enabled">
-                          <bool>true</bool>
+                     <item row="1" column="1">
+                      <widget class="QStackedWidget" name="stackedWidget_2">
+                       <property name="currentIndex">
+                        <number>0</number>
+                       </property>
+                       <widget class="QWidget" name="page_5">
+                        <layout class="QHBoxLayout" name="horizontalLayout_12">
+                         <property name="spacing">
+                          <number>3</number>
                          </property>
-                        </widget>
-                       </item>
-                       <item>
-                        <widget class="QPushButton" name="advOutFFPathBrowse">
-                         <property name="enabled">
-                          <bool>true</bool>
+                         <property name="leftMargin">
+                          <number>0</number>
                          </property>
-                         <property name="text">
-                          <string>Browse</string>
+                         <property name="topMargin">
+                          <number>0</number>
                          </property>
-                        </widget>
-                       </item>
-                      </layout>
+                         <property name="rightMargin">
+                          <number>0</number>
+                         </property>
+                         <property name="bottomMargin">
+                          <number>0</number>
+                         </property>
+                         <item>
+                          <widget class="QLineEdit" name="advOutFFRecPath">
+                           <property name="readOnly">
+                            <bool>true</bool>
+                           </property>
+                          </widget>
+                         </item>
+                         <item>
+                          <widget class="QPushButton" name="advOutFFPathBrowse">
+                           <property name="text">
+                            <string>Browse</string>
+                           </property>
+                          </widget>
+                         </item>
+                        </layout>
+                       </widget>
+                       <widget class="QWidget" name="page_4">
+                        <layout class="QHBoxLayout" name="horizontalLayout_8">
+                         <property name="spacing">
+                          <number>0</number>
+                         </property>
+                         <property name="leftMargin">
+                          <number>0</number>
+                         </property>
+                         <property name="topMargin">
+                          <number>0</number>
+                         </property>
+                         <property name="rightMargin">
+                          <number>0</number>
+                         </property>
+                         <property name="bottomMargin">
+                          <number>0</number>
+                         </property>
+                         <item>
+                          <widget class="QLineEdit" name="advOutFFURL">
+                           <property name="enabled">
+                            <bool>true</bool>
+                           </property>
+                          </widget>
+                         </item>
+                        </layout>
+                       </widget>
+                      </widget>
                      </item>
-                     <item row="1" column="0">
+                     <item row="2" column="0">
                       <widget class="QLabel" name="label_16">
                        <property name="text">
                         <string>Basic.Settings.Output.Adv.FFmpeg.Format</string>
                        </property>
                       </widget>
                      </item>
+                     <item row="2" column="1">
+                      <widget class="QComboBox" name="advOutFFFormat"/>
+                     </item>
                      <item row="3" column="0">
+                      <widget class="QLabel" name="label_44">
+                       <property name="text">
+                        <string>Basic.Settings.Output.Adv.FFmpeg.FormatDesc</string>
+                       </property>
+                      </widget>
+                     </item>
+                     <item row="3" column="1">
+                      <widget class="QLabel" name="advOutFFFormatDesc">
+                       <property name="text">
+                        <string/>
+                       </property>
+                      </widget>
+                     </item>
+                     <item row="4" column="0">
                       <widget class="QLabel" name="label_40">
                        <property name="text">
                         <string>Basic.Settings.Output.VideoBitrate</string>
                        </property>
                       </widget>
                      </item>
-                     <item row="3" column="1">
+                     <item row="4" column="1">
                       <widget class="QSpinBox" name="advOutFFVBitrate">
                        <property name="minimum">
                         <number>0</number>
@@ -1363,7 +1425,7 @@
                        </property>
                       </widget>
                      </item>
-                     <item row="4" column="0">
+                     <item row="5" column="0">
                       <widget class="QCheckBox" name="advOutFFUseRescale">
                        <property name="sizePolicy">
                         <sizepolicy hsizetype="Minimum" vsizetype="Expanding">
@@ -1379,7 +1441,7 @@
                        </property>
                       </widget>
                      </item>
-                     <item row="4" column="1">
+                     <item row="5" column="1">
                       <widget class="QComboBox" name="advOutFFRescale">
                        <property name="enabled">
                         <bool>false</bool>
@@ -1389,34 +1451,34 @@
                        </property>
                       </widget>
                      </item>
-                     <item row="5" column="0">
+                     <item row="6" column="0">
                       <widget class="QLabel" name="label_37">
                        <property name="text">
                         <string>Basic.Settings.Output.Adv.FFmpeg.VEncoder</string>
                        </property>
                       </widget>
                      </item>
-                     <item row="5" column="1">
+                     <item row="6" column="1">
                       <widget class="QComboBox" name="advOutFFVEncoder"/>
                      </item>
-                     <item row="6" column="0">
+                     <item row="8" column="0">
                       <widget class="QLabel" name="label_38">
                        <property name="text">
                         <string>Basic.Settings.Output.Adv.FFmpeg.VEncoderSettings</string>
                        </property>
                       </widget>
                      </item>
-                     <item row="6" column="1">
+                     <item row="8" column="1">
                       <widget class="QLineEdit" name="advOutFFVCfg"/>
                      </item>
-                     <item row="7" column="0">
+                     <item row="9" column="0">
                       <widget class="QLabel" name="label_41">
                        <property name="text">
                         <string>Basic.Settings.Output.AudioBitrate</string>
                        </property>
                       </widget>
                      </item>
-                     <item row="7" column="1">
+                     <item row="9" column="1">
                       <widget class="QSpinBox" name="advOutFFABitrate">
                        <property name="minimum">
                         <number>32</number>
@@ -1432,14 +1494,14 @@
                        </property>
                       </widget>
                      </item>
-                     <item row="8" column="0">
+                     <item row="10" column="0">
                       <widget class="QLabel" name="label_47">
                        <property name="text">
                         <string>Basic.Settings.Output.Adv.AudioTrack</string>
                        </property>
                       </widget>
                      </item>
-                     <item row="8" column="1">
+                     <item row="10" column="1">
                       <widget class="QWidget" name="widget_10" native="true">
                        <property name="sizePolicy">
                         <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
@@ -1494,42 +1556,61 @@
                        </layout>
                       </widget>
                      </item>
-                     <item row="9" column="0">
+                     <item row="11" column="0">
                       <widget class="QLabel" name="label_39">
                        <property name="text">
                         <string>Basic.Settings.Output.Adv.FFmpeg.AEncoder</string>
                        </property>
                       </widget>
                      </item>
-                     <item row="10" column="0">
+                     <item row="11" column="1">
+                      <widget class="QComboBox" name="advOutFFAEncoder"/>
+                     </item>
+                     <item row="12" column="0">
                       <widget class="QLabel" name="label_46">
                        <property name="text">
                         <string>Basic.Settings.Output.Adv.FFmpeg.AEncoderSettings</string>
                        </property>
                       </widget>
                      </item>
-                     <item row="10" column="1">
+                     <item row="12" column="1">
                       <widget class="QLineEdit" name="advOutFFACfg"/>
                      </item>
-                     <item row="1" column="1">
-                      <widget class="QComboBox" name="advOutFFFormat"/>
-                     </item>
-                     <item row="2" column="1">
-                      <widget class="QLabel" name="advOutFFFormatDesc">
-                       <property name="text">
-                        <string/>
+                     <item row="0" column="0">
+                      <widget class="QLabel" name="label_48">
+                       <property name="sizePolicy">
+                        <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+                         <horstretch>0</horstretch>
+                         <verstretch>0</verstretch>
+                        </sizepolicy>
+                       </property>
+                       <property name="minimumSize">
+                        <size>
+                         <width>170</width>
+                         <height>0</height>
+                        </size>
                        </property>
-                      </widget>
-                     </item>
-                     <item row="2" column="0">
-                      <widget class="QLabel" name="label_44">
                        <property name="text">
-                        <string>Basic.Settings.Output.Adv.FFmpeg.FormatDesc</string>
+                        <string>Basic.Settings.Output.Adv.FFmpeg.Type</string>
+                       </property>
+                       <property name="alignment">
+                        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
                        </property>
                       </widget>
                      </item>
-                     <item row="9" column="1">
-                      <widget class="QComboBox" name="advOutFFAEncoder"/>
+                     <item row="0" column="1">
+                      <widget class="QComboBox" name="advOutFFType">
+                       <item>
+                        <property name="text">
+                         <string>Basic.Settings.Output.Adv.FFmpeg.Type.RecordToFile</string>
+                        </property>
+                       </item>
+                       <item>
+                        <property name="text">
+                         <string>Basic.Settings.Output.Adv.FFmpeg.Type.URL</string>
+                        </property>
+                       </item>
+                      </widget>
                      </item>
                     </layout>
                    </widget>
@@ -2171,8 +2252,8 @@
              <rect>
               <x>0</x>
               <y>0</y>
-              <width>98</width>
-              <height>28</height>
+              <width>67</width>
+              <height>16</height>
              </rect>
             </property>
            </widget>
@@ -2559,8 +2640,8 @@
              <rect>
               <x>0</x>
               <y>0</y>
-              <width>325</width>
-              <height>229</height>
+              <width>428</width>
+              <height>287</height>
              </rect>
             </property>
             <layout class="QVBoxLayout" name="verticalLayout_16">
@@ -2789,8 +2870,8 @@
    <slot>setCurrentIndex(int)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>310</x>
-     <y>29</y>
+     <x>159</x>
+     <y>34</y>
     </hint>
     <hint type="destinationlabel">
      <x>241</x>
@@ -2821,12 +2902,12 @@
    <slot>setEnabled(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>422</x>
-     <y>168</y>
+     <x>875</x>
+     <y>254</y>
     </hint>
     <hint type="destinationlabel">
-     <x>420</x>
-     <y>188</y>
+     <x>875</x>
+     <y>291</y>
     </hint>
    </hints>
   </connection>
@@ -2837,12 +2918,12 @@
    <slot>setEnabled(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>503</x>
-     <y>160</y>
+     <x>875</x>
+     <y>254</y>
     </hint>
     <hint type="destinationlabel">
-     <x>501</x>
-     <y>209</y>
+     <x>875</x>
+     <y>328</y>
     </hint>
    </hints>
   </connection>
@@ -2853,12 +2934,12 @@
    <slot>setVisible(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>439</x>
-     <y>240</y>
+     <x>875</x>
+     <y>360</y>
     </hint>
     <hint type="destinationlabel">
-     <x>750</x>
-     <y>295</y>
+     <x>875</x>
+     <y>427</y>
     </hint>
    </hints>
   </connection>
@@ -2869,12 +2950,12 @@
    <slot>setVisible(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>482</x>
-     <y>241</y>
+     <x>875</x>
+     <y>360</y>
     </hint>
     <hint type="destinationlabel">
-     <x>367</x>
-     <y>295</y>
+     <x>466</x>
+     <y>427</y>
     </hint>
    </hints>
   </connection>
@@ -2885,12 +2966,12 @@
    <slot>setVisible(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>459</x>
-     <y>234</y>
+     <x>875</x>
+     <y>360</y>
     </hint>
     <hint type="destinationlabel">
-     <x>750</x>
-     <y>347</y>
+     <x>875</x>
+     <y>503</y>
     </hint>
    </hints>
   </connection>
@@ -2901,12 +2982,12 @@
    <slot>setVisible(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>554</x>
-     <y>236</y>
+     <x>875</x>
+     <y>360</y>
     </hint>
     <hint type="destinationlabel">
-     <x>367</x>
-     <y>347</y>
+     <x>466</x>
+     <y>503</y>
     </hint>
    </hints>
   </connection>
@@ -2917,12 +2998,12 @@
    <slot>setVisible(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>398</x>
-     <y>241</y>
+     <x>871</x>
+     <y>360</y>
     </hint>
     <hint type="destinationlabel">
-     <x>410</x>
-     <y>261</y>
+     <x>875</x>
+     <y>392</y>
     </hint>
    </hints>
   </connection>
@@ -2933,12 +3014,12 @@
    <slot>setEnabled(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>318</x>
-     <y>312</y>
+     <x>466</x>
+     <y>464</y>
     </hint>
     <hint type="destinationlabel">
-     <x>473</x>
-     <y>311</y>
+     <x>875</x>
+     <y>464</y>
     </hint>
    </hints>
   </connection>
@@ -2949,12 +3030,12 @@
    <slot>setVisible(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>456</x>
-     <y>241</y>
+     <x>875</x>
+     <y>360</y>
     </hint>
     <hint type="destinationlabel">
-     <x>260</x>
-     <y>315</y>
+     <x>457</x>
+     <y>464</y>
     </hint>
    </hints>
   </connection>
@@ -2965,12 +3046,12 @@
    <slot>setVisible(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>525</x>
-     <y>238</y>
+     <x>875</x>
+     <y>360</y>
     </hint>
     <hint type="destinationlabel">
-     <x>519</x>
-     <y>317</y>
+     <x>875</x>
+     <y>464</y>
     </hint>
    </hints>
   </connection>
@@ -2981,12 +3062,12 @@
    <slot>setCurrentIndex(int)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>259</x>
-     <y>101</y>
+     <x>705</x>
+     <y>144</y>
     </hint>
     <hint type="destinationlabel">
-     <x>243</x>
-     <y>106</y>
+     <x>396</x>
+     <y>245</y>
     </hint>
    </hints>
   </connection>
@@ -2997,12 +3078,12 @@
    <slot>setEnabled(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>259</x>
-     <y>113</y>
+     <x>514</x>
+     <y>344</y>
     </hint>
     <hint type="destinationlabel">
-     <x>230</x>
-     <y>125</y>
+     <x>748</x>
+     <y>344</y>
     </hint>
    </hints>
   </connection>
@@ -3013,12 +3094,12 @@
    <slot>setEnabled(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>468</x>
-     <y>110</y>
+     <x>864</x>
+     <y>141</y>
     </hint>
     <hint type="destinationlabel">
-     <x>362</x>
-     <y>136</y>
+     <x>427</x>
+     <y>178</y>
     </hint>
    </hints>
   </connection>
@@ -3029,12 +3110,12 @@
    <slot>setEnabled(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>468</x>
-     <y>110</y>
+     <x>864</x>
+     <y>141</y>
     </hint>
     <hint type="destinationlabel">
-     <x>468</x>
-     <y>136</y>
+     <x>864</x>
+     <y>178</y>
     </hint>
    </hints>
   </connection>
@@ -3045,12 +3126,12 @@
    <slot>setEnabled(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>468</x>
-     <y>110</y>
+     <x>864</x>
+     <y>141</y>
     </hint>
     <hint type="destinationlabel">
-     <x>299</x>
-     <y>162</y>
+     <x>427</x>
+     <y>215</y>
     </hint>
    </hints>
   </connection>
@@ -3061,12 +3142,12 @@
    <slot>setEnabled(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>468</x>
-     <y>110</y>
+     <x>864</x>
+     <y>141</y>
     </hint>
     <hint type="destinationlabel">
-     <x>468</x>
-     <y>162</y>
+     <x>864</x>
+     <y>215</y>
     </hint>
    </hints>
   </connection>
@@ -3077,12 +3158,12 @@
    <slot>setEnabled(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>270</x>
-     <y>237</y>
+     <x>427</x>
+     <y>355</y>
     </hint>
     <hint type="destinationlabel">
-     <x>437</x>
-     <y>237</y>
+     <x>862</x>
+     <y>355</y>
     </hint>
    </hints>
   </connection>
@@ -3093,12 +3174,12 @@
    <slot>setEnabled(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>259</x>
-     <y>113</y>
+     <x>424</x>
+     <y>331</y>
     </hint>
     <hint type="destinationlabel">
-     <x>230</x>
-     <y>125</y>
+     <x>658</x>
+     <y>331</y>
     </hint>
    </hints>
   </connection>
@@ -3109,12 +3190,12 @@
    <slot>setEnabled(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>444</x>
-     <y>162</y>
+     <x>875</x>
+     <y>254</y>
     </hint>
     <hint type="destinationlabel">
-     <x>298</x>
-     <y>190</y>
+     <x>466</x>
+     <y>291</y>
     </hint>
    </hints>
   </connection>
@@ -3125,12 +3206,28 @@
    <slot>setEnabled(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>475</x>
-     <y>161</y>
+     <x>875</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>466</x>
+     <y>328</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>advOutFFType</sender>
+   <signal>currentIndexChanged(int)</signal>
+   <receiver>stackedWidget_2</receiver>
+   <slot>setCurrentIndex(int)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>732</x>
+     <y>179</y>
     </hint>
     <hint type="destinationlabel">
-     <x>350</x>
-     <y>218</y>
+     <x>777</x>
+     <y>206</y>
     </hint>
    </hints>
   </connection>

+ 20 - 12
obs/window-basic-main-outputs.cpp

@@ -298,6 +298,7 @@ struct AdvancedOutput : BasicOutputHandler {
 	OBSEncoder             h264Streaming;
 	OBSEncoder             h264Recording;
 
+	bool                   ffmpegOutput;
 	bool                   ffmpegRecording;
 	bool                   useStreamEncoder;
 
@@ -351,7 +352,9 @@ AdvancedOutput::AdvancedOutput(OBSBasic *main_) : BasicOutputHandler(main_)
 	const char *recordEncoder = config_get_string(main->Config(), "AdvOut",
 			"RecEncoder");
 
-	ffmpegRecording = astrcmpi(recType, "FFmpeg") == 0;
+	ffmpegOutput = astrcmpi(recType, "FFmpeg") == 0;
+	ffmpegRecording = ffmpegOutput &&
+		config_get_bool(main->Config(), "AdvOut", "FFOutputToFile");
 	useStreamEncoder = astrcmpi(recordEncoder, "none") == 0;
 
 	OBSData streamEncSettings = GetDataFromJsonFile("streamEncoder.json");
@@ -363,7 +366,7 @@ AdvancedOutput::AdvancedOutput(OBSBasic *main_) : BasicOutputHandler(main_)
 		throw "Failed to create stream output (advanced output)";
 	obs_output_release(streamOutput);
 
-	if (ffmpegRecording) {
+	if (ffmpegOutput) {
 		fileOutput = obs_output_create("ffmpeg_output",
 				"adv_ffmpeg_output", nullptr, nullptr);
 		if (!fileOutput)
@@ -447,7 +450,7 @@ inline void AdvancedOutput::UpdateRecordingSettings()
 void AdvancedOutput::Update()
 {
 	UpdateStreamSettings();
-	if (!useStreamEncoder && !ffmpegRecording)
+	if (!useStreamEncoder && !ffmpegOutput)
 		UpdateRecordingSettings();
 	UpdateAudioSettings();
 }
@@ -649,7 +652,7 @@ void AdvancedOutput::SetupOutputs()
 
 	SetupStreaming();
 
-	if (ffmpegRecording)
+	if (ffmpegOutput)
 		SetupFFmpeg();
 	else
 		SetupRecording();
@@ -667,7 +670,7 @@ int AdvancedOutput::GetAudioBitrate(size_t i) const
 bool AdvancedOutput::StartStreaming(obs_service_t *service)
 {
 	if (!useStreamEncoder ||
-	    (!ffmpegRecording && !obs_output_active(fileOutput))) {
+	    (!ffmpegOutput && !obs_output_active(fileOutput))) {
 		UpdateStreamSettings();
 	}
 
@@ -697,8 +700,11 @@ bool AdvancedOutput::StartStreaming(obs_service_t *service)
 
 bool AdvancedOutput::StartRecording()
 {
+	const char *path;
+	const char *format;
+
 	if (!useStreamEncoder) {
-		if (!ffmpegRecording) {
+		if (!ffmpegOutput) {
 			UpdateRecordingSettings();
 		}
 	} else if (!obs_output_active(streamOutput)) {
@@ -710,11 +716,11 @@ bool AdvancedOutput::StartRecording()
 	if (!Active())
 		SetupOutputs();
 
-	if (!ffmpegRecording) {
-		const char *path = config_get_string(main->Config(),
-				"AdvOut", "RecFilePath");
-		const char *format = config_get_string(main->Config(),
-				"AdvOut", "RecFormat");
+	if (!ffmpegOutput || ffmpegRecording) {
+		path = config_get_string(main->Config(), "AdvOut",
+				ffmpegRecording ? "FFFilePath" : "RecFilePath");
+		format = config_get_string(main->Config(), "AdvOut",
+				ffmpegRecording ? "FFExtension" : "RecFormat");
 
 		os_dir_t *dir = path ? os_opendir(path) : nullptr;
 
@@ -737,7 +743,9 @@ bool AdvancedOutput::StartRecording()
 		strPath += GenerateTimeDateFilename(format);
 
 		obs_data_t *settings = obs_data_create();
-		obs_data_set_string(settings, "path", strPath.c_str());
+		obs_data_set_string(settings,
+				ffmpegRecording ? "url" : "path",
+				strPath.c_str());
 
 		obs_output_update(fileOutput, settings);
 

+ 5 - 0
obs/window-basic-main.cpp

@@ -681,6 +681,11 @@ bool OBSBasic::InitBasicConfigDefaults()
 	config_set_default_string(basicConfig, "AdvOut", "RecEncoder",
 			"none");
 
+	config_set_default_bool  (basicConfig, "AdvOut", "FFOutputToFile",
+			true);
+	config_set_default_string(basicConfig, "AdvOut", "FFFilePath",
+			GetDefaultVideoSavePath().c_str());
+	config_set_default_string(basicConfig, "AdvOut", "FFExtension", "mp4");
 	config_set_default_uint  (basicConfig, "AdvOut", "FFVBitrate", 2500);
 	config_set_default_bool  (basicConfig, "AdvOut", "FFUseRescale",
 			false);

+ 31 - 12
obs/window-basic-settings.cpp

@@ -300,6 +300,8 @@ OBSBasicSettings::OBSBasicSettings(QWidget *parent)
 	HookWidget(ui->advOutRecTrack2,      CHECK_CHANGED,  OUTPUTS_CHANGED);
 	HookWidget(ui->advOutRecTrack3,      CHECK_CHANGED,  OUTPUTS_CHANGED);
 	HookWidget(ui->advOutRecTrack4,      CHECK_CHANGED,  OUTPUTS_CHANGED);
+	HookWidget(ui->advOutFFType,         COMBO_CHANGED,  OUTPUTS_CHANGED);
+	HookWidget(ui->advOutFFRecPath,      EDIT_CHANGED,   OUTPUTS_CHANGED);
 	HookWidget(ui->advOutFFURL,          EDIT_CHANGED,   OUTPUTS_CHANGED);
 	HookWidget(ui->advOutFFFormat,       COMBO_CHANGED,  OUTPUTS_CHANGED);
 	HookWidget(ui->advOutFFVBitrate,     SCROLL_CHANGED, OUTPUTS_CHANGED);
@@ -1172,6 +1174,10 @@ static void SelectEncoder(QComboBox *combo, const char *name, int id)
 
 void OBSBasicSettings::LoadAdvOutputFFmpegSettings()
 {
+	bool saveFile = config_get_bool(main->Config(), "AdvOut",
+			"FFOutputToFile");
+	const char *path = config_get_string(main->Config(), "AdvOut",
+			"FFFilePath");
 	const char *url = config_get_string(main->Config(), "AdvOut", "FFURL");
 	const char *format = config_get_string(main->Config(), "AdvOut",
 			"FFFormat");
@@ -1200,7 +1206,9 @@ void OBSBasicSettings::LoadAdvOutputFFmpegSettings()
 	const char *aEncCustom = config_get_string(main->Config(), "AdvOut",
 			"FFACustom");
 
-	ui->advOutFFURL->setText(url);
+	ui->advOutFFType->setCurrentIndex(saveFile ? 0 : 1);
+	ui->advOutFFRecPath->setText(QT_UTF8(path));
+	ui->advOutFFURL->setText(QT_UTF8(url));
 	SelectFormat(ui->advOutFFFormat, format, mimeType);
 	ui->advOutFFVBitrate->setValue(videoBitrate);
 	ui->advOutFFUseRescale->setChecked(rescale);
@@ -2008,11 +2016,23 @@ void OBSBasicSettings::SaveFormat(QComboBox *combo)
 				desc.name);
 		config_set_string(main->Config(), "AdvOut", "FFFormatMimeType",
 				desc.mimeType);
+
+		const char *ext = ff_format_desc_extensions(desc.desc);
+		string extStr = ext;
+
+		char *comma = strchr(&extStr[0], ',');
+		if (comma)
+			comma = 0;
+
+		config_set_string(main->Config(), "AdvOut", "FFExtension",
+				extStr.c_str());
 	} else {
 		config_set_string(main->Config(), "AdvOut", "FFFormat",
 				nullptr);
 		config_set_string(main->Config(), "AdvOut", "FFFormatMimeType",
 				nullptr);
+
+		config_remove_value(main->Config(), "AdvOut", "FFExtension");
 	}
 }
 
@@ -2078,6 +2098,9 @@ void OBSBasicSettings::SaveOutputSettings()
 			(ui->advOutRecTrack3->isChecked() ? (1<<2) : 0) |
 			(ui->advOutRecTrack4->isChecked() ? (1<<3) : 0));
 
+	config_set_bool(main->Config(), "AdvOut", "FFOutputToFile",
+			ui->advOutFFType->currentIndex() == 0 ? true : false);
+	SaveEdit(ui->advOutFFRecPath, "AdvOut", "FFFilePath");
 	SaveEdit(ui->advOutFFURL, "AdvOut", "FFURL");
 	SaveFormat(ui->advOutFFFormat);
 	SaveSpinBox(ui->advOutFFVBitrate, "AdvOut", "FFVBitrate");
@@ -2387,19 +2410,15 @@ void OBSBasicSettings::on_advOutRecPathBrowse_clicked()
 
 void OBSBasicSettings::on_advOutFFPathBrowse_clicked()
 {
-	QString filter;
-	filter += QTStr("Basic.Settings.Output.Adv.FFmpeg.SaveFilter.Common");
-	filter += " (*.avi *.mp4 *.flv *.ts *.mkv *.wav *.aac);;";
-	filter += QTStr("Basic.Settings.Output.Adv.FFmpeg.SaveFilter.All");
-	filter += " (*.*)";
-
-	QString file = QFileDialog::getSaveFileName(this,
-			QTStr("Basic.Settings.Output.SelectFile"),
-			ui->simpleOutputPath->text(), filter);
-	if (file.isEmpty())
+	QString dir = QFileDialog::getExistingDirectory(this,
+			QTStr("Basic.Settings.Output.SelectDirectory"),
+			ui->advOutRecPath->text(),
+			QFileDialog::ShowDirsOnly |
+			QFileDialog::DontResolveSymlinks);
+	if (dir.isEmpty())
 		return;
 
-	ui->advOutFFURL->setText(file);
+	ui->advOutFFRecPath->setText(dir);
 }
 
 void OBSBasicSettings::on_advOutEncoder_currentIndexChanged(int idx)