試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

zoomeとSMILEVIDEO向けの動画エンコード支援スクリプトを更新(2009/11/30版)

(2009/12/25)本記事のバージョンは古く、新しいバージョンを「zoomeとSMILEVIDEO向けの動画エンコード支援スクリプトを更新(2009/12/25版)」に貼り付けている。以下、以前の内容。
以前「zoomeとSMILEVIDEOへアップロードする動画のエンコードに関する追加メモ(2009/8/28現在)」で作成した(H.264 + AAC).mp4な動画ファイルへのエンコード支援スクリプトについて、以下の点を改善した。

  • エンコード処理の出力をログファイル(encode-video-[ファイル名]-[日付].log)へ出力するようにした
  • オプション(-m)指定により、処理中のログをXの端末エミュレータ内のtailコマンドで参照できるようにした(映像エンコードの進行状況も、端末でそのまま実行するのと同様にリアルタイム更新される)
  • オプション(-1)指定により映像の1Passエンコードができるようにした
  • 映像2Passエンコード時、2Pass目のエンコード中に停止して止めた場合向けに1回目のエンコード後に一時ディレクトencode-video-[文字列]/内に生成された*12pass.logの場所をオプション(-p)で指定することでこれを再利用し、2Pass目から開始できるようにした

その他、-sオプションで開始位置の指定もできるようにはしたが、音ズレの原因となる場合もあるため、あまり役には立たないかも知れない。一方で以前から用意している終了位置指定の-tオプションはほぼ同じ位置で映像と音声が切れる。
スクリプトは以前と同様SMILEVIDEO用とzoome用を分けているが、違いは既定のビットレート値だけで、このビットレートを含め、幾つかの指定はオプションでいじれるようにしてある。
長さや内容によってオプション指定で適切な値を指定して使用する。
なお、今回もまだどこかスクリプトにおかしい部分が残っている可能性がある。

  1. SMILEVIDEO向け
  2. zoome向け

SMILEVIDEO向け

既定の設定では

としたが、動画の長さや用途など、必要に応じて値はオプション指定で調整する。
[任意]ファイル名: encode-video-smilevideo-20091130.sh

#! /bin/bash

# (H.264 + AAC).mp4 encode support script
# version 20091130
# (C) 2009 kakurasan
# Licensed under GPL-3

PATH=/bin:/usr/bin

BITRATE_AUDIO=96
BITRATE_VIDEO=512
FPS=30

TMP_VIDEO=video.264
TMP_AUDIO=audio.aac
OUTFILE=output.mp4
PASSLOGFILE=2pass.log

print_usage()
{
  printf "Usage: %s ( [OPTIONS...] ) INPUT
  -1               1pass video encode
  -b BITRATE       use BITRATE for audio (default: %d)
  -c WIDTH:HEIGHT  scale to WIDTHxHEIGHT
  -f FPS           set frame rate to FPS (default: %d)
  -h               print help
  -i BITRATE       use BITRATE for video (default: %d)
  -m TERM          display log using TERM (X terminal emulator)
  -p PASSLOGFILE   start from 2nd pass (video) using PASSLOGFILE
  -r W:H:X:Y       crop (size:WxH, pos:X,Y)
  -s POS           seek to POS
  -t DURATION      set DURATION(hh:mm:ss)
  -v               video only
  -x OPTION...     set extra x264 options
" ${0} ${BITRATE_AUDIO} ${FPS} ${BITRATE_VIDEO}
}

SCALE=0
USE_X264_EXTRA_OPTS=0
SET_DURATION=0
VIDEOONLY=0
VIDEO_1PASS=0
SKIP_1STPASS_VIDEO=0
POS=0
CROP=0
USE_XTERM=0
while getopts '1b:c:f:hi:m:p:r:s:t:vx:' OPT
do
  case ${OPT} in
   1)
    VIDEO_1PASS=1
    ;;
   b)
    BITRATE_AUDIO=${OPTARG}
    ;;
   c)
    SCALE=1
    SIZE=${OPTARG}
    ;;
   f)
    FPS=${OPTARG}
    ;;
   i)
    BITRATE_VIDEO=${OPTARG}
    ;;
   m)
    USE_XTERM=1
    TERMINAL=${OPTARG}
    ;;
   p)
    SKIP_1STPASS_VIDEO=1
    PASSLOGFILE=${OPTARG}
    if [ ! -f ${PASSLOGFILE} ]; then
      echo "Cannot open \"${PASSLOGFILE}\""
      exit 1
    fi
    PASSLOGFILE=$(cd $(dirname ${PASSLOGFILE}) && pwd)/$(basename ${PASSLOGFILE})  # rel.p->abs.p
    ;;
   r)
    CROP=1
    CROPPARAMS=${OPTARG}
    ;;
   s)
    POS=${OPTARG}
    ;;
   t)
    SET_DURATION=1
    DURATION=${OPTARG}
    ;;
   v)
    VIDEOONLY=1
    ;;
   x)
    USE_X264_EXTRA_OPTS=1
    X264_EXTRA_OPTS=${OPTARG}
    ;;
   ?)
    print_usage
    exit 1
    ;;
  esac
