1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
| #!/bin/bash
# ========= 环境检查 ========= if ! command -v ffmpeg &>/dev/null || ! command -v ffprobe &>/dev/null; then echo "请先安装 ffmpeg 和 ffprobe" exit 1 fi
echo "🎬 欢迎使用 视频分割小工具 for Mac"
# ========= 文件大小格式化 ========= format_size() { local bytes=$1
if (( bytes < 1073741824 )); then size=$(echo "scale=2; $bytes / (1024 * 1024)" | bc) printf "%.2fMB" "$size" else size=$(echo "scale=2; $bytes / (1024 * 1024 * 1024)" | bc) printf "%.2fGB" "$size" fi }
# ========= 主循环 ========= while true; do echo "" echo "📥 拖入视频文件,或输入 q 退出:" IFS= read -r input_line
[[ "$input_line" == "q" ]] && echo "👋 已退出" && exit 0
eval "set -- $input_line" inputs=() for arg in "$@"; do inputs+=("$arg") done
for input in "${inputs[@]}"; do if [ ! -f "$input" ]; then echo "❗ 文件不存在:$input,跳过..." continue fi
echo "" echo "🚀 正在处理:$input"
filename=$(basename "$input") basename_no_ext="${filename%.*}" dir=$(dirname "$input") output_dir="$dir/${basename_no_ext}_parts" mkdir -p "$output_dir"
filesize=$(stat -f%z "$input") filesize_human=$(format_size "$filesize") echo "📋 文件大小:$filesize_human"
# ========= 输入大小 ========= echo "" read -p "请输入每段大小(GB,默认 1.9): " size_gb
if [[ -z "$size_gb" ]]; then size_gb=1.9 echo "📦 使用默认大小:1.9GB" else if ! [[ "$size_gb" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then echo "❌ 输入格式错误" continue fi echo "📦 每段大小:${size_gb}GB" fi
max_size=$(echo "$size_gb * 1024^3" | bc | cut -d'.' -f1)
duration=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$input") duration_int=$(printf "%.0f" "$duration")
echo "📋 总时长:$duration_int 秒"
# ========= 智能估算分段 ========= estimated_parts=$(echo "($filesize + $max_size - 1) / $max_size" | bc)
part_duration=$(echo "$duration / $estimated_parts" | bc) part_duration_int=$(printf "%.0f" "$part_duration")
((part_duration_int <= 0)) && part_duration_int=1
echo "🚀 预计分割为 $estimated_parts 段" echo "⏱ 每段约 ${part_duration_int}s(关键帧对齐,实际略有浮动)"
# ========= 稳定无损分割 ========= ffmpeg -loglevel quiet \ -fflags +genpts \ -i "$input" \ -c copy \ -map 0 \ -f segment \ -segment_time "$part_duration_int" \ -segment_time_delta 0.5 \ -reset_timestamps 1 \ -avoid_negative_ts make_zero \ "$output_dir/${basename_no_ext}_part%03d.${filename##*.}"
echo "" echo "✅ 分割完成" echo "📂 输出目录:$output_dir"
for file in "$output_dir"/*; do size_human=$(du -h "$file" | cut -f1) echo " - $(basename "$file") [$size_human]" done
open "$output_dir" done
done
|