我家的小米摄像头是按每小时一个文件夹,文件夹内是每分钟一个视频的,跟论坛提供小米摄像头小文件合并 有点不一样,所以就自己写了个脚本进行合并


#!/bin/bash
# 定义根目录
root_dir="/vol4/1000/Monitor/xiaomi_camera_videos"
# 定义合并后文件存放目录
output_dir="/vol4/1000/Monitor/xiaomi"
# 定义日志文件路径
log_file="$output_dir/merge_camera_videos_$(date +%Y%m%d).log"
# 检查目录是否存在,不存在则创建
if [ ! -d "$output_dir" ]; then
mkdir -p "$output_dir"
fi
# 检查 ffmpeg 是否安装,飞牛一般都会默认安装的
# sudo apt-get update
# sudo apt-get install ffmpeg
if ! command -v ffmpeg &> /dev/null
then
echo "ffmpeg 未安装,请先安装 ffmpeg。" | tee -a "$log_file"
exit 1
fi
# 检查 GNU Parallel 是否安装
# sudo apt-get update
# sudo apt-get install parallel
if ! command -v parallel &> /dev/null
then
echo "GNU Parallel 未安装,请先安装 GNU Parallel。" | tee -a "$log_file"
exit 1
fi
# 获取前天的日期,根据自己需求来更改需要合并的日期
# 我是担心有时候视频同步慢,合并当天或昨天的,怕还没同步完就合并了,所以就只处理前天的
yesterday=$(date -d "2 days ago" +%Y%m%d)
echo "前天的日期: $yesterday" | tee -a "$log_file"
# 定义合并函数
merge_camera_videos() {
camera_dir="$1"
output_dir="$2"
yesterday="$3"
camera_id=$(basename "$camera_dir")
daily_files=""
date_dirs=()
# 遍历每个日期时间目录
for datetime_dir in "$camera_dir"/*; do
if [ -d "$datetime_dir" ]; then
date_str=$(basename "$datetime_dir" | cut -c1-8)
if [ "$date_str" = "$yesterday" ]; then
daily_files="${daily_files} $datetime_dir/*.mp4"
date_dirs+=("$datetime_dir")
fi
fi
done
# 若前天有文件,进行合并
if [ -n "$daily_files" ]; then
echo "摄像头 $camera_id 有前天的文件,开始合并..." | tee -a "$log_file"
# 检查并创建摄像头 ID 对应的目录
camera_output_dir="$output_dir/$camera_id"
if [ ! -d "$camera_output_dir" ]; then
mkdir -p "$camera_output_dir"
fi
output_file="$camera_output_dir/${yesterday}.mp4"
# 创建一个临时文件列表
tmp_file_list=$(mktemp)
valid_files=0
for file in $daily_files; do
if [ -f "$file" ]; then
# 检查文件是否能正常打开
if ffmpeg -v error -i "$file" -f null - 2>/dev/null; then
echo "file '$file'" >> "$tmp_file_list"
valid_files=$((valid_files + 1))
else
echo "文件 $file 损坏,跳过" | tee -a "$log_file"
fi
fi
done
# 检查临时文件列表是否为空
if [ $valid_files -eq 0 ]; then
echo "摄像头 $camera_id 没有有效的视频文件,跳过合并" | tee -a "$log_file"
rm "$tmp_file_list"
return
fi
# 使用 ffmpeg 合并视频文件,更换音频编码为 mp3,调整线程数量为 2,使用 -strict experimental
echo "开始合并 $camera_id 的文件到 $output_file" | tee -a "$log_file"
ffmpeg -f concat -safe 0 -i "$tmp_file_list" -c:v copy -c:a libmp3lame -q:a 2 -threads 2 -strict experimental "$output_file" 2>&1 | tee -a "$log_file"
ffmpeg_exit_code=$?
echo "摄像头 $camera_id 的文件合并成功" | tee -a "$log_file"
# 删除临时文件列表
rm "$tmp_file_list"
# 删除已合并的文件
for file in $daily_files; do
if [ -f "$file" ]; then
rm "$file"
fi
done
# 删除该天对应的文件夹
for dir in "${date_dirs[@]}"; do
if [ -d "$dir" ]; then
rm -r "$dir"
fi
done
else
echo "摄像头 $camera_id 没有前天的文件,跳过合并" | tee -a "$log_file"
fi
}
# 并行处理每个摄像头的合并任务,排除根目录,设置并行任务数量为 6,根据自己的CPU来设定,我的是 I5-11400 6核 12线程的
export -f merge_camera_videos
find "$root_dir" -mindepth 1 -maxdepth 1 -type d -print0 | parallel -j 6 -0 merge_camera_videos {} "$output_dir" "$yesterday" | tee -a "$log_file"
echo "视频合并完成,已合并的文件和对应文件夹已删除。" | tee -a "$log_file"
# 清理 /vol4/1000/Monitor/xiaomi 目录下超过30天的文件
echo "开始清理 /vol4/1000/Monitor/xiaomi 目录下超过30天的文件..." | tee -a "$log_file"
find "$output_dir" -type f -mtime +30 -exec rm -f {} \;
echo "超过30天的文件清理完成。" | tee -a "$log_file"
下载脚本
附件:merge_videos.zip,获取文件路径,如 /vol4/1000/Monitor/merge_videos.sh
进入控制台修改权限 sudo chmod +x /vol4/1000/Monitor/merge_videos.sh
接着输入 crontab -e,打开定时任务输入
0 1 * * * /vol4/1000/Monitor/merge_videos.sh
我的是每天凌晨1点开始执行