diff options
Diffstat (limited to 'localvideodump')
-rwxr-xr-x | localvideodump | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/localvideodump b/localvideodump new file mode 100755 index 0000000..ba4880c --- /dev/null +++ b/localvideodump @@ -0,0 +1,119 @@ +#!/bin/sh +# Copyright © 2012, 2013 Jonas Smedegaard <dr@jones.dk> +# Description: record most possible video data using least CPU +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# Depends: libav-tools, alsa-utils, v4l-utils +# +# TODO: add --help option +# TODO: make inputs overrideable +# TODO: optionally limit number of inputs +# TODO: make codecs, rates etc. configurable +# TODO: auto-limit number of video-inputs per USB channel +# TODO: include SMTPE channel +# TODO: Check and ask if outfile already exist +# TODO: Add --force option to skip asking for overwriting + +set -e + +#melt cam_Microsoft_LifeCam_Studio.mlt -consumer avformat:x.avi vcodec=ffv1 an=1 + +output="${1:-dump.mkv}" + +# resolve audio inputs: default PCM of all ALSA cards with input devices +ainputs="$(arecord -l | perl -anE '/^card/ and say $F[2]')" +#ainputs="CARD=Generic_1,DEV=0" + +# FIXME: detect and avoid more than one device on same USB channel: +# [video4linux2 @ 0xed7e00] ioctl(VIDIOC_STREAMON): No space left on device +# /dev/video2: No space left on device +# maybe with $(v4l2-ctl --list-devices) +vinputs="$(ls -1 /dev/video*)" +#vinputs="$(ls -1 /dev/video* | grep -v video1)" +#vinputs="/dev/video0 /dev/video1 /dev/video3" +#vinputs="/dev/video0" + +# TODO: probe and optimize V4L settings (highest 16/9 size at >= 20fps +inrate=20 +#inrate=10 +outrate=$inrate # seems this ensures fixed rate when input is flaky + +#vcodec=huffyuv # more common +vcodec=ffvhuff # more compact, supports YV12 colorspace +#vcodec=ffv1 # most compact, supports RGBA colorspace, too CPU-hungry + +acodec=pcm_s16le + +vf="${vf:+$vf }-vf setpts=(RTCTIME-RTCSTART)/(TB*1000000)" # current time +vf="${vf:+$vf }-vf hqdn3d" # high-quality denoise (good for webcams) +font='/usr/share/fonts/truetype/droid/DroidSans.ttf' +#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"}" +#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"}" + +parse_v4l2_formats() { + v4l2-ctl --list-formats-ext -d "$1" | perl -n \ + -e '/^\tIndex\h*:/ and $type=$format=$raw=$size=$speed=undef;'\ + -e '/^\tType\h*: (Video Capture)/ and $type=$1;'\ + -e '/^\tPixel Format: '\''(\w+)'\''( \(compressed\))?/ and $format=$1 and $raw=int(!($2));'\ + -e '/^\t\tSize: Discrete (\d+x\d+)/ and $size=$1;'\ + -e 'next unless ($type and $format and $size);'\ + -e '/^\t\t\tInterval: .* \((\d+)\.\d+ fps\)/ and $speed=$1;'\ + -e 'next unless ($speed >= '$inrate');'\ + -E 'say "$raw $size $format"' \ + | sort -rV +} + +# expand arguments +i=0 +ainargs= +amaps= +for input in $ainputs; do + # TODO: handle varying descriptions (not just pick first entry) + # TODO: handle more descriptions (not just assume stereo) + achannels= + achannelsdesc="$(amixer -c $input | grep '^ Capture channels:' | head -n 1)" + case $achannelsdesc in + *': Mono') + achannels=1 + ;; + esac + ainargs="${ainargs:+$ainargs }-f alsa -ar 44100 ${achannels:+-ac $achannels} -i hw:$input" + amaps="${amaps:+$amaps }-map $i:a" + i=$(expr $i + 1) +done +vinargs= +vmaps= +for input in $vinputs; do + read raw size format dummy <<FORMATS +$(parse_v4l2_formats $input) +FORMATS + case $format in + YUYV) + format=yuyv422 + ;; + MJPG) + format=mjpeg + ;; + esac + [ -n "$format" ] || { echo "Skipping unsuitable input $input"; continue; } + vinargs="${vinargs:+$vinargs }-f video4linux2 -input_format $format ${inrate:+-framerate $inrate }-s $size -i $input" + vmaps="${vmaps:+$vmaps }-map $i:v:0" + i=$(expr $i + 1) +done +voutargs=${vinputs:+-c:v $vcodec $vf ${outrate:+-r $outrate}} +aoutargs=${ainputs:+-c:a $acodec} + +echo avconv -threads auto $ainargs $vinargs $vmaps $amaps $voutargs $aoutargs -y "$output" +exec avconv -threads auto $ainargs $vinargs $vmaps $amaps $voutargs $aoutargs -y "$output" |