

















脚本内容:
#!/bin/bash # 一键添加封面脚本 - 使用视频第一帧作为封面 # 支持: 单个文件、目录、递归子目录、通配符(* ?) SCRIPT_NAME=$(basename "$0") TARGETS=() RECURSIVE=0 DRY_RUN=0 # 显示帮助信息 show_help() { cat << EOF ======================================== MP4 添加封面工具 - 使用视频第一帧作为封面 ======================================== 用法: bash ${SCRIPT_NAME} [选项] <文件或目录...> 选项: -h, --help 显示本帮助信息 -r, --recursive 递归处理子目录 -d, --dry-run 试运行模式(只显示要处理的文件,不执行) 参数: <文件或目录> 要处理的MP4文件、目录,或通配符模式 支持多个参数,支持通配符(* ?) 不传参数时显示此帮助信息 示例: # 处理单个文件 bash ${SCRIPT_NAME} video.mp4 # 处理多个文件 bash ${SCRIPT_NAME} video1.mp4 video2.mp4 video3.mp4 # 使用通配符处理多个文件 bash ${SCRIPT_NAME} *.mp4 bash ${SCRIPT_NAME} video*.mp4 bash ${SCRIPT_NAME} ????.mp4 # 处理当前目录下所有mp4(不递归子目录) bash ${SCRIPT_NAME} . # 处理指定目录下所有mp4(递归子目录) bash ${SCRIPT_NAME} -r /e/ff_output_mp4 # 试运行模式(查看会处理哪些文件) bash ${SCRIPT_NAME} -d *.mp4 执行逻辑: 1. 检查输入参数是否存在 2. 如果是文件: 直接处理该文件 3. 如果是目录: 查找该目录下所有mp4文件 - 默认只处理当前目录,不进入子目录 - 加 -r 参数会递归处理所有子目录 4. 如果是通配符: 展开后处理匹配的文件 5. 对每个mp4文件: a. 提取视频第一帧作为临时封面图片 b. 将封面嵌入mp4文件(不重新编码视频) c. 替换原文件,清理临时文件 6. 输出处理统计报告 注意事项: - 原文件会被覆盖,请提前备份重要文件 - 处理后的文件会保留原有的faststart特性 - 封面图片使用mjpeg格式,质量较高 - 失败时会保留原文件,不会损坏数据 ======================================== EOF } # 解析参数 while [[ $# -gt 0 ]]; do case $1 in -h|--help) show_help exit 0 ;; -r|--recursive) RECURSIVE=1 shift ;; -d|--dry-run) DRY_RUN=1 shift ;; -*) echo "错误: 未知选项 $1" echo "使用 -h 或 --help 查看帮助信息" exit 1 ;; *) # 收集所有非选项参数(支持通配符展开) TARGETS+=("$1") shift ;; esac done # 检查是否提供了目标参数 if [ ${#TARGETS[@]} -eq 0 ]; then echo "错误: 未指定文件或目录" echo "" show_help exit 1 fi # 收集所有要处理的文件 FILES=() # 处理每个目标参数 for target in "${TARGETS[@]}"; do # 检查目标是否存在 if [ ! -e "$target" ]; then echo "警告: 路径不存在,跳过: $target" continue fi if [ -f "$target" ]; then # 单个文件 if [[ "$target" == *.mp4 ]] || [[ "$target" == *.MP4 ]]; then FILES+=("$target") else echo "警告: 不是MP4文件,跳过: $target" fi elif [ -d "$target" ]; then # 目录 if [ $RECURSIVE -eq 1 ]; then # 递归查找 while IFS= read -r -d '' file; do FILES+=("$file") done < <(find "$target" -type f \( -name "*.mp4" -o -name "*.MP4" \) -print0 2>/dev/null) else # 非递归,仅当前目录 for file in "$target"/*.mp4 "$target"/*.MP4; do [ -e "$file" ] && FILES+=("$file") done fi fi done # 去重(防止通配符和显式参数重复) UNIQUE_FILES=() for file in "${FILES[@]}"; do is_duplicate=0 for unique in "${UNIQUE_FILES[@]}"; do if [ "$file" = "$unique" ]; then is_duplicate=1 break fi done if [ $is_duplicate -eq 0 ]; then UNIQUE_FILES+=("$file") fi done FILES=("${UNIQUE_FILES[@]}") # 检查是否找到文件 TOTAL=${#FILES[@]} if [ $TOTAL -eq 0 ]; then echo "错误: 未找到有效的MP4文件" exit 1 fi # 显示执行信息 echo "========================================" echo "MP4 添加封面工具" echo "========================================" echo "找到: $TOTAL 个MP4文件" if [ $DRY_RUN -eq 1 ]; then echo "模式: 试运行(不实际执行)" fi echo "========================================" echo "" # 试运行模式:只显示列表 if [ $DRY_RUN -eq 1 ]; then echo "【试运行模式】将要处理的文件:" for i in "${!FILES[@]}"; do idx=$((i + 1)) echo " [$idx] ${FILES[$i]}" done echo "" echo "试运行完成,未实际处理文件" echo "去掉 -d 参数即可正式执行" exit 0 fi # 处理文件 SUCCESS=0 FAILED=0 SKIPPED=0 for i in "${!FILES[@]}"; do idx=$((i + 1)) file="${FILES[$i]}" filename=$(basename "$file") echo "[$idx/$TOTAL] 处理: $filename" # 检查文件是否可写 if [ ! -w "$file" ]; then echo " ✗ 文件不可写,跳过" SKIPPED=$((SKIPPED + 1)) continue fi # 创建临时封面路径(与原文件同目录) cover_jpg="${file}.cover.tmp.jpg" temp_output="${file}.tmp.mp4" # 步骤1: 提取第一帧 ffmpeg -i "$file" -ss 00:00:00.1 -vframes 1 -q:v 2 -y "$cover_jpg" 2>/dev/null if [ ! -f "$cover_jpg" ]; then echo " ✗ 提取封面失败" FAILED=$((FAILED + 1)) continue fi # 步骤2: 嵌入封面 ffmpeg -i "$file" -i "$cover_jpg" -map 0 -map 1 -c copy -disposition:v:1 attached_pic -movflags +faststart -y "$temp_output" 2>/dev/null if [ $? -eq 0 ] && [ -f "$temp_output" ]; then # 获取文件大小 orig_size=$(ls -lh "$file" 2>/dev/null | awk '{print $5}') new_size=$(ls -lh "$temp_output" 2>/dev/null | awk '{print $5}') # 替换原文件 mv "$temp_output" "$file" rm -f "$cover_jpg" echo " ✓ 成功 (${orig_size} → ${new_size})" SUCCESS=$((SUCCESS + 1)) else echo " ✗ 嵌入封面失败" rm -f "$temp_output" "$cover_jpg" FAILED=$((FAILED + 1)) fi done # 输出统计 echo "" echo "========================================" echo "处理完成" echo "========================================" echo "总计: $TOTAL 个文件" echo "成功: $SUCCESS 个" echo "失败: $FAILED 个" echo "跳过: $SKIPPED 个" echo "========================================" if [ $FAILED -gt 0 ]; then exit 1 else exit 0 fi
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。