- #!/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: add --speech option, using mono, lower audio rate, and (when solved how) speex
- set -e
- PRG=$(basename "$0")
- showhelp() {
- cat <<EOF
- Usage: $PRG [OPTION...] [--] [ARG=VALUE...] INPUTFILE [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)
- -a, --aspect Display Aspect Ratio in melt format e.g. @16/9
- (default: no aspect hinting)
- -b, --bitrate Bitrate in bytes, optionally ISO appreviated
- (default: 768k)
- -p, --profile Melt profile like square_ntsc quarter_pal_wide
- qcif_15 etc.
- (default: none - reuse input profile)
- --h264profile MPEG-4 AVC target profile (baseline medium)
- (default: baseline)
- -t, --title Title used in html fallback graphics
- (default: basename of first input file)
- -h, --help This help text
- Examples:
- $PRG -s qvga -t "Funny guy" myvideo.dv outro.dv
- $PRG -p sdi_486i_5994 -s hd480 -t "Funny guy" myvideo.dv
- Arguments can be passed directly to the melt avformat consumer.
- If multiple input files are provided, they are merged together and
- output files are named based on first input file.
- Default options are optimal for 320x240 (qvga) and similar.
- Suggested bitrates:
- 320x240 (qvga): 768k
- 640x480 (vga): 1120k
- NB! Old iPod require baseline encoding and has 640x480 size limit.
- Use e.g. quarter_ntsc_wide, svcd_ntsc_wide or svcd_pal_wide (varying in
- framerate and Pixel Aspect Ratio) for widescreen material.
- More info: <http://camendesign.com/code/video_for_everybody>
- <http://www.streaminglearningcenter.com/>
- <http://en.wikipedia.org/wiki/HTML5_video>
- EOF
- }
- exit1() {
- response="${1:+Error: }${1:-Internal error!}"
- echo >&2 "$response"
- exit 1
- }
- # defaults
- bitrate=768k
- h264profile=baseline
- # parse cmdline options
- TEMP="`getopt -s sh -o hs:a:b:p:t: -l help,size:,aspect:,bitrate:,profile:,h264profile,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;;
- -a|--aspect) aspect="$2"; shift 2;;
- -b|--bitrate) bitrate="$2"; shift 2;;
- -p|--profile) profile="$2"; shift 2;;
- --h264profile) h264profile="$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
- # input filename (mandatory)
- infile="$1"
- [ -e "$infile" ] || exit1 "Input file missing!"
- filebase=$(echo "$infile" | perl -pe 's/\.[^.]*//')
- # fallback graphics title
- title=${title:-$filebase}
- # TODO: Check and fail if all needed tools are not available
- # TODO: When verified beneficial, add option real_time=-2
- opts="${profile:+-profile $profile}"
- args=" ${bitrate:+b=${bitrate}} ${size:+s=$size} ${aspect:+aspect=$aspect}"
- args_audio="ac=2 ar=44100 ab=96k"
- # bail out (before any expensive tasks) if logfiles exists
- [ ! -f x264-*.log* ] || exit1 "logfiles already exist. Remove them (or wait for that other process using them to complete) and try again."
- ## Theora/Vorbis/Ogg
- melt $opts -consumer avformat:"$filebase.ogg" f=ogg vcodec=libtheora $args acodec=libvorbis aq=25 $args_audio "$@"
- ## H.264/AAC/MP4
- melt $opts -consumer avformat:/dev/null f=mp4 properties=x264-medium-$h264profile $args pass=1 an=1 fastfirstpass=1 "$@"
- melt $opts -consumer avformat:"$filebase.mp4" properties=x264-medium-$h264profile $args pass=2 acodec=libvo_aacenc $args_audio "$@"
- mv "$filebase.mp4" "$filebase.mp4"~
- qt-faststart "$filebase.mp4"~ "$filebase.mp4"
- [ -f "$filebase.mp4" ] && rm "$filebase.mp4"~ || exit1 "failed to optimize with qt-faststart."
- ## VP8/Vorbis/WebM
- # TODO: use two-pass when supported by melt
- melt $opts -consumer avformat:"$filebase.webm" properties=webm $args $args_audio "$@"
- ## JPEG preview
- ffmpegthumbnailer -s0 -i "$filebase.mp4" -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
|