@@ -19,6 +19,8 @@ max_attempts=${SE_VIDEO_WAIT_ATTEMPTS:-50}
1919file_ready_max_attempts=${SE_VIDEO_FILE_READY_WAIT_ATTEMPTS:- 5}
2020wait_uploader_shutdown_max_attempts=${SE_VIDEO_WAIT_UPLOADER_SHUTDOWN_ATTEMPTS:- 5}
2121graceful_stop_delay=${SE_VIDEO_GRACEFUL_STOP_DELAY:- 5}
22+ ffmpeg_stop_timeout=${SE_VIDEO_FFMPEG_STOP_TIMEOUT:- 10}
23+ file_stability_wait=${SE_VIDEO_FILE_STABILITY_WAIT:- 2}
2224min_recording_duration=${SE_VIDEO_MIN_RECORDING_DURATION:- 5}
2325video_validation_enabled=${SE_VIDEO_VALIDATION_ENABLED:- " true" }
2426video_fix_corrupted=${SE_VIDEO_FIX_CORRUPTED:- " true" }
@@ -190,6 +192,32 @@ function exit_on_max_session_reach() {
190192 fi
191193}
192194
195+ function wait_for_file_stability() {
196+ local video_file=" $1 "
197+ local session_id_param=" $2 "
198+
199+ if [[ ! -f " ${video_file} " ]]; then
200+ return 1
201+ fi
202+
203+ echo " $( date -u +" ${ts_format} " ) [${process_name} ] - [Session: ${session_id_param} ] Waiting ${file_stability_wait} s for file to stabilize: ${video_file} "
204+
205+ local prev_size=$( stat -f%z " ${video_file} " 2> /dev/null || stat -c%s " ${video_file} " 2> /dev/null)
206+ sleep ${file_stability_wait}
207+ local curr_size=$( stat -f%z " ${video_file} " 2> /dev/null || stat -c%s " ${video_file} " 2> /dev/null)
208+
209+ if [[ " ${prev_size} " != " ${curr_size} " ]]; then
210+ echo " $( date -u +" ${ts_format} " ) [${process_name} ] - [Session: ${session_id_param} ] WARNING: File size changed during stability check (${prev_size} -> ${curr_size} ), waiting longer"
211+ sleep ${file_stability_wait}
212+ fi
213+
214+ # Force filesystem sync
215+ sync
216+
217+ echo " $( date -u +" ${ts_format} " ) [${process_name} ] - [Session: ${session_id_param} ] File stable at size: ${curr_size} bytes"
218+ return 0
219+ }
220+
193221function validate_mp4_file() {
194222 local video_file=" $1 "
195223 local session_id_param=" $2 "
@@ -274,17 +302,33 @@ function stop_ffmpeg_graceful_async() {
274302 echo " $( date -u +" ${ts_format} " ) [${process_name} ] - [Session: ${session_id_param} ] Sending SIGTERM to FFmpeg PID: $FFMPEG_PID for file: ${video_file_name_param} "
275303 kill -SIGTERM $FFMPEG_PID
276304
277- # Wait for FFmpeg to finish writing
305+ # Wait for FFmpeg to finish writing with timeout
306+ local wait_count=0
307+ while kill -0 $FFMPEG_PID 2> /dev/null && [ $wait_count -lt ${ffmpeg_stop_timeout} ]; do
308+ sleep 1
309+ wait_count=$(( wait_count + 1 ))
310+ done
311+
312+ if kill -0 $FFMPEG_PID 2> /dev/null; then
313+ echo " $( date -u +" ${ts_format} " ) [${process_name} ] - [Session: ${session_id_param} ] WARNING: FFmpeg still running after ${ffmpeg_stop_timeout} s, forcing kill"
314+ kill -SIGKILL $FFMPEG_PID 2> /dev/null
315+ else
316+ echo " $( date -u +" ${ts_format} " ) [${process_name} ] - [Session: ${session_id_param} ] FFmpeg exited gracefully after ${wait_count} s"
317+ fi
318+
278319 wait $FFMPEG_PID 2> /dev/null
279320
280- # Grace period for metadata finalization
281- echo " $( date -u +" ${ts_format} " ) [${process_name} ] - [Session: ${session_id_param} ] Waiting ${graceful_stop_delay} seconds for video metadata finalization"
321+ # Grace period for metadata finalization and filesystem sync
322+ echo " $( date -u +" ${ts_format} " ) [${process_name} ] - [Session: ${session_id_param} ] Waiting ${graceful_stop_delay} s for video metadata finalization"
282323 sleep ${graceful_stop_delay}
283324
284- # Verify file exists
325+ # Verify file exists and wait for stability
285326 if [[ -f " ${video_file_to_finalize} " ]]; then
286327 echo " $( date -u +" ${ts_format} " ) [${process_name} ] - [Session: ${session_id_param} ] Video file finalized: ${video_file_to_finalize} "
287328
329+ # Wait for file to stabilize (no more writes)
330+ wait_for_file_stability " ${video_file_to_finalize} " " ${session_id_param} "
331+
288332 # Validate MP4 file integrity
289333 if validate_mp4_file " ${video_file_to_finalize} " " ${session_id_param} " ; then
290334 # File is valid, proceed with upload
@@ -436,8 +480,10 @@ if [[ "${VIDEO_UPLOAD_ENABLED}" != "true" ]] && [[ "${VIDEO_FILE_NAME}" != "auto
436480 ffmpeg -hide_banner -loglevel warning -threads ${SE_FFMPEG_THREADS:- 1} -thread_queue_size 512 \
437481 -probesize 32M -analyzeduration 0 -y -f x11grab -video_size ${VIDEO_SIZE} -r ${FRAME_RATE} \
438482 -i ${DISPLAY} ${SE_AUDIO_SOURCE} -codec:v ${CODEC} ${PRESET:- " -preset veryfast" } \
439- -tune zerolatency -crf ${SE_VIDEO_CRF:- 28} -maxrate ${SE_VIDEO_MAXRATE:- 1000k} -bufsize ${SE_VIDEO_BUFSIZE:- 2000k} \
440- -pix_fmt yuv420p -movflags +faststart " $video_file " &
483+ -crf ${SE_VIDEO_CRF:- 28} -maxrate ${SE_VIDEO_MAXRATE:- 1000k} -bufsize ${SE_VIDEO_BUFSIZE:- 2000k} \
484+ -pix_fmt yuv420p -g ${SE_VIDEO_GOP_SIZE:- 60} -keyint_min ${SE_VIDEO_KEYINT_MIN:- 30} \
485+ -sc_threshold 0 -force_key_frames " expr:gte(t,n_forced*2)" \
486+ -movflags +faststart+frag_keyframe+empty_moov+default_base_moof " $video_file " &
441487 FFMPEG_PID=$!
442488 if ps -p $FFMPEG_PID > /dev/null; then
443489 wait $FFMPEG_PID
@@ -474,8 +520,10 @@ else
474520 ffmpeg -hide_banner -loglevel warning -threads ${SE_FFMPEG_THREADS:- 1} -thread_queue_size 512 \
475521 -probesize 32M -analyzeduration 0 -y -f x11grab -video_size ${VIDEO_SIZE} -r ${FRAME_RATE} \
476522 -i ${DISPLAY} ${SE_AUDIO_SOURCE} -codec:v ${CODEC} ${PRESET:- " -preset veryfast" } \
477- -tune zerolatency -crf ${SE_VIDEO_CRF:- 28} -maxrate ${SE_VIDEO_MAXRATE:- 1000k} -bufsize ${SE_VIDEO_BUFSIZE:- 2000k} \
478- -pix_fmt yuv420p -movflags +faststart " $video_file " &
523+ -crf ${SE_VIDEO_CRF:- 28} -maxrate ${SE_VIDEO_MAXRATE:- 1000k} -bufsize ${SE_VIDEO_BUFSIZE:- 2000k} \
524+ -pix_fmt yuv420p -g ${SE_VIDEO_GOP_SIZE:- 60} -keyint_min ${SE_VIDEO_KEYINT_MIN:- 30} \
525+ -sc_threshold 0 -force_key_frames " expr:gte(t,n_forced*2)" \
526+ -movflags +faststart+frag_keyframe+empty_moov+default_base_moof " $video_file " &
479527 FFMPEG_PID=$!
480528 if ps -p $FFMPEG_PID > /dev/null; then
481529 recording_started=" true"
0 commit comments