summaryrefslogtreecommitdiff
path: root/localvideowebencode
blob: b89e6b02948f4326eec766c9ae878bba66ddc7c1 (plain)
  1. #!/bin/sh
  2. # Origins:
  3. # http://diveintohtml5.org/video.html
  4. # http://camendesign.com/code/video_for_everybody
  5. # http://www.streaminglearningcenter.com/articles/so-you-want-to-get-to-know-h264.html
  6. # Possible flashplayers:
  7. # http://www.internetmarketingnotes.com/2010/07/free-embeddable-flash-video-flv-players-for-commercial-use/
  8. # TODO: offer to skip rendering again if an output file exist already
  9. # TODO: support --width and --height (resolving the other part from input/forced aspect ratio)
  10. # TODO: support --formats (comma-separated, to allow e.g. excluding webm even if supported)
  11. # TODO: add --speech option, using mono, lower audio rate, and (when solved how) speex
  12. set -e
  13. PRG=$(basename "$0")
  14. showhelp() {
  15. cat <<EOF
  16. Usage: $PRG [OPTION...] [--] [ARG=VALUE...] INPUTFILE... [ARG=VALUE...]
  17. Encode video file in multiple web-optimized formats, and provide sample
  18. html favoring open formats with optional non-JavaScript Flash fallback.
  19. -s, --size Output size (ffmpeg): WIDTHxHEIGHT vga qcif etc.
  20. (default: use input size)
  21. -a, --aspect Display Aspect Ratio in melt format e.g. @16/9
  22. (default: no aspect hinting)
  23. -b, --bitrate Bitrate in bytes, optionally ISO appreviated
  24. (default: 768k)
  25. -p, --profile Video format (melt): square_ntsc qcif_15 etc.
  26. (default: none - reuse input format)
  27. --h264profile MPEG-4 AVC target profile (baseline medium)
  28. (default: baseline)
  29. --stem Stem of output filenames, optionally with path
  30. (default: basename of last input file)
  31. -t, --title Title used in html fallback graphics
  32. (default: stem)
  33. --filter Add melt filter (applied to all input files)
  34. --sample[=frame] Limit output to a 150 frames sample from
  35. beginning or optionally a later start frame
  36. -h, --help This help text
  37. Examples:
  38. $PRG -s qvga -t "Funny guy" intro.dv myvideo.dv
  39. $PRG -p sdi_486i_5994 --stem funny -t "Funny guy" myvideo.dv
  40. Options before input files are passed to melt producer, and after to
  41. melt avformat consumer.
  42. Defaults are optimized for 320x240 (qvga). For better quality use this:
  43. size: 640x480 (use lower numbers for widescreen!)
  44. bitrate: 1120k
  45. h264profile: baseline
  46. More info: <http://camendesign.com/code/video_for_everybody>
  47. <http://www.streaminglearningcenter.com/>
  48. <http://en.wikipedia.org/wiki/HTML5_video>
  49. EOF
  50. }
  51. exit1() {
  52. response="${1:+Error: }${1:-Internal error!}"
  53. echo >&2 "$response"
  54. exit 1
  55. }
  56. # defaults
  57. bitrate=768k
  58. h264profile=baseline
  59. # parse cmdline options
  60. TEMP="`getopt -s sh -o hs:a:b:p:t: -l help,size:,aspect:,bitrate:,profile:,h264profile:,stem:,title:,filter:,sample:: -n "$PRG" -- "$@"`" || exit1 "Internal getopt error."
  61. eval set -- "$TEMP"
  62. while true ; do
  63. case "$1" in
  64. -h|--help) showhelp; exit;;
  65. -s|--size) size="$2"; shift 2;;
  66. -a|--aspect) aspect="$2"; shift 2;;
  67. -b|--bitrate) bitrate="$2"; shift 2;;
  68. -p|--profile) profile="$2"; shift 2;;
  69. --h264profile) h264profile="$2"; shift 2;;
  70. --stem) stem="$2"; shift 2;;
  71. -t|--title) title="$2"; shift 2;;
  72. --filter) filters="${filters:+$filters }-filter $2"; shift 2
  73. while [ $# -gt 0 ] ; do
  74. case "$1" in
  75. *=*) filters="${filters:+$filters }$1"; shift;;
  76. *) break;;
  77. esac
  78. done
  79. ;;
  80. --sample) sample="in=${2:-0} out=$((${2:-0} + 150))"; shift 2;;
  81. --) shift; break;;
  82. *) exit1 "Internal error resolving options.";;
  83. esac
  84. done
  85. while [ $# -gt 0 ] ; do
  86. case "$1" in
  87. *=*) args_in="${args_in:+$args_in }$1"; shift;;
  88. *) break;;
  89. esac
  90. done
  91. while [ $# -gt 0 ] ; do
  92. case "$1" in
  93. *=*) args_out="${args_out:+$args_out }$1"; shift;;
  94. *) infiles="${infiles:+$infiles }$1"; shift;;
  95. esac
  96. done
  97. if [ -z "$infiles" ]; then
  98. showhelp
  99. exit1 "Too few parameters!"
  100. fi
  101. # input filename (mandatory)
  102. infile=$(perl -e 'print pop @ARGV' $infiles)
  103. [ -e "$infile" ] || exit1 "Input file missing!"
  104. # resolve stem and title (if not explicitly set)
  105. stem=${stem:-$(basename "$infile" | perl -pe 's/\.[^.]*//')}
  106. title=${title:-$stem}
  107. # TODO: Check and fail if all needed tools are not available
  108. # TODO: When verified beneficial, add option real_time=-2
  109. args_in="-progress $sample ${profile:+-profile $profile}${args_in:+ $args_in}"
  110. args=" ${bitrate:+b=${bitrate}} ${size:+s=$size} ${aspect:+aspect=$aspect}"
  111. args_audio="ac=2 ar=44100 ab=96k"
  112. ## Theora/Vorbis/Ogg
  113. melt -group $args_in $infiles -group $filters -consumer avformat:"$stem.ogg" f=ogg vcodec=libtheora $args acodec=libvorbis $args_audio $args_out
  114. ## H.264/AAC/MP4
  115. melt -group $args_in $infiles -group $filters -consumer avformat:/dev/null properties=x264-medium-pass1 properties=x264-medium-$h264profile $args $args_out
  116. melt -group $args_in $infiles -group $filters -consumer avformat:"$stem.mp4" pass=2 properties=x264-medium-$h264profile $args acodec=aac $args_audio $args_out
  117. mv "$stem.mp4" "$stem.mp4"~
  118. qt-faststart "$stem.mp4"~ "$stem.mp4"
  119. [ -f "$stem.mp4" ] && rm "$stem.mp4"~ || exit1 "failed to optimize with qt-faststart."
  120. ## VP8/Vorbis/WebM
  121. # TODO: use two-pass when supported by melt
  122. melt -group $args_in $infiles -group $filters -consumer avformat:"$stem.webm" properties=webm $args $args_audio $args_out
  123. ## JPEG preview
  124. ffmpegthumbnailer -s0 -i "$stem.mp4" -o "$stem.jpg"
  125. # resolve width and height from preview image
  126. size=$(jpeginfo "$stem.jpg" | perl -ane 'print "$F[1]x$F[3]"')
  127. width=$(echo "$size" | perl -Fx -ane 'print $F[0]')
  128. height=$(echo "$size" | perl -Fx -ane 'print $F[1]')
  129. heightplus=${height:+$(($height+4))}
  130. # TODO: resolve flash player to use
  131. [ -z "$flashplayer" ] || flash=yes
  132. cat >"$stem.html" <<EOF
  133. <!-- Video for Everybody, Kroc Camen of Camen Design -->
  134. <video width="$width" height="$height" preload controls>
  135. <source src="$stem.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' />
  136. <source src="$stem.ogg" type='video/ogg; codecs="theora, vorbis"' />
  137. <source src="$stem.webm" type='video/webm; codecs="vp8, vorbis"' />
  138. ${flash:+<object width="$width" height="$heightplus" type="application/x-shockwave-flash" data="$flashplayer.swf">
  139. <param name="movie" value="$flashplayer.swf" />
  140. <param name="flashvars" value="image=$stem.jpg&amp;file=$stem.mp4" />
  141. }<img src="$stem.jpg" width="$width" height="$height" alt="$title"
  142. title="No video playback capabilities, please download the video below" />
  143. ${flash:+</object>
  144. }</video>
  145. <p><strong>Download Video:</strong>
  146. open format <a href="$stem.ogg">Ogg</a>,
  147. open format <a href="$stem.webm">WebM</a>,
  148. closed Format <a href="$stem.mp4">MP4</a>.
  149. </p>
  150. EOF