done
shift $((${OPTIND} - 1))
if [ ${#} -lt 1 ]; then
  print_usage
  exit 1
fi
INFILE="${1}"
if [ ! -f "${INFILE}" ]; then
  echo "input file \"${INFILE}\" not found."
  exit 1
fi

LOGFILE="$(printf ../encode-video-%s-%s.log "$(basename "${INFILE}")" $(date +%Y%m%d%H%M%S))"

TMPDIR=$(mktemp -d encode-video.XXXXXXXX)
if [ ${?} -ne 0 ]; then
  echo "cannot create tempdir"
  exit 1
fi
INFILE="$(cd $(dirname "${INFILE}") && pwd)/$(basename "${INFILE}")"
cd ${TMPDIR}

X264OPTS="bitrate=${BITRATE_VIDEO}:bframes=4:b_pyramid:me=umh:weight_b:frameref=6:nofast_pskip:nodct_decimate"
if [ ${USE_X264_EXTRA_OPTS} -eq 1 ]; then
  X264OPTS=${X264OPTS}:${X264_EXTRA_OPTS}
fi

MENCODER="mencoder"
FFMPEG="ffmpeg"
MP4BOX="MP4Box"
if [ ${SET_DURATION} -eq 1 ]; then
  MENCODER="${MENCODER} -endpos ${DURATION}"
  FFMPEG="${FFMPEG} -t ${DURATION}"
fi
if [ ${SCALE} -eq 1 ]; then
  VFOPTS="scale=${SIZE},harddup"
else
  VFOPTS="harddup"
fi
if [ ${CROP} -eq 1 ]; then
  VFOPTS="${VFOPTS},crop=${CROPPARAMS}"
fi
MENCODEROPT_COMMON="-ss ${POS} -nosound -ovc x264 -vf ${VFOPTS} -ofps ${FPS}"
CMD_VIDEO="${MENCODER} ${MENCODEROPT_COMMON} -x264encopts ${X264OPTS}:subq=7 ${INFILE} -of rawvideo -o ${TMP_VIDEO}"
CMD_VIDEO1="${MENCODER} ${MENCODEROPT_COMMON} -passlogfile ${PASSLOGFILE} -x264encopts ${X264OPTS}:pass=1:turbo=1 ${INFILE} -of rawvideo -o /dev/null"
CMD_VIDEO2="${MENCODER} ${MENCODEROPT_COMMON} -passlogfile ${PASSLOGFILE} -x264encopts ${X264OPTS}:pass=2:subq=7 ${INFILE} -of rawvideo -o ${TMP_VIDEO}"
CMD_AUDIO="${FFMPEG} -ss ${POS} -i ${INFILE} -y -vn -acodec libfaac -ab ${BITRATE_AUDIO}k ${TMP_AUDIO}"

exec 3> >(zenity --notification --listen ${ICON:+--window-icon }${ICON:-})
touch "${LOGFILE}"
if [ ${USE_XTERM} -eq 1 ]; then
  ${TERMINAL} -e tail -f "${LOGFILE}" &
  PID=${!}
fi
if [ ${VIDEO_1PASS} -eq 1 ]; then
  # 1pass
  echo "tooltip: ${CMD_VIDEO}" >&3
  echo ${CMD_VIDEO} >> "${LOGFILE}"
  ${CMD_VIDEO} >> "${LOGFILE}" 2>&1 || exit 1
  echo "message: video: done" >&3
else
  # 2pass
  if [ ${SKIP_1STPASS_VIDEO} -eq 0 ]; then
    # pass#1
    echo "tooltip: ${CMD_VIDEO1}" >&3
    echo ${CMD_VIDEO1} >> "${LOGFILE}"
    ${CMD_VIDEO1} >> "${LOGFILE}" 2>&1 || exit 1
    echo "message: video pass 1 / 2 done" >&3
  fi
  # pass#2
  echo "tooltip: ${CMD_VIDEO2}" >&3
  echo ${CMD_VIDEO2} >> "${LOGFILE}" 2>&1
  ${CMD_VIDEO2} >> "${LOGFILE}" 2>&1 || exit 1
  echo "message: video: pass 2 / 2 done" >&3
fi
if [ ${VIDEOONLY} -eq 0 ]; then
  echo "tooltip: ${CMD_AUDIO}" >&3
  echo ${CMD_AUDIO} >> "${LOGFILE}"
  ${CMD_AUDIO} >> "${LOGFILE}" 2>&1 || exit 1
  echo "message: audio: done" >&3
  ${MP4BOX} -fps ${FPS} -add ${TMP_VIDEO} -add ${TMP_AUDIO} -new ../${OUTFILE} >> "${LOGFILE}" 2>&1
else
  ${MP4BOX} -fps ${FPS} -add ${TMP_VIDEO} -new ../${OUTFILE} >> "${LOGFILE}" 2>&1
fi
echo "message: mp4: done" >&3
if [ ${USE_XTERM} -eq 1 ]; then
  kill ${PID}
fi
cd ..
rm ${TMPDIR} -fr

zoome向け

既定の設定では

としたが、映像ビットレートが高くなりすぎないように注意。
[任意]ファイル名: encode-video-zoome-20091130.sh

#! /bin/bash

# (H.264 + AAC).mp4 encode support script
# version 20091130
# (C) 2009 kakurasan
# Licensed under GPL-3

PATH=/bin:/usr/bin

BITRATE_AUDIO=128
BITRATE_VIDEO=1344
FPS=30

TMP_VIDEO=video.264
TMP_AUDIO=audio.aac
OUTFILE=output.mp4
PASSLOGFILE=2pass.log

print_usage()
{
  printf "Usage: %s ( [OPTIONS...] ) INPUT
  -1               1pass video encode
  -b BITRATE       use BITRATE for audio (default: %d)
  -c WIDTH:HEIGHT  scale to WIDTHxHEIGHT
  -f FPS           set frame rate to FPS (default: %d)
  -h               print help
  -i BITRATE       use BITRATE for video (default: %d)
  -m TERM          display log using TERM (X terminal emulator)
  -p PASSLOGFILE   start from 2nd pass (video) using PASSLOGFILE
  -r W:H:X:Y       crop (size:WxH, pos:X,Y)
  -s POS           seek to POS
  -t DURATION      set DURATION(hh:mm:ss)
  -v               video only
  -x OPTION...     set extra x264 options
" ${0} ${BITRATE_AUDIO} ${FPS} ${BITRATE_VIDEO}
}

SCALE=0
USE_X264_EXTRA_OPTS=0
SET_DURATION=0
VIDEOONLY=0
VIDEO_1PASS=0
SKIP_1STPASS_VIDEO=0
POS=0
CROP=0
USE_XTERM=0
while getopts '1b:c:f:hi:m:p:r:s:t:vx:' OPT
do
  case ${OPT} in
   1)
    VIDEO_1PASS=1
    ;;
   b)
    BITRATE_AUDIO=${OPTARG}
    ;;
   c)
    SCALE=1
    SIZE=${OPTARG}
    ;;
   f)
    FPS=${OPTARG}
    ;;
   i)
    BITRATE_VIDEO=${OPTARG}
    ;;
   m)
    USE_XTERM=1
    TERMINAL=${OPTARG}
    ;;
   p)
    SKIP_1STPASS_VIDEO=1
    PASSLOGFILE=${OPTARG}
    if [ ! -f ${PASSLOGFILE} ]; then
      echo "Cannot open \"${PASSLOGFILE}\""
      exit 1
    fi
    PASSLOGFILE=$(cd $(dirname ${PASSLOGFILE}) && pwd)/$(basename ${PASSLOGFILE})  # rel.p->abs.p
    ;;
   r)
    CROP=1
    CROPPARAMS=${OPTARG}
    ;;
   s)
    POS=${OPTARG}
    ;;
   t)
    SET_DURATION=1
    DURATION=${OPTARG}
    ;;
   v)
    VIDEOONLY=1
    ;;
   x)
    USE_X264_EXTRA_OPTS=1
    X264_EXTRA_OPTS=${OPTARG}
    ;;
   ?)
    print_usage
    exit 1
    ;;
  esac
done
shift $((${OPTIND} - 1))
if [ ${#} -lt 1 ]; then
  print_usage
  exit 1
fi
INFILE="${1}"
if [ ! -f "${INFILE}" ]; then
  echo "input file \"${INFILE}\" not found."
  exit 1
fi

LOGFILE="$(printf ../encode-video-%s-%s.log "$(basename "${INFILE}")" $(date +%Y%m%d%H%M%S))"

TMPDIR=$(mktemp -d encode-video.XXXXXXXX)
if [ ${?} -ne 0 ]; then
  echo "cannot create tempdir"
  exit 1
fi
INFILE="$(cd $(dirname "${INFILE}") && pwd)/$(basename "${INFILE}")"
cd ${TMPDIR}

X264OPTS="bitrate=${BITRATE_VIDEO}:bframes=4:b_pyramid:me=umh:weight_b:frameref=6:nofast_pskip:nodct_decimate"
if [ ${USE_X264_EXTRA_OPTS} -eq 1 ]; then
  X264OPTS=${X264OPTS}:${X264_EXTRA_OPTS}
fi

MENCODER="mencoder"
FFMPEG="ffmpeg"
MP4BOX="MP4Box"
if [ ${SET_DURATION} -eq 1 ]; then
  MENCODER="${MENCODER} -endpos ${DURATION}"
  FFMPEG="${FFMPEG} -t ${DURATION}"
fi
if [ ${SCALE} -eq 1 ]; then
  VFOPTS="scale=${SIZE},harddup"
else
  VFOPTS="harddup"
fi
if [ ${CROP} -eq 1 ]; then
  VFOPTS="${VFOPTS},crop=${CROPPARAMS}"
fi
MENCODEROPT_COMMON="-ss ${POS} -nosound -ovc x264 -vf ${VFOPTS} -ofps ${FPS}"
CMD_VIDEO="${MENCODER} ${MENCODEROPT_COMMON} -x264encopts ${X264OPTS}:subq=7 ${INFILE} -of rawvideo -o ${TMP_VIDEO}"
CMD_VIDEO1="${MENCODER} ${MENCODEROPT_COMMON} -passlogfile ${PASSLOGFILE} -x264encopts ${X264OPTS}:pass=1:turbo=1 ${INFILE} -of rawvideo -o /dev/null"
CMD_VIDEO2="${MENCODER} ${MENCODEROPT_COMMON} -passlogfile ${PASSLOGFILE} -x264encopts ${X264OPTS}:pass=2:subq=7 ${INFILE} -of rawvideo -o ${TMP_VIDEO}"
CMD_AUDIO="${FFMPEG} -ss ${POS} -i ${INFILE} -y -vn -acodec libfaac -ab ${BITRATE_AUDIO}k ${TMP_AUDIO}"

exec 3> >(zenity --notification --listen ${ICON:+--window-icon }${ICON:-})
touch "${LOGFILE}"
if [ ${USE_XTERM} -eq 1 ]; then
  ${TERMINAL} -e tail -f "${LOGFILE}" &
  PID=${!}
fi
if [ ${VIDEO_1PASS} -eq 1 ]; then
  # 1pass
  echo "tooltip: ${CMD_VIDEO}" >&3
  echo ${CMD_VIDEO} >> "${LOGFILE}"
  ${CMD_VIDEO} >> "${LOGFILE}" 2>&1 || exit 1
  echo "message: video: done" >&3
else
  # 2pass
  if [ ${SKIP_1STPASS_VIDEO} -eq 0 ]; then
    # pass#1
    echo "tooltip: ${CMD_VIDEO1}" >&3
    echo ${CMD_VIDEO1} >> "${LOGFILE}"
    ${CMD_VIDEO1} >> "${LOGFILE}" 2>&1 || exit 1
    echo "message: video pass 1 / 2 done" >&3
  fi
  # pass#2
  echo "tooltip: ${CMD_VIDEO2}" >&3
  echo ${CMD_VIDEO2} >> "${LOGFILE}" 2>&1
  ${CMD_VIDEO2} >> "${LOGFILE}" 2>&1 || exit 1
  echo "message: video: pass 2 / 2 done" >&3
fi
if [ ${VIDEOONLY} -eq 0 ]; then
  echo "tooltip: ${CMD_AUDIO}" >&3
  echo ${CMD_AUDIO} >> "${LOGFILE}"
  ${CMD_AUDIO} >> "${LOGFILE}" 2>&1 || exit 1
  echo "message: audio: done" >&3
  ${MP4BOX} -fps ${FPS} -add ${TMP_VIDEO} -add ${TMP_AUDIO} -new ../${OUTFILE} >> "${LOGFILE}" 2>&1
else
  ${MP4BOX} -fps ${FPS} -add ${TMP_VIDEO} -new ../${OUTFILE} >> "${LOGFILE}" 2>&1
fi
echo "message: mp4: done" >&3
if [ ${USE_XTERM} -eq 1 ]; then
  kill ${PID}
fi
cd ..
rm ${TMPDIR} -fr

使用したバージョン:

  • MPlayer,MEncoder 1.0-1.rc3.0.r29554.3.1plf2010.0
  • FFmpeg 0.5-2plf2010.0
  • libfaac 1.28-3plf2010.0
  • libx264 0.65.2245-1plf2009.1
  • GPAC 0.4.5-1plf2009.1

*1:正常に終了した場合は一時ディレクトリ以下を自動的に消すようにしているが、途中で失敗したり止めたりした場合は一時ディレクトリとその中の一時ファイルは残すようにしている