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