Skip to content

Instantly share code, notes, and snippets.

@izfsk-ium
Created May 11, 2025 12:35
Show Gist options
  • Save izfsk-ium/395feae4dae7bcce64d4997ac1c3ed7e to your computer and use it in GitHub Desktop.
Save izfsk-ium/395feae4dae7bcce64d4997ac1c3ed7e to your computer and use it in GitHub Desktop.
减少视频文件的大小
#!/bin/bash
# ====== 彩色定义 ======
RED='\033[1;31m'
GREEN='\033[1;32m'
YELLOW='\033[1;33m'
CYAN='\033[1;36m'
BLUE='\033[1;34m'
BOLD='\033[1m'
NC='\033[0m' # 重置
# ====== 函数:打印分隔线 ======
print_section() {
echo -e "${BLUE}${BOLD}\n========== $1 ==========${NC}"
}
# ====== 参数解析 ======
force_delete=false
for arg in "$@"; do
case "$arg" in
--force-delete)
force_delete=true
shift
;;
*)
if [[ -z "$input_file" ]]; then
input_file="$arg"
fi
;;
esac
done
# ====== 检查输入文件 ======
if [[ -z "$input_file" ]]; then
echo -e "${YELLOW}用法: $0 [--force-delete] <输入视频文件>${NC}"
exit 1
fi
if [[ ! -f "$input_file" ]]; then
echo -e "${RED}错误: 文件 '$input_file' 未找到!${NC}"
exit 1
fi
# ====== 显示原视频信息 ======
print_section "原视频信息"
ffprobe_output=$(ffprobe -hide_banner -v error -select_streams v:0 \
-show_entries stream=codec_name,width,height,bit_rate,r_frame_rate,avg_frame_rate \
-of default=noprint_wrappers=1 "$input_file")
echo -e "${CYAN}$ffprobe_output${NC}"
# ====== 提取文件名信息 ======
original_size=$(stat -c%s "$input_file")
base_name=$(basename "$input_file")
extension="${base_name##*.}"
file_name_without_extension="${base_name%.*}"
tmp_output_file="/tmp/${file_name_without_extension}_$(date +%s).mkv"
target_dir=$(dirname "$input_file")
print_section "文件准备"
echo -e "${CYAN}输入文件 : $input_file"
echo -e "中间输出文件 : $tmp_output_file"
echo -e "原始文件大小 : $(numfmt --to=iec-i --suffix=B $original_size)${NC}"
# ====== 构建 FFmpeg 命令 ======
ffmpeg_command=(
ffmpeg
-hide_banner
-loglevel error
-stats
-i "$input_file"
-c:v hevc_nvenc
-rc vbr_hq
-cq 24
-c:a libopus
-b:a 128k
-map 0
-map_metadata 0
-y
"$tmp_output_file"
)
print_section "将执行的 FFmpeg 命令"
echo -e "${YELLOW}${BOLD}${ffmpeg_command[*]}${NC}"
# ====== 执行 FFmpeg ======
print_section "开始编码"
"${ffmpeg_command[@]}"
ffmpeg_exit_status=$?
if [[ $ffmpeg_exit_status -ne 0 ]]; then
echo -e "${RED}错误: FFmpeg 编码失败 (退出状态码: $ffmpeg_exit_status)。${NC}"
[[ -f "$tmp_output_file" ]] && rm "$tmp_output_file"
exit 1
fi
echo -e "${GREEN}FFmpeg 编码成功!${NC}"
# ====== 输出结果和压缩比 ======
output_size=$(stat -c%s "$tmp_output_file")
size_diff=$((original_size - output_size))
print_section "压缩结果"
echo -e "${CYAN}输出文件大小 : $(numfmt --to=iec-i --suffix=B $output_size)${NC}"
if [[ $size_diff -ge 0 ]]; then
echo -e "${GREEN}文件体积减少了: $(numfmt --to=iec-i --suffix=B $size_diff)${NC}"
else
echo -e "${YELLOW}文件体积增加了: $(numfmt --to=iec-i --suffix=B $((-size_diff)))${NC}"
fi
# ====== 文件移动和删除 ======
print_section "处理输出文件"
if $force_delete; then
final_output="${target_dir}/${file_name_without_extension}.mkv"
echo -e "${CYAN}复制到: $final_output 并删除原始文件...${NC}"
rm "$input_file"
cp "$tmp_output_file" "$final_output"
echo -e "${GREEN}已删除原始文件: $input_file${NC}"
else
if [[ "${extension,,}" == "mkv" ]]; then
final_output="${target_dir}/new_${file_name_without_extension}.mkv"
else
final_output="${target_dir}/${file_name_without_extension}.mkv"
fi
echo -e "${CYAN}复制到: $final_output${NC}"
cp "$tmp_output_file" "$final_output"
read -p "$(echo -e "${YELLOW}是否删除原始文件 '$input_file'? [y/N]: ${NC}")" confirm_delete
if [[ "$confirm_delete" =~ ^[Yy]$ ]]; then
rm "$input_file"
echo -e "${GREEN}已删除原始文件: $input_file 并重命名。${NC}"
else
echo -e "${CYAN}保留原始文件: $input_file${NC}"
fi
fi
# ====== 清理临时文件 ======
rm "$tmp_output_file"
print_section "完成"
echo -e "${GREEN}文件处理完成!${NC}"
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment