summaryrefslogtreecommitdiff
path: root/localvideowebencode
blob: 9fb22fde08c244f4d537fe399bf732917978083d (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 [INPUTFILE...]
  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 in WIDTHxHEIGHT or ffmpeg
  20. abbreviation like vga qvga qcif hd480 etc.
  21. (default: use input size)
  22. -a, --aspect Display Aspect Ratio in melt format e.g. @16/9
  23. (default: no aspect hinting)
  24. -b, --bitrate Bitrate in bytes, optionally ISO appreviated
  25. (default: 768k)
  26. -p, --profile Melt profile like square_ntsc quarter_pal_wide
  27. qcif_15 etc.
  28. (default: none - reuse input profile)
  29. --h264profile MPEG-4 AVC target profile (baseline medium)
  30. (default: baseline)
  31. -t, --title Title used in html fallback graphics
  32. (default: basename of first input file)
  33. -h, --help This help text
  34. Examples:
  35. $PRG -s qvga -t "Funny guy" myvideo.dv outro.dv
  36. $PRG -p sdi_486i_5994 -s hd480 -t "Funny guy" myvideo.dv
  37. Arguments can be passed directly to the melt avformat consumer.
  38. If multiple input files are provided, they are merged together and
  39. output files are named based on last input file.
  40. Default options are optimal for 320x240 (qvga) and similar.
  41. Suggested bitrates:
  42. 320x240 (qvga): 768k
  43. 640x480 (vga): 1120k
  44. NB! Old iPod require baseline encoding and has 640x480 size limit.
  45. Use e.g. quarter_ntsc_wide, svcd_ntsc_wide or svcd_pal_wide (varying in
  46. framerate and Pixel Aspect Ratio) for widescreen material.
  47. More info: <http://camendesign.com/code/video_for_everybody>
  48. <http://www.streaminglearningcenter.com/>
  49. <http://en.wikipedia.org/wiki/HTML5_video>
  50. EOF
  51. }
  52. exit1() {
  53. response="${1:+Error: }${1:-Internal error!}"
  54. echo >&2 "$response"
  55. exit 1
  56. }
  57. # defaults
  58. bitrate=768k
  59. h264profile=baseline
  60. # parse cmdline options
  61. TEMP="`getopt -s sh -o hs:a:b:p:t: -l help,size:,aspect:,bitrate:,profile:,h264profile,title: -n "$PRG" -- "$@"`" || exit1 "Internal getopt error."
  62. eval set -- "$TEMP"
  63. while true ; do
  64. case "$1" in
  65. -h|--help) showhelp; exit;;
  66. -s|--size) size="$2"; shift 2;;
  67. -a|--aspect) aspect="$2"; shift 2;;
  68. -b|--bitrate) bitrate="$2"; shift 2;;
  69. -p|--profile) profile="$2"; shift 2;;
  70. --h264profile) h264profile="$2"; shift 2;;
  71. -t|--title) title="$2"; shift 2;;
  72. --) shift; break;;
  73. *) exit1 "Internal error resolving options.";;
  74. esac
  75. done
  76. if [ $# -eq 0 ]; then
  77. showhelp
  78. exit1 "Too few parameters!"
  79. fi
  80. # input filename (mandatory)
  81. infile="${$#}"
  82. [ -e "$infile" ] || exit1 "Input file missing!"
  83. filebase=$(echo "$infile" | perl -pe 's/\.[^.]*//')
  84. # fallback graphics title
  85. title=${title:-$filebase}
  86. # TODO: Check and fail if all needed tools are not available
  87. # TODO: When verified beneficial, add option real_time=-2
  88. opts="${profile:+-profile $profile}"
  89. args=" ${bitrate:+b=${bitrate}} ${size:+s=$size} ${aspect:+aspect=$aspect}"
  90. args_audio="ac=2 ar=44100 ab=96k"
  91. # bail out (before any expensive tasks) if logfiles exists
  92. [ ! -f x264-*.log* ] || exit1 "logfiles already exist. Remove them (or wait for that other process using them to complete) and try again."
  93. ## Theora/Vorbis/Ogg
  94. melt $opts -consumer avformat:"$filebase.ogg" f=ogg vcodec=libtheora $args acodec=libvorbis aq=25 $args_audio "$@"
  95. ## H.264/AAC/MP4
  96. melt $opts -consumer avformat:/dev/null f=mp4 properties=x264-medium-$h264profile $args pass=1 an=1 fastfirstpass=1 "$@"
  97. melt $opts -consumer avformat:"$filebase.mp4" properties=x264-medium-$h264profile $args pass=2 acodec=libvo_aacenc $args_audio "$@"
  98. mv "$filebase.mp4" "$filebase.mp4"~
  99. qt-faststart "$filebase.mp4"~ "$filebase.mp4"
  100. [ -f "$filebase.mp4" ] && rm "$filebase.mp4"~ || exit1 "failed to optimize with qt-faststart."
  101. ## VP8/Vorbis/WebM
  102. # TODO: use two-pass when supported by melt
  103. melt $opts -consumer avformat:"$filebase.webm" properties=webm $args $args_audio "$@"
  104. ## JPEG preview
  105. ffmpegthumbnailer -s0 -i "$filebase.mp4" -o "$filebase.jpg"
  106. # resolve width and height from preview image
  107. size=$(jpeginfo "$filebase.jpg" | perl -ane 'print "$F[1]x$F[3]"')
  108. width=$(echo "$size" | perl -Fx -ane 'print $F[0]')
  109. height=$(echo "$size" | perl -Fx -ane 'print $F[1]')
  110. heightplus=${height:+$(($height+4))}
  111. # TODO: resolve flash player to use
  112. [ -z "$flashplayer" ] || flash=yes
  113. cat >"$filebase.html" <<EOF
  114. <!-- Video for Everybody, Kroc Camen of Camen Design -->
  115. <video width="$width" height="$height" preload controls>
  116. <source src="$filebase.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' />
  117. <source src="$filebase.ogg" type='video/ogg; codecs="theora, vorbis"' />
  118. <source src="$filebase.webm" type='video/webm; codecs="vp8, vorbis"' />
  119. ${flash:+<object width="$width" height="$heightplus" type="application/x-shockwave-flash" data="$flashplayer.swf">
  120. <param name="movie" value="$flashplayer.swf" />
  121. <param name="flashvars" value="image=$filebase.jpg&amp;file=$filebase.mp4" />
  122. }<img src="$filebase.jpg" width="$width" height="$height" alt="$title"
  123. title="No video playback capabilities, please download the video below" />
  124. ${flash:+</object>
  125. }</video>
  126. <p><strong>Download Video:</strong>
  127. open format <a href="$filebase.ogg">Ogg</a>,
  128. open format <a href="$filebase.webm">WebM</a>,
  129. closed Format <a href="$filebase.mp4">MP4</a>.
  130. </p>
  131. EOF