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