Skip to content

Instantly share code, notes, and snippets.

@jmkim
Last active May 6, 2026 09:30
Show Gist options
  • Select an option

  • Save jmkim/6e1a49de73d2cccff7b6845efea70587 to your computer and use it in GitHub Desktop.

Select an option

Save jmkim/6e1a49de73d2cccff7b6845efea70587 to your computer and use it in GitHub Desktop.
아이리버 딕플 D7용 비디오 인코더 (mencoder XviD + MP3, 480x272, 30.000fps)
#!/bin/sh
#
# encode_d7.sh -- IRIVER D7 video encoder (mencoder, XviD+MP3, 480x272, 30fps)
#
# POSIX /bin/sh
#
# SPDX-License-Identifier: MIT
# Copyright: 2026 Jongmin Kim <jmkim@debian.org>
set -u
PROG=$(basename "$0")
# ---------------- Tunables (env로도 override 가능) --------
: "${FPS:=30.000}"
: "${WIDTH:=480}"
: "${HEIGHT:=272}"
: "${VBITRATE:=1000}" # XviD bitrate, kbps
: "${VTHREADS:=$(getconf _NPROCESSORS_ONLN 2>/dev/null \
|| nproc 2>/dev/null \
|| echo 4)}"
: "${ARATE:=44100}" # audio sample rate, Hz
: "${ABITRATE:=128}" # MP3 CBR bitrate, kbps
: "${PASSES:=2}" # 1 = single-pass, 2 = 2-pass (high quality, default)
: "${VIDEO_EXTS:=avi mp4 m4v mkv mov wmv flv webm mpg mpeg ts}"
# ----------------------------------------------------------
# 2-pass 통계 파일 정리
XVID_STATS=xvid-twopass.stats
trap 'rm -f -- "$XVID_STATS"' EXIT INT TERM
usage() {
cat <<EOF
Usage: $PROG [-h] INPUT [OUTPUT]
IRIVER D7용 비디오 인코더 (mencoder XviD + MP3, ${WIDTH}x${HEIGHT}, ${FPS}fps).
Arguments:
INPUT 입력 파일 또는 디렉토리
OUTPUT 출력 경로 (선택)
OUTPUT 결정 규칙:
INPUT이 파일일 때:
OUTPUT 미지정 -> <INPUT 부모>/<이름>.d7.avi
OUTPUT이 디렉토리 -> <OUTPUT>/<이름>.avi
OUTPUT이 파일 -> 지정 경로 그대로 사용
INPUT이 디렉토리일 때:
OUTPUT 미지정 -> <INPUT>/d7_out
OUTPUT이 디렉토리 -> 그 안에 각 영상이 <이름>.avi
Options:
-h 이 도움말을 출력하고 종료
Environment overrides (현재값):
EOF
printf ' %-14s %s\n' "FPS=$FPS" "프레임레이트"
printf ' %-14s %s\n' "WIDTH=$WIDTH" "가로 해상도 (px)"
printf ' %-14s %s\n' "HEIGHT=$HEIGHT" "세로 해상도 (px)"
printf ' %-14s %s\n' "VBITRATE=$VBITRATE" "XviD 비트레이트 (kbps)"
printf ' %-14s %s\n' "VTHREADS=$VTHREADS" "XviD 스레드 (기본: CPU 코어 수 자동 감지)"
printf ' %-14s %s\n' "ARATE=$ARATE" "오디오 샘플레이트 (Hz)"
printf ' %-14s %s\n' "ABITRATE=$ABITRATE" "MP3 CBR 비트레이트 (kbps)"
printf ' %-14s %s\n' "PASSES=$PASSES" "1 = 단일패스, 2 = 2-pass (기본, 고품질)"
printf " VIDEO_EXTS='%s'\n" "$VIDEO_EXTS"
cat <<EOF
Examples:
$PROG video.mkv
$PROG video.mkv out.avi
$PROG video.mkv outdir/
$PROG indir/ outdir/
VBITRATE=1200 $PROG video.mkv
ABITRATE=192 $PROG indir/ outdir/
EOF
}
# ---- option parsing (POSIX getopts) ----
while getopts 'h' opt; do
case "$opt" in
h) usage; exit 0 ;;
?) usage >&2; exit 2 ;;
esac
done
shift $((OPTIND - 1))
if [ $# -lt 1 ] || [ $# -gt 2 ]; then
usage >&2
exit 2
fi
INPUT=$1
OUTPUT=${2:-}
# ---- helpers ----
# 공통 mencoder 호출. $1=in, $2=out, $3=xvid extra (예: pass=1), $4=audio(yes|no)
# 서브쉘 함수: 내부 변수 할당이 호출자에게 누출되지 않도록.
run_mencoder() (
_in=$1
_out=$2
_xvid_extra=$3
_audio=$4
if [ -n "$_xvid_extra" ]; then
_xvid="threads=${VTHREADS}:${_xvid_extra}:bitrate=${VBITRATE}"
else
_xvid="threads=${VTHREADS}:bitrate=${VBITRATE}"
fi
set -- "$_in" -o "$_out" \
-mc 0 \
-audio-preload 0.0 \
-noodml \
-ofps "$FPS" \
-vf-add "dsize=${WIDTH}:${HEIGHT}:0" \
-vf-add "scale=0:0" \
-vf-add "expand=${WIDTH}:${HEIGHT}:-1:-1:1" \
-ovc xvid \
-xvidencopts "$_xvid"
if [ "$_audio" = yes ]; then
set -- "$@" \
-srate "$ARATE" \
-oac mp3lame \
-lameopts "cbr:br=${ABITRATE}:mode=1:aq=0:padding=3"
else
set -- "$@" -nosound
fi
mencoder "$@"
)
encode_one() {
_in=$1
_out=$2
if [ "$PASSES" = 2 ]; then
printf '==> %s [pass 1/2 analyze]\n' "$_in"
run_mencoder "$_in" /dev/null pass=1 no || return $?
printf ' -> %s [pass 2/2 encode]\n' "$_out"
run_mencoder "$_in" "$_out" pass=2 yes
else
printf '==> %s\n -> %s\n' "$_in" "$_out"
run_mencoder "$_in" "$_out" '' yes
fi
}
# basename에서 확장자만 .avi 로 교체
to_avi_name() {
_n=$(basename "$1")
case "$_n" in
*.*) printf '%s.avi\n' "${_n%.*}" ;;
*) printf '%s.avi\n' "$_n" ;;
esac
}
# 비디오 확장자인지 (대소문자 무시, $VIDEO_EXTS 기준)
is_video_file() {
_n=$(basename "$1")
case "$_n" in
*.*) _ext=${_n##*.} ;;
*) return 1 ;;
esac
# to lower
_ext=$(printf '%s' "$_ext" | tr '[:upper:]' '[:lower:]')
for _e in $VIDEO_EXTS; do
[ "$_ext" = "$_e" ] && return 0
done
return 1
}
check_mencoder() {
command -v mencoder >/dev/null 2>&1 && return 0
{
printf 'Error: mencoder가 설치되어 있지 않습니다.\n\n'
printf '설치 방법:\n'
if command -v apt >/dev/null 2>&1; then
printf ' Debian/Ubuntu : sudo apt install mencoder\n'
elif command -v dnf >/dev/null 2>&1; then
printf ' Fedora/RHEL : sudo dnf install mencoder # RPM Fusion 활성화 필요\n'
elif command -v zypper >/dev/null 2>&1; then
printf ' openSUSE : sudo zypper install mplayer\n'
elif command -v pacman >/dev/null 2>&1; then
printf ' Arch Linux : yay -S mplayer-vaapi # 공식 저장소에서 제외됨, AUR 사용\n'
elif command -v xbps-install >/dev/null 2>&1; then
printf ' Void Linux : sudo xbps-install -S mplayer\n'
elif command -v emerge >/dev/null 2>&1; then
printf ' Gentoo : sudo emerge media-video/mplayer\n'
elif command -v nix-env >/dev/null 2>&1; then
printf ' NixOS : nix-env -iA nixpkgs.mplayer\n'
elif command -v apk >/dev/null 2>&1; then
printf ' Alpine : sudo apk add mplayer\n'
elif [ "$(uname -s)" = Darwin ] && command -v brew >/dev/null 2>&1; then
printf ' macOS (brew) : brew install mplayer\n'
elif command -v brew >/dev/null 2>&1; then
printf ' Homebrew : brew install mplayer\n'
else
printf ' 패키지 매니저를 자동 감지하지 못했습니다.\n'
printf ' http://www.mplayerhq.hu/ 에서 빌드된 mencoder를 받거나\n'
printf ' 사용 배포판의 패키지 매니저로 mplayer/mencoder를 설치하세요.\n'
fi
} >&2
exit 127
}
# ---- dispatch ----
check_mencoder
rc=0
if [ -f "$INPUT" ]; then
if [ -z "$OUTPUT" ]; then
_dir=$(dirname "$INPUT")
_name=$(basename "$INPUT")
case "$_name" in
*.*) _stem=${_name%.*} ;;
*) _stem=$_name ;;
esac
OUTPUT="${_dir}/${_stem}.d7.avi"
elif [ -d "$OUTPUT" ]; then
OUTPUT="${OUTPUT%/}/$(to_avi_name "$INPUT")"
fi
encode_one "$INPUT" "$OUTPUT" || rc=$?
elif [ -d "$INPUT" ]; then
if [ -z "$OUTPUT" ]; then
OUTPUT="${INPUT%/}/d7_out"
fi
if [ -e "$OUTPUT" ] && [ ! -d "$OUTPUT" ]; then
printf 'Error: INPUT은 디렉토리지만 OUTPUT이 디렉토리가 아닙니다: %s\n' "$OUTPUT" >&2
exit 1
fi
mkdir -p "$OUTPUT" || exit 1
ok=0
fail=0
for f in "$INPUT"/*; do
[ -f "$f" ] || continue
is_video_file "$f" || continue
out="${OUTPUT%/}/$(to_avi_name "$f")"
if encode_one "$f" "$out"; then
ok=$((ok + 1))
else
fail=$((fail + 1))
rc=1
fi
done
if [ "$ok" -eq 0 ] && [ "$fail" -eq 0 ]; then
printf 'Warning: %s 안에 비디오 파일이 없습니다.\n' "$INPUT" >&2
fi
printf 'Done. success=%d failed=%d\n' "$ok" "$fail"
else
printf 'Error: INPUT 경로가 없거나 파일/디렉토리가 아닙니다: %s\n' "$INPUT" >&2
exit 1
fi
exit "$rc"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment