YouTube に高音質でアップロードできる動画ファイルを作るシェル・スクリプト (改良 MEncoder 版)
2008-02-17 追記
- OFPS が指定されない場合のエラーを直した。
改良した
ウェブをさまよってて MEncoder で 2 パス・エンコードする方法がわかったので、"YouTube に高音質でアップロードできる動画ファイルを作るシェル・スクリプト - だらりな。" で書いたシェル・スクリプトをアップデート (ちなみに、ほぼニコニコ動画の転載専用であることに変わりはなし)。他にもいろいろ改良した。
- MEncoder だけで OK なようにした (前のは FFmpeg も使ってた)。
- 画質の良くなるエンコード・オプションをつけた (公式ドキュメントの "6.1. Selecting codecs and container formats" の一番下に書いてるやつ)。文字が微妙に読みやすくなったりする感じ。
- 画質が良くなったかどうかは確認できないけど、なんとなく 3 パス・エンコードするようにした。
- YouTube はアスペクト比 16:9 の FLV ファイルでも 4:3 で再生しちゃう (縦長になる) みたいなので (sm1852802 で気づいた)、自動で上下に黒い部分を足して 4:3 にするようにした。
- アスペクト比が設定されてる場合も対応できるようにした (つもりだ) けど、そもそも FLV ファイルではアスペクト比の指定はできないのかもしれない。
静止映像の動画でもシークできるように、10 秒に 1 度はキー・フレームが入るようにした。関係なかった。どうやればシークできるようになるんだろ。- いろいろメッセージを出すようにした。
- しかし、どんくさいシェル・スクリプトであることには変わりなし。非整数の計算方法がわからなかったので、文字列操作で小数点を取り除くとかむちゃくちゃやってる。*1
エンコード例はこんな感じ (結局 The Idolm@ster のリミックスものをエンコードしてる……)。
ところで、YouTube のプレイヤーはデブロッキング・フィルタが入ってるのか (ていうか、それがたぶんふつうなのか)。フィルタを全部はずした MPlayer で見たら、もっとブロック・ノイズが目立ってた。
どんくさいシェル・スクリプト
設定を別ファイルに分離した。いろいろ自動化しても、ある程度は動画ごとにいじる必要があるし。
#! /bin/sh source ${HOME}/bin/mencoder-youtube.conf MSG_PREFIX="[MEncoder for YouTube] " # # Probe # INPUT_FILE=`echo $1 | sed -e 's/"/\\"/g' -e 's/!/\\!/g'` if [ ! -f "${INPUT_FILE}" ]; then echo "${MSG_PREFIX}Can't find \"${INPUT_FILE}\"" >&2 exit 1 fi OUTPUT_FILE=`basename "${INPUT_FILE}" | sed "s/\w\+$/forYouTube.flv/"` INPUT_AUDIO_FILE=`echo "${INPUT_FILE}" | sed "s/\w\+$/mp3/"` if [ -f "${INPUT_AUDIO_FILE}" ]; then echo "${MSG_PREFIX}Found \"${INPUT_AUDIO_FILE}\"" else INPUT_AUDIO_FILE=${INPUT_FILE} fi probe () { PROBE_DATA=`mplayer -vo null -ao null -frames 0 -identify "$1" 2> /dev/null | grep -e "$2"` eval ${PROBE_DATA} } probe "${INPUT_AUDIO_FILE}" "^ID_AUDIO" AUDIO_BITRATE=`expr ${ID_AUDIO_BITRATE} / 1000` VIDEO_BITRATE=`expr ${TOTAL_BITRATE} - ${AUDIO_BITRATE}` echo "${MSG_PREFIX}AUDIO_BITRATE: ${AUDIO_BITRATE}; VIDEO_BITRATE: ${VIDEO_BITRATE}" #exit 0 probe "${INPUT_FILE}" "^ID_VIDEO" [ ! ${WIDTH} ] && WIDTH=${ID_VIDEO_WIDTH} ID_VIDEO_ASPECT_X10000=`echo ${ID_VIDEO_ASPECT} | sed "s/\.//"` if [ ${ID_VIDEO_ASPECT_X10000} -eq 0 ]; then SCALE_HEIGHT=`expr ${ID_VIDEO_HEIGHT} \* ${WIDTH} / ${ID_VIDEO_WIDTH}` else SCALE_HEIGHT=`expr ${WIDTH} \* ${ID_VIDEO_ASPECT_X10000} / 10000` fi EXPAND_HEIGHT=`expr ${WIDTH} \* 3 / 4` [ ! ${OFPS} ] && OFPS=${ID_VIDEO_FPS} echo "${MSG_PREFIX}WIDTH: ${WIDTH}; SCALE_HEIGHT: ${SCALE_HEIGHT}; EXPAND_HEIGHT: ${EXPAND_HEIGHT}; OFPS: ${OFPS}" #exit 0 # # Encode # MSGLEVEL="all=1" VF="${VF_PP}scale=${WIDTH}:${SCALE_HEIGHT},expand=${WIDTH}:${EXPAND_HEIGHT}" #VF="${VF_PP}scale=320:180,expand=320:240" OFPS_INT=`echo ${OFPS} | sed "s/\..*//"`; KEYINT=":keyint=`expr ${OFPS_INT} \* 10`" LAVCOPTS="vcodec=flv:vbitrate=${VIDEO_BITRATE}:mbd=2:mv0:trell:v4mv:cbp:last_pred=3${KEYINT}" PASSLOGFILE="mencoder-youtube-pass.log" encode () { mencoder -msglevel ${MSGLEVEL} -of lavf -oac copy -ovc lavc -ofps ${OFPS} -vf ${VF} -lavcopts ${LAVCOPTS}:vpass=$1 -passlogfile ${PASSLOGFILE}\ -o "${OUTPUT_FILE}" -audiofile "${INPUT_AUDIO_FILE}" "${INPUT_FILE}" } echo "${MSG_PREFIX}Encoding \"${INPUT_FILE}\" (pass 1/3)" encode 1 echo "${MSG_PREFIX}Encoding \"${INPUT_FILE}\" (pass 2/3)" encode 3 echo "${MSG_PREFIX}Encoding \"${INPUT_FILE}\" (pass 3/3)" encode 3 OUTPUT_FILE_SIZE_BYTE=`ls -l "${OUTPUT_FILE}" | cut -d " " -f 5` OUTPUT_FILE_SIZE_BIT_X100=`expr ${OUTPUT_FILE_SIZE_BYTE} \* 8 \* 100` probe "${OUTPUT_FILE}" "^ID_LENGTH" OUTPUT_FILE_LENGTH_X100=`echo ${ID_LENGTH} | sed "s/\.//"` echo "${MSG_PREFIX}TOTAL_BITRATE: `expr ${OUTPUT_FILE_SIZE_BIT_X100} / ${OUTPUT_FILE_LENGTH_X100}` bps" [ -f ${PASSLOGFILE} ] && rm ${PASSLOGFILE} exit 0
設定用ファイル。WIDTH と OFPS については、全部コメントアウトすると元動画の設定を読む。
TOTAL_BITRATE=340 #TOTAL_BITRATE=244 # 音声 128000 bps なのに 32000 bps と自己申請する動画用 #TOTAL_BITRATE=276 # 音声 96000 bps なのに 32000 bps と自己申請する動画用 WIDTH=320 #OFPS=1 # 静止映像動画でビットレートをかせぎたいとき用 #OFPS=7 #OFPS=10 #OFPS=12 OFPS=15 #VF_PP="" VF_PP="pp=ac," #VF_PP="pp=md/ac," # インターレース解除してない動画用