summaryrefslogtreecommitdiff
path: root/localvideowebencode
blob: 6c5b043653369fc65dd3a2224efdae397405b1bc (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: use (openshot and) melt:
  12. # * melt -consumer avformat:outfile.webm properties=consumer/avformat/webm infile.xml
  13. # * melt -consumer avformat:outfile.x264 properties=consumer/avformat/x264-medium-baseline infile.xml
  14. # * melt -consumer avformat:outfile.ogg f=ogg vcodec=libtheora b=1120k acodec=libvorbis aq=25 infile.xml
  15. # TODO: add --speech option, using mono, lower audio rate, and (when solved how) speex
  16. set -e
  17. PRG=$(basename "$0")
  18. showhelp() {
  19. cat <<EOF
  20. Usage: $PRG --size SIZE [--profile PROFILE] [--title TITLE] INPUTFILE
  21. Encode video file in multiple web-optimized formats, and provide sample
  22. html favoring open formats with optional non-JavaScript Flash fallback.
  23. -s, --size Output size in WIDTHxHEIGHT or ffmpeg
  24. abbreviation like vga qvga qcif hd480 etc.
  25. (default: use input size)
  26. -p, --profile Quality profile (lo, hi, lowide, hiwide)
  27. (default: lo)
  28. -t, --title Title used in html fallback graphics
  29. (default: basename of input file)
  30. -h, --help This help text
  31. Examples:
  32. $PRG -s qvga -t "Funny guy" myvideo.dv
  33. $PRG -p hiwide -s hd480 -t "Funny guy" myvideo.dv
  34. Profile "lo" (default) is optimal for 320x240 (qvga).
  35. Profile "hi" is optimal for 640x240 (vga) content.
  36. NB! Old iPod has 640x480 limit, so use 640x360 (not hd480) with hiwide.
  37. More info: <http://camendesign.com/code/video_for_everybody>
  38. EOF
  39. }
  40. exit1() {
  41. response="${1:+Error: }${1:-Internal error!}"
  42. echo >&2 "$response"
  43. exit 1
  44. }
  45. # parse cmdline options
  46. TEMP="`getopt -s sh -o hs:p:t: -l help,size:,profile:,title: -n "$PRG" -- "$@"`" || exit1 "Internal getopt error."
  47. eval set -- "$TEMP"
  48. while true ; do
  49. case "$1" in
  50. -h|--help) showhelp; exit;;
  51. -s|--size) size="$2"; shift 2;;
  52. -p|--profile) profile="$2"; shift 2;;
  53. -t|--title) title="$2"; shift 2;;
  54. --) shift; break;;
  55. *) exit1 "Internal error resolving options.";;
  56. esac
  57. done
  58. if [ $# -eq 0 ]; then
  59. showhelp
  60. exit1 "Too few parameters!"
  61. fi
  62. if [ $# -gt 1 ]; then
  63. showhelp
  64. exit1 "Too many parameters!"
  65. fi
  66. # input filename (mandatory)
  67. infile="$1"; shift
  68. [ -e "$infile" ] || exit1 "Input file missing!"
  69. filebase=$(echo "$infile" | perl -pe 's/\.[^.]*//')
  70. # fallback profile
  71. profile=${profile:-lo}
  72. case "$profile" in
  73. lo)
  74. bitrate=768
  75. aspect=4:3
  76. ;;
  77. lowide)
  78. bitrate=768
  79. aspect=16:9
  80. ;;
  81. hi)
  82. bitrate=1120
  83. aspect=4:3
  84. ;;
  85. hiwide)
  86. bitrate=1120
  87. aspect=16:9
  88. ;;
  89. esac
  90. # fallback graphics title
  91. title=${title:-$filebase}
  92. # TODO: Check and fail if all needed tools are not available
  93. _ffmpeg() {
  94. passes="$1"; shift
  95. ext="$1"; shift
  96. [ ! -f "$filebase.$ext" ] || exit1 "output file \"$filebase.$ext\" already exist. Remove it and try again."
  97. case $passes in
  98. 0)
  99. ffmpeg -i "$infile" $opts "$@" -f "$ext" -y "$filebase.$ext"
  100. ;;
  101. 1)
  102. [ ! -f "$filebase"-*.log ] || exit1 "logfiles already exist. Remove them (or wait for that other process to complete) and try again."
  103. ffmpeg -i "$infile" -pass 1 -passlogfile "$filebase" "$@" -an -f "$ext" -y /dev/null
  104. ;;
  105. 2)
  106. [ -f "$filebase"-*.log ] || exit1 "logfiles missing. Pass 2 cannot succeed without a prior pass 1."
  107. ffmpeg -i "$infile" -pass 2 -passlogfile "$filebase" "$@" -y "$filebase.$ext"
  108. rm "$filebase"-*.log
  109. case $ext in
  110. mp4)
  111. mv "$filebase.$ext" "$filebase.$ext"~
  112. qt-faststart "$filebase.$ext"~ "$filebase.$ext"
  113. [ -f "$filebase.$ext" ] && rm "$filebase.$ext"~ || exit1 "failed to optimize with qt-faststart."
  114. ;;
  115. esac
  116. ;;
  117. esac
  118. }
  119. opts_common="-threads 0 -b ${bitrate}k ${size:+-s $size} ${aspect:+-aspect $aspect}"
  120. opts_audio="-ac 2 -ar 44100 -ab 96k"
  121. opts_webm="-vcodec libvpx -keyint_min 0 -g 250 -skip_threshold 0"
  122. ## Theora/Vorbis/Ogg
  123. _ffmpeg 0 ogg $opts_common -vcodec libtheora -acodec libvorbis $opts_audio
  124. ## H.264/AAC/MP4
  125. _ffmpeg 1 mp4 $opts_common -vcodec libx264 -vpre medium_firstpass -vpre baseline
  126. _ffmpeg 2 mp4 $opts_common -vcodec libx264 -vpre medium -vpre baseline -acodec libvo_aacenc $opts_audio
  127. ## VP8/Vorbis/WebM
  128. ! ffmpeg -codecs | grep -iw vp8 || webm=yes
  129. [ -z "$webm" ] || _ffmpeg 1 webm $opts_common $opts_webm
  130. [ -z "$webm" ] || _ffmpeg 2 webm $opts_common $opts_webm -acodec libvorbis $opts_audio
  131. ## JPEG preview
  132. ffmpegthumbnailer -s0 -i "$filebase.ogg" -o "$filebase.jpg"
  133. # resolve width and height from preview image
  134. size=$(jpeginfo "$filebase.jpg" | perl -ane 'print "$F[1]x$F[3]"')
  135. width=$(echo "$size" | perl -Fx -ane 'print $F[0]')
  136. height=$(echo "$size" | perl -Fx -ane 'print $F[1]')
  137. heightplus=${height:+$(($height+4))}
  138. # TODO: resolve flash player to use
  139. [ -z "$flashplayer" ] || flash=yes
  140. cat >"$filebase.html" <<EOF
  141. <!-- Video for Everybody, Kroc Camen of Camen Design -->
  142. <video width="$width" height="$height" preload controls>
  143. <source src="$filebase.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' />
  144. <source src="$filebase.ogg" type='video/ogg; codecs="theora, vorbis"' />
  145. ${webm:+<source src="$filebase.webm" type='video/webm; codecs="vp8, vorbis"' />
  146. }${flash:+<object width="$width" height="$heightplus" type="application/x-shockwave-flash" data="$flashplayer.swf">
  147. <param name="movie" value="$flashplayer.swf" />
  148. <param name="flashvars" value="image=$filebase.jpg&amp;file=$filebase.mp4" />
  149. }<img src="$filebase.jpg" width="$width" height="$height" alt="$title"
  150. title="No video playback capabilities, please download the video below" />
  151. ${flash:+</object>
  152. }</video>
  153. <p><strong>Download Video:</strong>
  154. open format <a href="$filebase.ogg">Ogg</a>,
  155. ${webm:+open format <a href="$filebase.webm">WebM</a>,}
  156. closed Format <a href="$filebase.mp4">MP4</a>.
  157. </p>
  158. EOF