@@ -65,8 +65,7 @@ pub struct MediaRecorder {
6565 ffmpeg_stdin : Option < ChildStdin > ,
6666 device_name : Option < String > ,
6767 start_time : Option < Instant > ,
68- audio_file_path : Option < PathBuf > ,
69- video_file_path : Option < PathBuf > ,
68+ chunks_dir : PathBuf ,
7069 audio_pipe_task : Option < JoinHandle < ( ) > > ,
7170 video_pipe_task : Option < JoinHandle < ( ) > > ,
7271}
@@ -81,8 +80,7 @@ impl MediaRecorder {
8180 & mut self ,
8281 options : RecordingOptions ,
8382 screenshot_dir : & Path ,
84- audio_chunks_dir : & Path ,
85- video_chunks_dir : & Path ,
83+ recording_dir : & Path ,
8684 custom_device : Option < & str > ,
8785 max_screen_width : usize ,
8886 max_screen_height : usize ,
@@ -126,17 +124,15 @@ impl MediaRecorder {
126124 video_capturer. start ( video_start_time. clone ( ) , screenshot_dir, options_clone) ;
127125
128126 tracing:: info!( "Starting audio recording and processing..." ) ;
129- let audio_chunk_pattern = audio_chunks_dir. join ( "audio_recording_%03d.aac" ) ;
130- let video_chunk_pattern = video_chunks_dir. join ( "video_recording_%03d.ts" ) ;
131- let audio_segment_list_filename = audio_chunks_dir. join ( "segment_list.txt" ) ;
132- let video_segment_list_filename = video_chunks_dir. join ( "segment_list.txt" ) ;
127+ let segment_pattern_path = recording_dir. join ( "segment_%03d.ts" ) ;
128+ let playlist_path = recording_dir. join ( "stream.m3u8" ) ;
133129
134- let video_pipe_path = video_chunks_dir . join ( "pipe .pipe" ) ;
130+ let video_pipe_path = recording_dir . join ( "video .pipe" ) ;
135131
136132 std:: fs:: remove_file ( & video_pipe_path) . ok ( ) ;
137133 create_named_pipe ( & video_pipe_path) . map_err ( |e| e. to_string ( ) ) ?;
138134
139- let audio_pipe_path = audio_chunks_dir . join ( "pipe .pipe" ) ;
135+ let audio_pipe_path = recording_dir . join ( "audio .pipe" ) ;
140136
141137 std:: fs:: remove_file ( & audio_pipe_path) . ok ( ) ;
142138 create_named_pipe ( & audio_pipe_path) . map_err ( |e| e. to_string ( ) ) ?;
@@ -167,21 +163,7 @@ impl MediaRecorder {
167163 . args ( [ "-f" , "rawvideo" , "-pix_fmt" , "bgra" ] )
168164 . args ( [ "-s" , & size, "-r" , & fps] )
169165 . args ( [ "-thread_queue_size" , "4096" , "-i" ] )
170- . arg ( & video_pipe_path)
171- // video out
172- . args ( [
173- "-vf" ,
174- & format ! ( "fps={fps},scale=in_range=full:out_range=limited" ) ,
175- ] )
176- . args ( [ "-c:v" , "libx264" , "-preset" , "ultrafast" ] )
177- . args ( [ "-pix_fmt" , "yuv420p" , "-tune" , "zerolatency" ] )
178- . args ( [ "-vsync" , "1" , "-force_key_frames" , "expr:gte(t,n_forced*3)" ] )
179- . args ( [ "-f" , "segment" , "-movflags" , "frag_keyframe+empty_moov" ] )
180- . args ( [ "-reset_timestamps" , "1" , "-an" ] )
181- . args ( [ "-segment_time" , "3" ] )
182- . args ( [ "-segment_format" , "ts" ] )
183- . args ( [ "-segment_time_delta" , "0.01" , "-segment_list" ] )
184- . args ( [ & video_segment_list_filename, & video_chunk_pattern] ) ;
166+ . arg ( & video_pipe_path) ;
185167
186168 if self . audio_enabled {
187169 if let Some ( ( TimeOffsetTarget :: Audio , args) ) = & time_offset {
@@ -197,19 +179,46 @@ impl MediaRecorder {
197179 // audio in
198180 . args ( [ "-f" , sample_format, "-ar" , & sample_rate_str] )
199181 . args ( [ "-ac" , & channels_str, "-thread_queue_size" , "4096" , "-i" ] )
200- . arg ( & audio_pipe_path)
201- // out
182+ . arg ( & audio_pipe_path) ;
183+ // out
184+ // .args(["-f", "hls", "-async", "1"])
185+ // .args(["-segment_time", "3", "-segment_time_delta", "0.01"])
186+ // .args(["-reset_timestamps", "1", "-vn", "-segment_list"])
187+ // .args([&audio_segment_list_filename, &audio_chunk_pattern]);
188+ }
189+
190+ ffmpeg_command
191+ . args ( [ "-f" , "hls" ] )
192+ . args ( [ "-hls_time" , "5" , "-hls_playlist_type" , "vod" ] )
193+ . args ( [ "-hls_flags" , "independent_segments" ] )
194+ . args ( [ "-master_pl_name" , "master.m3u8" ] )
195+ . args ( [ "-hls_segment_type" , "mpegts" ] )
196+ . arg ( "-hls_segment_filename" )
197+ . arg ( & segment_pattern_path)
198+ // video
199+ . args ( [ "-codec:v" , "libx264" , "-preset" , "ultrafast" ] )
200+ . args ( [ "-pix_fmt" , "yuv420p" , "-tune" , "zerolatency" ] )
201+ . args ( [ "-vsync" , "1" , "-force_key_frames" , "expr:gte(t,n_forced*3)" ] )
202+ . args ( [ "-movflags" , "frag_keyframe+empty_moov" ] )
203+ . args ( [
204+ "-vf" ,
205+ & format ! ( "fps={fps},scale=in_range=full:out_range=limited" ) ,
206+ ] ) ;
207+
208+ if self . audio_enabled {
209+ ffmpeg_command
210+ // audio
211+ . args ( [ "-codec:a" , "aac" , "-b:a" , "128k" , "-async" , "1" ] )
202212 . args ( [
203213 "-af" ,
204214 "aresample=async=1:min_hard_comp=0.100000:first_pts=0" ,
205- ] )
206- . args ( [ "-codec:a" , "aac" , "-b:a" , "128k" ] )
207- . args ( [ "-async" , "1" , "-f" , "segment" ] )
208- . args ( [ "-segment_time" , "3" , "-segment_time_delta" , "0.01" ] )
209- . args ( [ "-reset_timestamps" , "1" , "-vn" , "-segment_list" ] )
210- . args ( [ & audio_segment_list_filename, & audio_chunk_pattern] ) ;
215+ ] ) ;
216+ } else {
217+ ffmpeg_command. args ( [ "-an" ] ) ;
211218 }
212219
220+ ffmpeg_command. arg ( & playlist_path) ;
221+
213222 tracing:: trace!( "Starting FFmpeg process..." ) ;
214223
215224 let ( ffmpeg_child, ffmpeg_stdin) = self
@@ -226,8 +235,7 @@ impl MediaRecorder {
226235 self . video_pipe_task = Some ( tokio:: spawn ( video_capturer. collect_frames ( video_pipe_path) ) ) ;
227236
228237 self . start_time = Some ( Instant :: now ( ) ) ;
229- self . audio_file_path = Some ( audio_chunks_dir. to_path_buf ( ) ) ;
230- self . video_file_path = Some ( video_chunks_dir. to_path_buf ( ) ) ;
238+ self . chunks_dir = recording_dir. to_path_buf ( ) ;
231239 self . ffmpeg_process = Some ( ffmpeg_child) ;
232240 self . ffmpeg_stdin = Some ( ffmpeg_stdin) ;
233241 self . device_name = self . audio_capturer . as_ref ( ) . map ( |c| c. device_name . clone ( ) ) ;
0 commit comments