- #!/bin/sh
- # Origins:
- # http://diveintohtml5.org/video.html
- # http://camendesign.com/code/video_for_everybody
- # http://www.streaminglearningcenter.com/articles/so-you-want-to-get-to-know-h264.html
- # Possible flashplayers:
- # http://www.internetmarketingnotes.com/2010/07/free-embeddable-flash-video-flv-players-for-commercial-use/
- # TODO: offer to skip rendering again if an output file exist already
- # TODO: support --width and --height (resolving the other part from input/forced aspect ratio)
- # TODO: support --formats (comma-separated, to allow e.g. excluding webm even if supported)
- # TODO: use (openshot and) melt:
- # * melt -consumer avformat:outfile.webm properties=consumer/avformat/webm infile.xml
- # * melt -consumer avformat:outfile.x264 properties=consumer/avformat/x264-medium-baseline infile.xml
- # * melt -consumer avformat:outfile.ogg f=ogg vcodec=libtheora b=1120k acodec=libvorbis aq=25 infile.xml
- set -e
- PRG=$(basename "$0")
- showhelp() {
- cat <<EOF
- Usage: $PRG --size SIZE [--profile PROFILE] [--title TITLE] INPUTFILE
- Encode video file in multiple web-optimized formats, and provide sample
- html favoring open formats with optional non-JavaScript Flash fallback.
- -s, --size Output size in WIDTHxHEIGHT or ffmpeg
- abbreviation like vga qvga qcif hd480 etc.
- (default: use input size)
- -p, --profile Quality profile (lo, hi, lowide, hiwide)
- (default: lo)
- -t, --title Title used in html fallback graphics
- (default: basename of input file)
- -h, --help This help text
- Examples:
- $PRG -s 320x200 -t "Funny guy" myvideo.dv
- NB! use max. 640x480 to support old iPod (e.g. 640x360 for 16:9).
- More info: <http://camendesign.com/code/video_for_everybody>
- EOF
- }
- exit1() {
- response="${1:+Error: }${1:-Internal error!}"
- echo >&2 "$response"
- exit 1
- }
- # parse cmdline options
- TEMP="`getopt -s sh -o hs:p:t: -l help,size:,profile:,title: -n "$PRG" -- "$@"`" || exit1 "Internal getopt error."
- eval set -- "$TEMP"
- while true ; do
- case "$1" in
- -h|--help) showhelp; exit;;
- -s|--size) size="$2"; shift 2;;
- -p|--profile) profile="$2"; shift 2;;
- -t|--title) title="$2"; shift 2;;
- --) shift; break;;
- *) exit1 "Internal error resolving options.";;
- esac
- done
- if [ $# -eq 0 ]; then
- showhelp
- exit1 "Too few parameters!"
- fi
- if [ $# -gt 1 ]; then
- showhelp
- exit1 "Too many parameters!"
- fi
- # input filename (mandatory)
- infile="$1"; shift
- [ -e "$infile" ] || exit1 "Input file missing!"
- filebase=$(echo "$infile" | perl -pe 's/\.[^.]*//')
- # fallback profile
- profile=${profile:-lo}
- case "$profile" in
- lo)
- bitrate=768
- aspect=4:3
- ;;
- lowide)
- bitrate=768
- aspect=16:9
- ;;
- hi)
- bitrate=1120
- aspect=4:3
- ;;
- hiwide)
- bitrate=1120
- aspect=16:9
- ;;
- esac
- # fallback graphics title
- title=${title:-$filebase}
- # TODO: Check and fail if all needed tools are not available
- _ffmpeg() {
- passes="$1"; shift
- ext="$1"; shift
- [ ! -f "$filebase.$ext" ] || exit1 "output file \"$filebase.$ext\" already exist. Remove it and try again."
- case $passes in
- 0)
- ffmpeg -i "$infile" $opts "$@" -f "$ext" -y "$filebase.$ext"
- ;;
- 1)
- [ ! -f "$filebase"-*.log ] || exit1 "logfiles already exist. Remove them (or wait for that other process to complete) and try again."
- ffmpeg -i "$infile" -pass 1 -passlogfile "$filebase" "$@" -an -f "$ext" -y /dev/null
- ;;
- 2)
- [ -f "$filebase"-*.log ] || exit1 "logfiles missing. Pass 2 cannot succeed without a prior pass 1."
- ffmpeg -i "$infile" -pass 2 -passlogfile "$filebase" "$@" -y "$filebase.$ext"
- rm "$filebase"-*.log
- case $ext in
- mp4)
- mv "$filebase.$ext" "$filebase.$ext"~
- qt-faststart "$filebase.$ext"~ "$filebase.$ext"
- [ -f "$filebase.$ext" ] && rm "$filebase.$ext"~ || exit1 "failed to optimize with qt-faststart."
- ;;
- esac
- ;;
- esac
- }
- opts_common="-threads 0 -b ${bitrate}k ${size:+-s $size} ${aspect:+-aspect $aspect}"
- opts_audio="-ac 2 -ar 44100 -ab 96k"
- opts_webm="-vcodec libvpx -keyint_min 0 -g 250 -skip_threshold 0"
- ## Theora/Vorbis/Ogg
- _ffmpeg 0 ogg $opts_common -vcodec libtheora -acodec libvorbis $opts_audio
- ## H.264/AAC/MP4
- _ffmpeg 1 mp4 $opts_common -vcodec libx264 -vpre medium_firstpass -vpre baseline
- _ffmpeg 2 mp4 $opts_common -vcodec libx264 -vpre medium -vpre baseline -acodec libvo_aacenc $opts_audio
- ## VP8/Vorbis/WebM
- ! ffmpeg -codecs | grep -iw vp8 || webm=yes
- [ -z "$webm" ] || _ffmpeg 1 webm $opts_common $opts_webm
- [ -z "$webm" ] || _ffmpeg 2 webm $opts_common $opts_webm -acodec libvorbis $opts_audio
- ## JPEG preview
- ffmpegthumbnailer -s0 -i "$filebase.ogg" -o "$filebase.jpg"
- # resolve width and height from preview image
- size=$(jpeginfo "$filebase.jpg" | perl -ane 'print "$F[1]x$F[3]"')
- width=$(echo "$size" | perl -Fx -ane 'print $F[0]')
- height=$(echo "$size" | perl -Fx -ane 'print $F[1]')
- heightplus=${height:+$(($height+4))}
- # TODO: resolve flash player to use
- [ -z "$flashplayer" ] || flash=yes
- cat >"$filebase.html" <<EOF
- <!-- Video for Everybody, Kroc Camen of Camen Design -->
- <video width="$width" height="$height" preload controls>
- <source src="$filebase.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' />
- <source src="$filebase.ogg" type='video/ogg; codecs="theora, vorbis"' />
- ${webm:+<source src="$filebase.webm" type='video/webm; codecs="vp8, vorbis"' />
- }${flash:+<object width="$width" height="$heightplus" type="application/x-shockwave-flash" data="$flashplayer.swf">
- <param name="movie" value="$flashplayer.swf" />
- <param name="flashvars" value="image=$filebase.jpg&file=$filebase.mp4" />
- }<img src="$filebase.jpg" width="$width" height="$height" alt="$title"
- title="No video playback capabilities, please download the video below" />
- ${flash:+</object>
- }</video>
- <p><strong>Download Video:</strong>
- open format <a href="$filebase.ogg">Ogg</a>,
- ${webm:+open format <a href="$filebase.webm">WebM</a>,}
- closed Format <a href="$filebase.mp4">MP4</a>.
- </p>
- EOF
|