YouTube に高音質でアップロードできる動画ファイルを作るシェル・スクリプト (改良 FFmpeg 版)
2008-02-18 追記
外部に MP3 ファイルがなかった場合の処理がおかしかったので修正した。
FFmpeg 版も改良しておく
"YouTube に高音質でアップロードできる動画ファイルを作るシェル・スクリプト (改良 MEncoder 版) - だらりな。" のシェル・スクリプトでうまくエンコードできない動画があって、FFmpeg だとうまくエンコードできたので、FFmpeg を使ったほうも一応改良しておくことにした。ただし、こっちはあくまで非常時用。
たぶん、動画ファイル側のむちゃくちゃな自己申請が悪い。
$ mplayer -vo null -ao null -frames 0 -identify <ファイル名> 2> /dev/null | grep -e ^ID_ ID_VIDEO_ID=0 ID_AUDIO_ID=1 ID_FILENAME=<ファイル名> ID_DEMUXER=lavfpref ID_VIDEO_FORMAT=VP6F ID_VIDEO_BITRATE=0 ID_VIDEO_WIDTH=512 ID_VIDEO_HEIGHT=384 ID_VIDEO_FPS=1000.000 ID_VIDEO_ASPECT=0.0000 ID_AUDIO_FORMAT=85 ID_AUDIO_BITRATE=112000 ID_AUDIO_RATE=44100 ID_AUDIO_NCH=2 ID_LENGTH=188.72 ID_VIDEO_CODEC=ffvp6f ID_AUDIO_BITRATE=32000 ID_AUDIO_RATE=44100 ID_AUDIO_NCH=2 ID_AUDIO_CODEC=mp3
映像が 1000 fps とか音声が 32 kbps とかむちゃくちゃ。ID_VIDEO_BITRATE=0
ってのは、たぶん MPlayer のその部分が壊れてるか、まだ実装されてないかで、他の動画ファイルでもいっしょだけど。
それはともかく、MEncoder 版とほぼ同じ感じで改良した。
- 画質改善オプションについては、そんなオプション知らないと怒られてしまったものをハズした。
- FFmpeg で外部音声ファイルを使う方法もわかったのだけど、うまく mux できないと怒られるケースがあったので、結局その部分は MEncoder を使うことにした。
以下が問題の動画。MEncoder でエンコードすると数秒の動画になってしまったのだけど、FFmpeg だとだいじょうぶだった。
どんくさいシェル・スクリプト
MEncoder 版とほぼ同じ感じ。
#! /bin/sh source ${HOME}/bin/ffmpeg-youtube.conf MSG_PREFIX="[FFmpeg 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/"` OUTPUT_FILE_NEW_AUDIO=`basename "${INPUT_FILE}" | sed "s/\w\+$/forYouTube.NewAudio.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" VIDEO_BITRATE=`expr ${TOTAL_BITRATE} - ${ID_AUDIO_BITRATE}` echo "${MSG_PREFIX}AUDIO_BITRATE: ${ID_AUDIO_BITRATE} VIDEO_BITRATE: ${VIDEO_BITRATE}" #exit 0 # Debug 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 HEIGHT=`expr ${ID_VIDEO_HEIGHT} \* ${WIDTH} / ${ID_VIDEO_WIDTH}` else HEIGHT=`expr ${WIDTH} \* ${ID_VIDEO_ASPECT_X10000} / 10000` fi PAD_SIZE=`expr ${WIDTH} \* 3 / 4 - ${HEIGHT}` PADTOP_SIZE=`expr ${PAD_SIZE} / 2` PADBOTTOM_SIZE=`expr ${PAD_SIZE} - ${PADTOP_SIZE}` [ ! ${FPS} ] && FPS=${ID_VIDEO_FPS} echo "${MSG_PREFIX}WIDTH: ${WIDTH}; HEIGHT: ${HEIGHT}; PAD_SIZE: ${PAD_SIZE}; FPS: ${FPS}" #exit 0 # Debug # # Encode # VIDEO_OPTIONS="-mbd 2 -mv0 -trell -last_pred 3" PASSLOGFILE="ffmpeg-youtube" encode () { ffmpeg -y -i "${INPUT_FILE}" $1 -pass $2 -passlogfile ${PASSLOGFILE}\ -s ${WIDTH}x${HEIGHT} -padtop ${PAD_SIZE} -padbottom ${PAD_SIZE} -r ${FPS}\ -vcodec flv -b ${VIDEO_BITRATE} ${VIDEO_OPTIONS} "${OUTPUT_FILE}" } echo "${MSG_PREFIX}Encoding \"${INPUT_FILE}\" (pass 1/2)" encode "-an" 1 echo "${MSG_PREFIX}Encoding \"${INPUT_FILE}\" (pass 2/2)" if [ -f "`echo ${INPUT_FILE} | sed 's/\w\+$/mp3/'`" ]; then encode "-an" 2 mencoder -oac copy -ovc copy -o "${OUTPUT_FILE_NEW_AUDIO}" -audiofile "${INPUT_AUDIO_FILE}" "${OUTPUT_FILE}" -of lavf -lavfopts format=flv rm "${OUTPUT_FILE}"; OUTPUT_FILE=${OUTPUT_FILE_NEW_AUDIO} else encode "-acodec copy" 2 fi 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" rm ${PASSLOGFILE}*.log exit 0
設定用ファイル。
TOTAL_BITRATE=340000 WIDTH=320 #FPS=1 #FPS=7 #FPS=10 #FPS=12 FPS=15