YouTube に高音質でアップロードできる動画ファイルを作るシェル・スクリプト

YouTube で再エンコードされないための条件

Vocaloid を使用して作られてるオリジナル曲を、ニコニコ動画から YouTube にかなり聴ける音質で転載してくれてる人たちがいるので、それを利用させてもらって Rimo にチャンネルを作ったりしてるのだけど ("Best of Vocaloid Original Songs" とか)、自分の好きな曲で転載されないものがあったりして、ちょっと歯がゆい思いをしてたのだった。
しかたがないので自分でやってみようかと、YouTube で再エンコードされない条件を Google してみたら、あっさり見つかった。

映像と音声、あわせて 340 kbps ぐらいまでなら OK らしい。
YouTube もそろそろ H.264 + HE-AAC に対応するんじゃないかという今日このごろ、微妙な時期ではあるけど試してみることにした。

試してみた

試してみたら、うまくいったぽい (2008-02-16 追記: 以下の動画は再エンコード版に差し替え済み。旧版はそのうち消すので。画質はわかるかわからないかぐらいに良くなった程度)。

気がつくと、Vocaloid 関連じゃなく The Idolm@ster 関連のリミックスをエンコードしてたけど、それはそれ。The Idolm@ster 関連も著作権者に怒られないぽいし、このリミックス、まともな音質のが YouTube に見つからなかったから (The Idolm@ster がすごいブームだったのはちょっと前だから、今後これをアップロードする人もいなさげだし)。
完全に音質重視で、音声は "http://blog.livedoor.jp/imoutoid/archives/50658756.html" からダウンロードできる MP3 に差し替え、映像は 15 fps、320 x 240 でエンコードした。
ところで、リミキサーの imoutoid 氏は最近 "STUDIO VOICE" 誌に載ったらしい。

作ったシェル・スクリプト

どんくさいシェル・スクリプトを書いてエンコードした。

  • /path/to/<入力ファイル> を引数に実行して、カレント・ディレクトリに YouTube へのアップロード用ファイルを出力。ただし、再エンコードされない保証はなし。
  • 入力ファイルの音声コーデックは MP3 であることを前提にしてて (手抜き)、それを再エンコードなしでコピーするようにした。
  • 入力ファイルと同名の MP3 ファイル (拡張子だけがちがうもの) が入力ファイルと同じディレクトリにあれば、それを利用するようにした。
  • FFmpegMEncoder、どっちかだけで OK なようにしようと思ったのだけど、FFmpeg では外部の音声ファイルを利用する方法がわからず、MEncoder では 2 パス・エンコードする方法がわからず、やむなく両方使った。
  • ややこしいオプションとかわからないので、そういうのは一切なし。
  • 入力ファイル名の処理がいいかげん。

以下が、そのどんくさいシェル・スクリプト

#! /bin/sh

#
# Config
#

TOTAL_BITRATE=340000

#FPS=1
#FPS=7
#FPS=12
FPS=15

#WIDTHxHEIGHT=""
#WIDTHxHEIGHT="-s 240x180"
#WIDTHxHEIGHT="-s 280x210"
WIDTHxHEIGHT="-s 320x240"

#
# Probe
#

INPUT_FILE=`echo ${1} | sed -e 's/"/\\"/g' -e 's/!/\\!/g'`
if [ ! -f "${INPUT_FILE}" ]; then
	echo "Can't find \"${INPUT_FILE}\"" >&2 
	exit 1
fi
OUTPUT_FILE=`basename "${INPUT_FILE}" | sed "s/\w\+$/forYouTube.flv/"`
OUTPUT_FILE_NEW_AUDIO=`basename "${INPUT_FILE}" | sed "s/\w\+$/forYouTube.NewAudio.flv/"`

INPUT_FILE_MP3=`echo "${INPUT_FILE}" | sed "s/\w\+$/mp3/"`
if [ -f "${INPUT_FILE_MP3}" ]; then
	echo "Found \"${INPUT_FILE_MP3}\""
	AUDIO_OPTION="-an"
	PROBE_DATA=`mplayer -vo null -ao null -frames 0 -identify "${INPUT_FILE_MP3}" 2> /dev/null | grep -e ^ID_AUDIO`
	eval ${PROBE_DATA}
else
	AUDIO_OPTION="-acodec copy"
	PROBE_DATA=`mplayer -vo null -ao null -frames 0 -identify "${INPUT_FILE}" 2> /dev/null | grep -e ^ID_AUDIO`
	eval ${PROBE_DATA}
fi

VIDEO_BITRATE=`expr ${TOTAL_BITRATE} - ${ID_AUDIO_BITRATE}`

#
# Encode
#

echo "Encoding \"${INPUT_FILE}\"."

ffmpeg -y -i "${INPUT_FILE}" -an -pass 1 ${WIDTHxHEIGHT} -vcodec flv -b ${VIDEO_BITRATE} -bt ${VIDEO_BITRATE} -r ${FPS} "${OUTPUT_FILE}"
ffmpeg -y -i "${INPUT_FILE}" ${AUDIO_OPTION} -pass 2 ${WIDTHxHEIGHT} -vcodec flv -b ${VIDEO_BITRATE} -bt ${VIDEO_BITRATE} -r ${FPS} "${OUTPUT_FILE}"

if [ -f "${INPUT_FILE_MP3}" ]; then
	mencoder -oac copy -ovc copy -o "${OUTPUT_FILE_NEW_AUDIO}" -audiofile "${INPUT_FILE_MP3}" "${OUTPUT_FILE}" -of lavf -lavfopts format=flv
	rm "${OUTPUT_FILE}"
fi

exit 0

しかし、引数の順番 sensitive な FFmpeg は使うのが難しい。もうちょっとなんとかならんのかな。
追記: "http://www.stardustdust.jp/my_flyff/" が miraclemilk765 の中の人のブログだと知る。しばらく前に subscribe したところで、アップロードされた動画は Rimo でも使わさせてもらってるのだった。感謝。