FFmpeg处理RTSP流分段后,如何可靠触发后续操作?
可靠处理FFmpeg分段视频的几种方案
方案1:用FFmpeg原生的分段回调命令(最推荐)
FFmpeg从4.3版本开始支持segment_muxer_close_command参数,这个参数会在每个分段文件完全写入并关闭后执行指定命令,完全由FFmpeg触发,没有竞争条件,完美匹配你的需求。
修改原FFmpeg命令,新增该参数即可:
ffmpeg -rtsp_transport tcp -i rtsp://$camera_creds@$camera_ip/video/1 \ -map 0 -c:v h264 -preset:v ultrafast -reset_timestamps 1 \ -f segment -segment_time 300 -strftime 1 \ -segment_list ${monitor_dir}/segments$camera.txt \ -segment_muxer_close_command 'bash -c "mv %s ${monitor_dir}/processed/ && /path/to/your_process_script.sh ${monitor_dir}/processed/$(basename %s)"' \ $monitor_dir/cam${camera}_out%Y%m%d_%H%M%S.mp4
%s会被FFmpeg自动替换为当前完成的分段文件完整路径- 示例中先将文件移至
processed目录(避免与正在写入的文件混淆),再调用自定义处理脚本,你可根据需求调整逻辑,比如直接上传、转码等。 - 若你的FFmpeg版本低于4.3,建议先升级到新版本,这个功能就是专门解决分段后处理这类场景的。
方案2:用inotify监控文件写入完成事件
如果暂时无法升级FFmpeg,可使用Linux下的inotifywait工具(需安装inotify-tools包)监控分段文件目录,监听close_write事件——该事件仅在文件被完全关闭时触发,也就是FFmpeg写完分段之后。
示例脚本:
#!/bin/bash MONITOR_DIR="$monitor_dir" PROCESSED_DIR="${MONITOR_DIR}/processed" mkdir -p "$PROCESSED_DIR" inotifywait -m -e close_write --format '%w%f' "$MONITOR_DIR" | while read FILE; do # 仅处理符合命名规则的分段文件 if [[ "$FILE" =~ cam${camera}_out[0-9]{8}_[0-9]{6}\.mp4 ]]; then # 先移走文件再处理,避免重复触发事件 mv "$FILE" "$PROCESSED_DIR/" /path/to/your_process_script.sh "$PROCESSED_DIR/$(basename $FILE)" fi done
- 这种方式无需依赖FFmpeg的分段列表文件,直接监控文件系统事件,比轮询高效,也不会出现竞争问题。
方案3:改进列表监控方式(兼容旧场景)
如果坚持使用分段列表的方式,绝对不要修改FFmpeg生成的segments$camera.txt文件(FFmpeg会持续向该文件追加内容,修改它会引发inode冲突或竞争问题),而是自己维护一个独立的处理记录文件,比如processed_segments$camera.txt。
示例脚本逻辑:
#!/bin/bash SEGMENT_LIST="${monitor_dir}/segments$camera.txt" PROCESSED_LIST="${monitor_dir}/processed_segments$camera.txt" touch "$PROCESSED_LIST" # 找出未处理的分段文件(对比FFmpeg列表与本地处理记录) comm -23 <(sort "$SEGMENT_LIST") <(sort "$PROCESSED_LIST") | while read FILE; do # 保险起见,等待1秒确保FFmpeg已关闭文件 sleep 1 if [[ -f "$FILE" ]]; then /path/to/your_process_script.sh "$FILE" echo "$FILE" >> "$PROCESSED_LIST" fi done
- 用
comm命令筛选出未处理的文件,完全避开对FFmpeg原列表的修改,彻底解决inode和竞争问题。
内容的提问来源于stack exchange,提问作者user717847
相关产品推荐
相关产品推荐

