#!/usr/bin/env bash set -Eeuo pipefail OUTPUT_DIR="video_result" FAILED_LIST="$OUTPUT_DIR/failed.txt" JOBS=2 mkdir -p "$OUTPUT_DIR" : > "$FAILED_LIST" ############################################# # 인코딩 ############################################# encode() { local input="$1" local filename name output local abr abr_k filename=$(basename "$input") name="${filename%.*}" output="$OUTPUT_DIR/$name.mp4" echo echo "▶ $filename" # 이미 존재 if [[ -f "$output" ]]; then echo " 이미 존재 -> 건너뜀" return fi ######################################### # 오디오 확인 및 옵션 구성 ######################################### local -a AUDIO_ARGS=() local -a MAP_ARGS=(-map 0:v:0) if ffprobe -v error \ -select_streams a:0 \ -show_entries stream=index \ -of csv=p=0 "$input" | grep -q .; then echo " 오디오 : 있음" abr=$(ffprobe -v error \ -select_streams a:0 \ -show_entries stream=bit_rate \ -of default=noprint_wrappers=1:nokey=1 \ "$input" || true) if [[ -z "$abr" || "$abr" == "N/A" ]]; then abr_k=112 else abr_k=$((abr / 1000)) (( abr_k < 1 )) && abr_k=112 (( abr_k > 112 )) && abr_k=112 fi AUDIO_ARGS=(-c:a aac -b:a "${abr_k}k") MAP_ARGS+=(-map 0:a:0) echo " 오디오 bitrate : ${abr_k}k" else echo " 오디오 : 없음" fi ######################################### # FFmpeg ######################################### if ffmpeg \ -hide_banner \ -loglevel warning \ -stats \ -y \ -i "$input" \ "${MAP_ARGS[@]}" \ -map_metadata 0 \ -map_metadata:s:v 0:s:v \ -vf "scale=1280:1280:force_original_aspect_ratio=decrease:force_divisible_by=2,fps=30" \ -c:v libx265 \ -preset fast \ -crf 32 \ -pix_fmt yuv420p \ -threads 0 \ -tag:v hvc1 \ "${AUDIO_ARGS[@]}" \ -movflags +faststart+use_metadata_tags \ "$output" then ##################################### # 원본 메타데이터 복사 ##################################### if exiftool \ -overwrite_original \ -tagsFromFile "$input" \ -all:all \ --unsafe \ "$output"; then # 파일 시간 보존 touch -r "$input" "$output" echo "✔ 완료" else rm -f "$output" echo "$filename" >> "$FAILED_LIST" echo "✖ 메타데이터 복사 실패" fi else rm -f "$output" echo "$filename" >> "$FAILED_LIST" echo "✖ FFmpeg 실패" fi } export -f encode export OUTPUT_DIR FAILED_LIST ############################################# # Ctrl+C ############################################# trap ' echo echo "중단됨" pkill -P $$ ffmpeg 2>/dev/null || true exit 1 ' INT ############################################# # 병렬 인코딩 ############################################# find . -maxdepth 1 -type f \ \( -iname "*.mp4" -o \ -iname "*.mov" -o \ -iname "*.mkv" -o \ -iname "*.avi" -o \ -iname "*.wmv" -o \ -iname "*.flv" -o \ -iname "*.webm" -o \ -iname "*.m4v" \) \ -print0 | xargs -0 -n1 -P "$JOBS" bash -c 'encode "$0"' ############################################# # 결과 ############################################# echo echo "========================================" SUCCESS=$(find "$OUTPUT_DIR" -maxdepth 1 -type f -name "*.mp4" | wc -l | tr -d ' ') echo "성공 : $SUCCESS" if [[ -s "$FAILED_LIST" ]]; then echo "실패 : $(wc -l < "$FAILED_LIST")" cat "$FAILED_LIST" else echo "실패 : 0" rm -f "$FAILED_LIST" fi echo "========================================"