summaryrefslogtreecommitdiff
path: root/localv4ldump
blob: a47f32c0295c143b03fc879bb8c22e38201f742b (plain)
  1. #!/bin/sh
  2. # Copyright © 2012, 2013 Jonas Smedegaard <dr@jones.dk>
  3. # Description: record most possible video data using least CPU
  4. #
  5. # This program is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; either version 3, or (at your option)
  8. # any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful, but
  11. # WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. # General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. #
  18. # Depends: libav-tools, alsa-utils, v4l-utils
  19. #
  20. # TODO: add --help option
  21. # TODO: make inputs overrideable
  22. # TODO: optionally limit number of inputs
  23. # TODO: make codecs, rates etc. configurable
  24. # TODO: auto-limit number of video-inputs per USB channel
  25. # TODO: include SMTPE channel
  26. # TODO: Check and ask if outfile already exist
  27. # TODO: Add --force option to skip asking for overwriting
  28. set -e
  29. #melt cam_Microsoft_LifeCam_Studio.mlt -consumer avformat:x.avi vcodec=ffv1 an=1
  30. output="${1:-dump.mkv}"
  31. ainputs="$(arecord -L | perl -nE '/^default:.*\b(CARD=\w+)/ and say $1')"
  32. #ainputs="hw:CARD=Generic_1,DEV=0"
  33. # FIXME: detect and avoid more than one device on same USB channel:
  34. # [video4linux2 @ 0xed7e00] ioctl(VIDIOC_STREAMON): No space left on device
  35. # /dev/video2: No space left on device
  36. # maybe with $(v4l2-ctl --list-devices)
  37. vinputs="$(ls -1 /dev/video*)"
  38. #vinputs="$(ls -1 /dev/video* | grep -v video1)"
  39. #vinputs="/dev/video0 /dev/video1 /dev/video3"
  40. #vinputs="/dev/video0"
  41. # TODO: probe and optimize V4L settings (highest 16/9 size at >= 20fps
  42. inrate=20
  43. #inrate=10
  44. outrate=$inrate # seems this ensures fixed rate when input is flaky
  45. #vcodec=huffyuv # more common
  46. vcodec=ffvhuff # more compact, supports YV12 colorspace
  47. #vcodec=ffv1 # most compact, supports RGBA colorspace, too CPU-hungry
  48. acodec=pcm_s16le
  49. vf="${vf:+$vf }-vf setpts=(RTCTIME-RTCSTART)/(TB*1000000)" # current time
  50. vf="${vf:+$vf }-vf hqdn3d" # high-quality denoise (good for webcams)
  51. font='/usr/share/fonts/truetype/droid/DroidSans.ttf'
  52. #vf="${vf:+$vf }-vf "drawtext=fontfile=$font: timecode='09\:57\:00\:00': r=25: x=(w-tw)/2: y=h-(2*lh): fontcolor=white: box=1: boxcolor=0x00000000@1"}"
  53. #vf="${vf:+$vf }-vf "drawtext=fontfile=DroidSans.ttf:'timecode=09\:57\:00\:00':r=25:x=\(w-tw\)/2:y=h-\(2*lh\):fontcolor=white:box=1:boxcolor=0x00000000@1"}"
  54. parse_v4l2_formats() {
  55. v4l2-ctl --list-formats-ext -d "$1" | perl -n \
  56. -e '/^\tIndex\h*:/ and $type=$format=$raw=$size=$speed=undef;'\
  57. -e '/^\tType\h*: (Video Capture)/ and $type=$1;'\
  58. -e '/^\tPixel Format: '\''(\w+)'\''( \(compressed\))?/ and $format=$1 and $raw=int(!($2));'\
  59. -e '/^\t\tSize: Discrete (\d+x\d+)/ and $size=$1;'\
  60. -e 'next unless ($type and $format and $size);'\
  61. -e '/^\t\t\tInterval: .* \((\d+)\.\d+ fps\)/ and $speed=$1;'\
  62. -e 'next unless ($speed >= '$inrate');'\
  63. -E 'say "$raw $size $format"' \
  64. | sort -rV
  65. }
  66. # expand arguments
  67. i=0
  68. ainargs=
  69. amaps=
  70. for input in $ainputs; do
  71. ainargs="${vinargs:+$vinargs }-f alsa -ar 44100 -i hw:$input"
  72. amaps="${amaps:+$amaps }-map $i:a"
  73. ((i=i+1))
  74. done
  75. vinargs=
  76. vmaps=
  77. for input in $vinputs; do
  78. read raw size format dummy <<FORMATS
  79. $(parse_v4l2_formats $input)
  80. FORMATS
  81. case $format in
  82. YUYV)
  83. format=yuyv422
  84. ;;
  85. MJPG)
  86. format=mjpeg
  87. ;;
  88. esac
  89. [ -n "$format" ] || { echo "Skipping unsuitable input $input"; continue; }
  90. vinargs="${vinargs:+$vinargs }-f video4linux2 -input_format $format ${inrate:+-framerate $inrate }-s $size -i $input"
  91. vmaps="${vmaps:+$vmaps }-map $i:v:0"
  92. ((i=i+1))
  93. done
  94. voutargs=${vinputs:+-c:v $vcodec $vf ${outrate:+-r $outrate}}
  95. aoutargs=${ainputs:+-c:a $acodec}
  96. exec avconv -threads auto $ainargs $vinargs $vmaps $amaps $voutargs $aoutargs -y "$output"