最后活跃于 1 month ago

p.sh 原始文件
1#!/bin/bash
2
3# =================配置区域=================
4# 基础路径配置
5BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6INPUT_DIR="$BASE_DIR/videos_to_process"
7OUTPUT_DIR="$BASE_DIR/enhanced_videos"
8APP_DIR="$BASE_DIR/app"
9EXEC_PATH="$APP_DIR/realesrgan-ncnn-vulkan"
10
11# Real-ESRGAN 配置
12# 模型可选: realesrgan-x4plus (适合真实影像), realesrgan-x4plus-anime (适合动漫)
13MODEL_NAME="realesrgan-x4plus"
14SCALE=4
15# 显卡ID,自动探测一般填0
16GPU_ID=0
17
18# 下载链接
19DOWNLOAD_URL="https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.5.0/realesrgan-ncnn-vulkan-20220424-ubuntu.zip"
20ZIP_FILE="realesrgan-ncnn-vulkan-20220424-ubuntu.zip"
21
22# =========================================
23
24# 颜色定义
25GREEN='\033[0;32m'
26YELLOW='\033[1;33m'
27RED='\033[0;31m'
28NC='\033[0m' # No Color
29
30# 0. 检查依赖 (ffmpeg)
31if ! command -v ffmpeg &> /dev/null; then
32 echo -e "${RED}Error: ffmpeg 未安装。${NC}"
33 echo "请运行: sudo apt update && sudo apt install ffmpeg"
34 exit 1
35fi
36
37# 1. 准备目录和环境
38mkdir -p "$OUTPUT_DIR"
39mkdir -p "$APP_DIR"
40
41# 检查并下载 Real-ESRGAN
42if [ ! -f "$EXEC_PATH" ]; then
43 echo -e "${YELLOW}Real-ESRGAN 可执行文件未找到,准备下载...${NC}"
44
45 # 进入 app 目录下载
46 cd "$APP_DIR" || exit
47
48 if [ -f "$ZIP_FILE" ]; then
49 rm "$ZIP_FILE"
50 fi
51
52 echo "正在下载: $DOWNLOAD_URL"
53 wget -q --show-progress "$DOWNLOAD_URL"
54
55 if [ $? -ne 0 ]; then
56 echo -e "${RED}下载失败,请检查网络连接。${NC}"
57 exit 1
58 fi
59
60 echo "正在解压..."
61 unzip -q "$ZIP_FILE"
62
63 # 赋予执行权限
64 chmod +x realesrgan-ncnn-vulkan
65
66 # 清理压缩包
67 rm "$ZIP_FILE"
68
69 echo -e "${GREEN}Real-ESRGAN 安装完成!${NC}"
70
71 # 回到基础目录
72 cd "$BASE_DIR" || exit
73else
74 echo -e "${GREEN}Real-ESRGAN 已安装,跳过下载。${NC}"
75fi
76
77# 2. 开始扫描视频并处理
78shopt -s nullglob
79video_files=("$INPUT_DIR"/*.mp4 "$INPUT_DIR"/*.mov "$INPUT_DIR"/*.avi "$INPUT_DIR"/*.mkv)
80
81if [ ${#video_files[@]} -eq 0 ]; then
82 echo -e "${YELLOW}$INPUT_DIR 中没有找到支持的视频文件。${NC}"
83 exit 0
84fi
85
86echo -e "${GREEN}找到 ${#video_files[@]} 个视频文件,开始处理...${NC}"
87
88# 进度条绘制用的全长字符串
89FULL_BAR="##################################################"
90BAR_WIDTH=50
91
92for INPUT_VIDEO in "${video_files[@]}"; do
93 BASE_NAME=$(basename "$INPUT_VIDEO")
94 FILENAME="${BASE_NAME%.*}"
95 OUTPUT_VIDEO="$OUTPUT_DIR/${FILENAME}_x${SCALE}.mp4"
96
97 echo "----------------------------------------------------------------"
98 echo -e "正在处理: ${YELLOW}$BASE_NAME${NC}"
99 echo "----------------------------------------------------------------"
100
101 # 创建临时目录
102 TMP_FRAMES=$(mktemp -d -p "$BASE_DIR" "tmp_frames_XXXXXX")
103 OUT_FRAMES=$(mktemp -d -p "$BASE_DIR" "out_frames_XXXXXX")
104
105 # Step 1: 拆帧
106 echo -e "${YELLOW}[1/3] 正在提取帧 (使用 ffmpeg)...${NC}"
107 # 使用 png 格式以保证无损画质传入 AI
108 ffmpeg -v error -stats -i "$INPUT_VIDEO" -qscale:v 1 -qmin 1 -fps_mode passthrough "$TMP_FRAMES/frame%08d.png"
109
110 if [ $? -ne 0 ]; then
111 echo -e "${RED}拆帧失败,跳过此视频。${NC}"
112 rm -rf "$TMP_FRAMES" "$OUT_FRAMES"
113 continue
114 fi
115
116 # 统计总帧数 (ls -1U 速度较快,不排序)
117 TOTAL_FRAMES=$(ls -1U "$TMP_FRAMES" | wc -l)
118 echo "总帧数: $TOTAL_FRAMES"
119
120 # Step 2: AI 超分
121 echo -e "${YELLOW}[2/3] 正在进行 AI 超分 (Real-ESRGAN GPU)...${NC}"
122 echo "模型: $MODEL_NAME | 放大倍数: x$SCALE"
123
124 # 1. 以后台方式启动 (&),并将标准输出和错误输出都扔进黑洞
125 "$EXEC_PATH" \
126 -i "$TMP_FRAMES" \
127 -o "$OUT_FRAMES" \
128 -n "$MODEL_NAME" \
129 -s "$SCALE" \
130 -g "$GPU_ID" \
131 -f png > /dev/null 2>&1 &
132
133 PID=$! # 获取进程ID
134
135 # 2. 循环监控进度
136 while kill -0 $PID 2> /dev/null; do
137 # 统计已生成的文件数
138 CURRENT_FRAMES=$(ls -1U "$OUT_FRAMES" | wc -l)
139
140 # 计算百分比
141 if [ "$TOTAL_FRAMES" -gt 0 ]; then
142 PERCENT=$(( CURRENT_FRAMES * 100 / TOTAL_FRAMES ))
143 else
144 PERCENT=0
145 fi
146
147 # 防止文件系统统计延迟导致超过 100%
148 if [ "$PERCENT" -gt 100 ]; then PERCENT=100; fi
149
150 # 计算进度条填充长度
151 FILLED_LEN=$(( PERCENT * BAR_WIDTH / 100 ))
152
153 # 打印进度条 (\r 回车不换行)
154 printf "\r[${GREEN}%-${BAR_WIDTH}s${NC}] %3d%% (%d/%d)" "${FULL_BAR:0:FILLED_LEN}" "$PERCENT" "$CURRENT_FRAMES" "$TOTAL_FRAMES"
155
156 sleep 1
157 done
158
159 # 等待进程彻底退出并获取退出码
160 wait $PID
161 EXIT_CODE=$?
162
163 echo "" # 进度条跑完换个行
164
165 if [ $EXIT_CODE -ne 0 ]; then
166 echo -e "${RED}AI 超分失败,请检查显卡驱动或显存是否足够。${NC}"
167 rm -rf "$TMP_FRAMES" "$OUT_FRAMES"
168 continue
169 fi
170
171 # Step 3: 合成视频
172 echo -e "${YELLOW}[3/3] 正在合成视频 (High Quality H.265)...${NC}"
173
174 # 获取原视频帧率
175 FPS=$(ffprobe -v error -select_streams v -of default=noprint_wrappers=1:nokey=1 -show_entries stream=r_frame_rate "$INPUT_VIDEO")
176
177 # 修复点:保持双引号防止 nullglob 错误
178 ffmpeg -v error -stats \
179 -framerate "$FPS" -i "$OUT_FRAMES/frame%08d.png" \
180 -i "$INPUT_VIDEO" -map 0:v:0 -map "1:a:0?" -c:a copy \
181 -c:v libx265 -preset veryslow -crf 18 -pix_fmt yuv420p -tag:v hvc1 \
182 "$OUTPUT_VIDEO"
183
184 if [ $? -ne 0 ]; then
185 echo -e "${YELLOW}H.265 编码失败,尝试回退到 H.264...${NC}"
186 ffmpeg -v error -stats \
187 -framerate "$FPS" -i "$OUT_FRAMES/frame%08d.png" \
188 -i "$INPUT_VIDEO" -map 0:v:0 -map "1:a:0?" -c:a copy \
189 -c:v libx264 -preset veryslow -crf 18 -pix_fmt yuv420p \
190 "$OUTPUT_VIDEO"
191 fi
192
193 # 清理临时文件
194 echo -e "${GREEN}清理临时文件...${NC}"
195 rm -rf "$TMP_FRAMES" "$OUT_FRAMES"
196
197 echo -e "${GREEN}完成! 输出文件: $OUTPUT_VIDEO${NC}"
198done
199
200echo -e "${GREEN}所有任务已完成。${NC}"