Skip to content

Instantly share code, notes, and snippets.

@yumin9822
Last active May 29, 2025 07:06
Show Gist options
  • Save yumin9822/e94ce90b1812a4cbe60633ec83435894 to your computer and use it in GitHub Desktop.
Save yumin9822/e94ce90b1812a4cbe60633ec83435894 to your computer and use it in GitHub Desktop.
video screenshoot and upload to imgbox, enable comppression by Tinypng while bigger than 10MB
#!/bin/bash
ScriptName=${0##*/}
function print_usage() {
echo "请使用: $ScriptName <文件序号> <视频文件夹> [排序方式]"
echo "截图将保存到 /root/screenshots 文件夹中。"
echo "示例: $ScriptName 2 /path/to/video_folder"
echo " $ScriptName 1 /path/to/video_folder name"
echo "说明:"
echo " - 文件序号:选择文件夹中的第几个视频文件(从 1 开始)。"
echo " - 视频文件夹:支持 ISO 文件、普通视频文件和多级目录。"
echo " - 排序方式(可选):"
echo " * size(默认):按文件大小从大到小排序"
echo " * name:按文件名字母顺序排序"
echo " - 支持常见视频文件后缀:.mp4, .mkv, .avi, .ts, .VOB, .m2ts, .iso 等。"
}
# 多个 TinyPNG API KEY
TINYPNG_API_KEYS=(
"aaaa"
"bbbb"
"cccc"
)
CURRENT_API_KEY_INDEX=0 # 当前使用的 API KEY 索引
QUOTA_LIMIT=450 # API KEY 使用次数上限
NUMBERS_PNG="6"
STARTING_TIME="00:03:30"
FILE_INDEX=$1
FILE_DIR=$2
FILES_SORT_BY=${3:-"size"} # 第三个参数,默认为size
ENABLE_COMPRESSION=true # 默认开启图片压缩功能
# 验证排序方式参数
if [[ "${FILES_SORT_BY}" != "size" && "${FILES_SORT_BY}" != "name" ]]; then
echo "错误:排序方式只能是 'size' 或 'name',当前值为:${FILES_SORT_BY}"
print_usage
exit 1
fi
# 文件大小限制
PNG_MAX_SIZE=$((10 * 1024 * 1024)) # 10MB in bytes
# 支持的视频文件后缀
VIDEO_EXTS=("mp4" "mkv" "avi" "ts" "VOB" "m2ts" "mov" "flv" "wmv" "mpeg" "mpg" "iso" "ISO")
## 检查参数数量
if [ $# -lt 2 ]; then
print_usage
exit 1
fi
## 检查视频文件夹是否存在
if [ ! -d "${FILE_DIR}" ]; then
echo "错误:文件夹 '${FILE_DIR}' 不存在。"
exit 1
fi
## 检查 ffmpeg 是否安装
if ! command -v ffmpeg &> /dev/null; then
echo "错误:未找到 'ffmpeg' 工具,请先安装。"
exit 1
fi
## 检查 tinifier 是否安装
if ! command -v tinifier &> /dev/null; then
echo "错误:未找到 'tinifier' 工具,请先安装。"
exit 1
fi
## 检查 imgbox 是否安装
if ! command -v imgbox &> /dev/null; then
echo "错误:未找到 'imgbox' 工具,请先安装。"
exit 1
fi
## 创建截图保存目录
OUTPUT_DIR="/root/screenshots"
mkdir -p "${OUTPUT_DIR}"
## 获取视频文件列表并按大小排序
# 使用临时文件存储文件路径和大小
TEMP_FILE=$(mktemp)
trap "rm -f ${TEMP_FILE}" EXIT
# 优先查找一级目录
echo "正在扫描一级目录中的视频文件..."
for ext in "${VIDEO_EXTS[@]}"; do
while IFS= read -r -d '' video_file; do
file_size=$(stat -c%s "${video_file}" 2>/dev/null)
if [[ -z "${file_size}" ]] || ! [[ "${file_size}" =~ ^[0-9]+$ ]]; then
echo "错误:无法获取文件大小,跳过文件:${video_file}"
continue
fi
# 将文件大小和路径写入临时文件
echo "${file_size} ${video_file}" >> "${TEMP_FILE}"
done < <(find "${FILE_DIR}" -maxdepth 1 -type f -iname "*.${ext}" -print0)
done
# 如果一级目录没有视频文件,则递归查找多级目录
if [ ! -s "${TEMP_FILE}" ]; then
echo "一级目录未找到视频文件,开始递归查找多级目录..."
for ext in "${VIDEO_EXTS[@]}"; do
while IFS= read -r -d '' video_file; do
file_size=$(stat -c%s "${video_file}" 2>/dev/null)
if [[ -z "${file_size}" ]] || ! [[ "${file_size}" =~ ^[0-9]+$ ]]; then
echo "错误:无法获取文件大小,跳过文件:${video_file}"
continue
fi
# 将文件大小和路径写入临时文件
echo "${file_size} ${video_file}" >> "${TEMP_FILE}"
done < <(find "${FILE_DIR}" -type f -iname "*.${ext}" -print0)
done
fi
# 检查是否找到视频文件
if [ ! -s "${TEMP_FILE}" ]; then
echo "错误:文件夹 '${FILE_DIR}' 中没有找到支持的视频文件。"
exit 1
fi
# 按文件大小从大到小排序,并提取文件路径到数组
VIDEO_FILES=()
if [ "${FILES_SORT_BY}" = "name" ]; then
# 按文件名排序
while IFS=' ' read -r size filepath; do
VIDEO_FILES+=("${filepath}")
done < <(sort -k2 "${TEMP_FILE}")
echo "找到 ${#VIDEO_FILES[@]} 个视频文件,按文件名排序:"
else
# 按文件大小排序(默认)
while IFS=' ' read -r size filepath; do
VIDEO_FILES+=("${filepath}")
done < <(sort -nr "${TEMP_FILE}")
echo "找到 ${#VIDEO_FILES[@]} 个视频文件,按大小从大到小排序:"
fi
display_count=$((${#VIDEO_FILES[@]} > 10 ? 10 : ${#VIDEO_FILES[@]}))
for ((i=0; i<display_count; i++)); do
file_size=$(stat -c%s "${VIDEO_FILES[$i]}" 2>/dev/null)
size_mb=$((file_size / 1024 / 1024))
if [ "${FILES_SORT_BY}" = "name" ]; then
echo "$((i + 1)). $(basename "${VIDEO_FILES[$i]}") (${size_mb}MB)"
else
echo "$((i + 1)). $(basename "${VIDEO_FILES[$i]}") (${size_mb}MB)"
fi
done
if [ ${#VIDEO_FILES[@]} -gt 10 ]; then
echo "... 还有 $((${#VIDEO_FILES[@]} - 10)) 个文件未显示"
fi
# 检查文件序号是否有效
if [ "${FILE_INDEX}" -lt 1 ] || [ "${FILE_INDEX}" -gt ${#VIDEO_FILES[@]} ]; then
echo "错误:文件序号 ${FILE_INDEX} 无效,有效范围是 1 到 ${#VIDEO_FILES[@]}"
exit 1
fi
# 获取指定序号的视频文件
NAME="${VIDEO_FILES[$((FILE_INDEX - 1))]}"
file_size=$(stat -c%s "${NAME}" 2>/dev/null)
size_mb=$((file_size / 1024 / 1024))
if [ "${FILES_SORT_BY}" = "name" ]; then
echo "选择的视频文件(按名称排序第${FILE_INDEX}个):${NAME} (${size_mb}MB)"
else
echo "选择的视频文件(按大小排序第${FILE_INDEX}个):${NAME} (${size_mb}MB)"
fi
## 处理 ISO 文件
if [[ "${NAME}" == *.iso || "${NAME}" == *.ISO ]]; then
echo "检测到 ISO 文件,正在挂载并查找视频文件..."
MOUNT_POINT="/mnt/iso"
sudo mkdir -p "${MOUNT_POINT}"
sudo umount "${MOUNT_POINT}" 2>/dev/null # 确保挂载点未被占用
sudo mount -o loop "${NAME}" "${MOUNT_POINT}"
# 查找 DVD 或蓝光视频文件,同样按大小排序
ISO_TEMP_FILE=$(mktemp)
trap "rm -f ${ISO_TEMP_FILE}" EXIT
# 查找 DVD 视频文件
while IFS= read -r -d '' video_file; do
file_size=$(stat -c%s "${video_file}" 2>/dev/null)
if [[ -z "${file_size}" ]] || ! [[ "${file_size}" =~ ^[0-9]+$ ]]; then
echo "错误:无法获取文件大小,跳过文件:${video_file}"
continue
fi
echo "${file_size} ${video_file}" >> "${ISO_TEMP_FILE}"
done < <(find "${MOUNT_POINT}/VIDEO_TS" -type f -iname "*.VOB" -print0 2>/dev/null)
# 如果没找到 DVD 文件,查找蓝光视频文件
if [ ! -s "${ISO_TEMP_FILE}" ]; then
echo "未找到 DVD 视频文件,开始查找蓝光视频文件..."
while IFS= read -r -d '' video_file; do
file_size=$(stat -c%s "${video_file}" 2>/dev/null)
if [[ -z "${file_size}" ]] || ! [[ "${file_size}" =~ ^[0-9]+$ ]]; then
echo "错误:无法获取文件大小,跳过文件:${video_file}"
continue
fi
echo "${file_size} ${video_file}" >> "${ISO_TEMP_FILE}"
done < <(find "${MOUNT_POINT}/BDMV/STREAM" -type f -iname "*.m2ts" -print0 2>/dev/null)
fi
if [ ! -s "${ISO_TEMP_FILE}" ]; then
echo "错误:未找到支持的视频文件。"
sudo umount "${MOUNT_POINT}"
exit 1
fi
# 使用最大的视频文件
NAME=$(sort -nr "${ISO_TEMP_FILE}" | head -1 | cut -d' ' -f2-)
file_size=$(stat -c%s "${NAME}" 2>/dev/null)
size_mb=$((file_size / 1024 / 1024))
echo "选择的视频文件:${NAME} (${size_mb}MB)"
fi
## 提取截图
echo "开始提取截图,起始时间:${STARTING_TIME},截图数量:${NUMBERS_PNG}"
ffmpeg -ss "${STARTING_TIME}" -i "${NAME}" -vf fps=1/20 -vframes "${NUMBERS_PNG}" "${OUTPUT_DIR}/${FILE_DIR}"-%02d.png
# 确保挂载点的挂载取消
if mountpoint -q "/mnt/iso" 2>/dev/null; then
sudo umount "/mnt/iso" 2>/dev/null
fi
## 记录日志
LOG_FILE="/root/snapshots.txt"
echo "########################################" >> "${LOG_FILE}"
echo "$(date)" >> "${LOG_FILE}"
## 处理截图文件
UPLOAD_FILES=() # 用于存储需要上传的文件
for screenshot in "${OUTPUT_DIR}/${FILE_DIR}"-*.png; do
if [ ! -f "${screenshot}" ]; then
echo "警告:截图文件不存在:${screenshot}"
continue
fi
file_size=$(stat -c%s "${screenshot}")
size_mb=$((file_size / 1024 / 1024))
echo "处理截图文件:$(basename "${screenshot}") (${size_mb}MB)"
# 如果文件大于 10MB 且启用了压缩功能,尝试压缩
if [ "${file_size}" -gt "${PNG_MAX_SIZE}" ] && ${ENABLE_COMPRESSION}; then
echo "文件 ${screenshot} 大小 ${file_size} 字节,大于 10MB,正在压缩..."
# 检查当前 API KEY 的使用次数
while true; do
CURRENT_API_KEY="${TINYPNG_API_KEYS[$CURRENT_API_KEY_INDEX]}"
USED_QUOTA=$(tinifier quota -k "${CURRENT_API_KEY}" | awk '{print $NF}'|sed 's/\x1b\[[0-9;]*m//g')
echo "当前 API KEY 使用次数:${USED_QUOTA}"
if [ "${USED_QUOTA}" -ge "${QUOTA_LIMIT}" ]; then
echo "API KEY ${CURRENT_API_KEY} 使用次数已达上限,切换到下一个 API KEY。"
CURRENT_API_KEY_INDEX=$((CURRENT_API_KEY_INDEX + 1))
if [ "${CURRENT_API_KEY_INDEX}" -ge ${#TINYPNG_API_KEYS[@]} ]; then
echo "错误:所有 API KEY 使用次数均已达到上限。"
if [[ "${NAME}" == *.iso || "${NAME}" == *.ISO ]]; then
sudo umount "/mnt/iso" 2>/dev/null
fi
exit 1
fi
else
break
fi
done
# 使用当前 API KEY 压缩文件
tinifier compress -k "${CURRENT_API_KEY}" "${screenshot}"
fi
# 将文件添加到上传列表
UPLOAD_FILES+=("${screenshot}")
done
# 批量上传文件
if [ ${#UPLOAD_FILES[@]} -gt 0 ]; then
echo "正在上传以下文件:"
printf '%s\n' "${UPLOAD_FILES[@]}"
imgbox --thumb-width 350 -t "${FILE_DIR}" "${UPLOAD_FILES[@]}" | tee -a "${LOG_FILE}"
else
echo "没有文件需要上传。"
fi
# 卸载 ISO 文件(如果存在)
if [[ "${NAME}" == *.iso || "${NAME}" == *.ISO ]]; then
sudo umount "/mnt/iso" 2>/dev/null
fi
echo "脚本执行完成!"
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment