xiandie/compress_audio.sh

68 lines
2.7 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# ==============================================================================
# WORKER SCRIPT: compress_audio.sh (v6.1 - libvorbis only, bug-fix)
# ==============================================================================
set -Eeuo pipefail
trap 'echo "❌ 发生错误 (line $LINENO)" >&2' ERR
# ---------- 可调环境变量 ----------
SOURCE_DIR="${SOURCE_DIR:-./asset/audio}"
OUTPUT_DIR="${OUTPUT_DIR:-./compressed_audio}"
BYTE_RATE_THRESHOLD="${BYTE_RATE_THRESHOLD:-60000}" # < 60 kB/s 视为已压缩
OVERWRITE="${OVERWRITE:-0}" # 0=跳过已存在
AUDIO_RATE="${AUDIO_RATE:-44100}" # Vorbis 常用 44.1 kHz
DRY_RUN="${DRY_RUN:-0}"
LOG_LEVEL="${LOG_LEVEL:-info}" # info / debug
# ---------- 固定编解码参数 ----------
OUTPUT_EXT="ogg"
ENC_OPTS="-c:a libvorbis -q:a 5" # 010, 5≈~160 kbps
# ---------- 参数检查 ----------
[[ $# -eq 0 || -z ${1:-} ]] && { echo "用法: $0 <audio-file>" >&2; exit 2; }
audio_file=$1
[[ ! -f $audio_file ]] && { echo "文件不存在: $audio_file" >&2; exit 2; }
# ---------- 辅助 ----------
log(){ [[ $LOG_LEVEL == debug || $1 != debug ]] && echo "[$1] $2" >&2; }
get_size(){ [[ $(uname) == Darwin ]] && stat -f%z "$1" || stat -c%s "$1"; }
# ---------- 输出路径 ----------
relative="${audio_file#$SOURCE_DIR/}"
base="${relative%.*}"
output="$OUTPUT_DIR/${base}.${OUTPUT_EXT}"
# ---------- 跳过已存在 ----------
if [[ $OVERWRITE -eq 0 && -f $output ]]; then
log info "SKIP(已存在): $output"; exit 2; fi
# ---------- 获取时长 ----------
duration=$(ffprobe -v error -show_entries format=duration \
-of default=noprint_wrappers=1:nokey=1 "$audio_file" | head -n1)
if [[ -z $duration || $(awk "BEGIN{print ($duration<=0)}") -eq 1 ]]; then
log info "SKIP(无效): $audio_file"; exit 2; fi
# ---------- 获取比特率 ----------
bitrate=$(ffprobe -v error -select_streams a:0 -show_entries stream=bit_rate \
-of default=noprint_wrappers=1:nokey=1 "$audio_file" | head -n1)
# 某些文件无 bit_rate回退到 size/duration
if [[ -z $bitrate || $bitrate == N/A || $bitrate == 0 ]]; then
size=$(get_size "$audio_file")
bitrate=$(awk "BEGIN{printf \"%.0f\", $size/$duration}")
fi
if (( bitrate < BYTE_RATE_THRESHOLD )); then
log info "SKIP(已压缩, ${bitrate}B/s): $audio_file"; exit 2; fi
[[ $DRY_RUN -eq 1 ]] && { log info "DRY-RUN: $audio_file$output"; exit 0; }
mkdir -p "$(dirname "$output")"
log info "COMPRESS → $output"
ffmpeg -hide_banner -loglevel error -y \
-i "$audio_file" -vn -sn $ENC_OPTS -ar "$AUDIO_RATE" -map_metadata -1 \
"$output" \
&& { log info "SUCCESS"; exit 0; } \
|| { log info "FAILED"; exit 1; }