blob: 2e6875feb8c6004189a18cd6363ee26502d2785a (
plain)
- #!/bin/sh
- # Copyright © 2012-2014 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: ffmpeg, 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
- output="${1:-dump.nut}"
- # resolve audio inputs: default PCM of all ALSA cards with input devices
- ainputs="$(arecord -l | grep -Po '^card \d+: \K\S+')"
- #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=copy # uncompressed
- #vcodec=huffyuv # more common
- #vcodec=ffvhuff # more compact, supports YV12 colorspace
- #vcodec=ffv1 # most compact, supports RGBA colorspace, too CPU-hungry
- acodec=copy
- #acodec=pcm_s16le
- 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 -threads auto -i $input"
- vmaps="${vmaps:+$vmaps }-map $i:v:0"
- i=$(expr $i + 1)
- done
- voutargs=${vinputs:+-c:v $vcodec ${outrate:+-r $outrate}}
- aoutargs=${ainputs:+-c:a $acodec}
- pasuspender=
- test ! -x /usr/bin/pasuspender | pasuspender=pasuspender
- which ffmpeg > /dev/null && ffmpeg=ffmpeg || ffmpeg=avconv
- echo $pasuspender $ffmpeg $ainargs $vinargs $vmaps $amaps $voutargs $aoutargs -y "$output"
- exec $pasuspender $ffmpeg $ainargs $vinargs $vmaps $amaps $voutargs $aoutargs -y "$output"
|