X-Git-Url: https://iankelling.org/git/?a=blobdiff_plain;f=ffs;h=6975d387931c6fb5b8441a270a4533874be6d547;hb=dab96f8fa4c701db13ba734fa0c07b5d12fc8fae;hp=253b83b9ec41e1585139c94e78daa69f6faa5738;hpb=b714b0dde29aaf5e44d628c1d723077465e9c488;p=distro-setup diff --git a/ffs b/ffs index 253b83b..6975d38 100755 --- a/ffs +++ b/ffs @@ -22,9 +22,108 @@ # ffs = ffmpeg stream -# todo: figure out how to record mumble -# todo: get icecast on li.b8.nz -# todo: https://superuser.com/questions/1106674/how-to-add-blank-lines-above-the-bottom-in-terminal +# todo: learn to start working in one corner of the screen. + +# todo: get an icecast on li.b8.nz for when i'm away from home. + +# potential improvement: it might be nice that we could have a tall terminal bug only use +# the top half for a 1080p stream, this is how: +# https://superuser.com/questions/1106674/how-to-add-blank-lines-above-the-bottom-in-terminal +# +# potential improvement: sometimes I probably want to stream full height +# window. I could add an option for that. + +# potential improvement: setup a function which automatically mutes after some time, or +# after some time of no audio input. + + +### begin background/development docs ### + +# zmq vs stdin commands: +# +# * zmq allows targeting a specific filter when there are duplicates. +# +# * if you type stdin command too slow, ffmpeg will die because it stops +# doing normal work while it is waiting. +# +# * zmq returns a result to the calling process, rather than printing to +# stdout. +# +# * the only simple zmq tool I found, zmqsend, requires compiling. I +# used the latest ffmpeg 7.0.1. Build like so: +# +# p build-dep ffmpeg/aramo +# ./configure --enable-libzmq # i already had libzmq3-dev installed +# make alltools +# cp tools/zmqsend /a/opt/bin +# +# * ffmpeg debug output was useful in testing zmq commands. +# +# * Important documentation for stdin commands is only found by typing +# "c" into the stdin of ffmpeg and reading the output. +# +# +# +# stdin command docs, before I abandoned it for zmq: +# mkfifo -m 0600 /tmp/iank-ffmpeg +# # ffmpeg sits and waits until we do this. dunno why. +# echo >/tmp/iank-ffmpeg & +# ffmpeg ... /tmp/iank-ffmpeg +# echo "cdrawbox -1 t fill" >/tmp/iank-ffmpeg +# echo "cdrawtext -1 reinit text=''" >/tmp/iank-ffmpeg +# echo "cvolume -1 volume=1" >/tmp/iank-ffmpeg + + +# For testing: to show the number of audio channels in a resulting file +# https://stackoverflow.com/questions/47905083/how-to-check-number-of-channels-in-my-audio-wav-file-using-ffmpeg-command +# +# ffprobe -i /tmp/out.wav -show_entries stream=channels -select_streams a:0 -of compact=p=0:nk=1 -v 0 + +# for a right/left speaker test: +# https://askubuntu.com/questions/148363/which-linux-command-can-i-use-to-test-my-speakers-for-current-talk-radio-output +# p install alsa-utils +# speaker-test -t wav -c 2 -l 1 + +# There are 2 other options for audio, so I wanted to do a little +# performance measurement of this method. +# 1 is to combine the 2 audio sources in pulse, +# https://unix.stackexchange.com/questions/351764/create-combined-source-in-pulseaudio . +# 1 is to record mumble and combine in post processing. + +### benchmark / perf tests: these are pretty inaccurate. +# 29 seconds cpu use. video bitrate 1500k, 8 fps, 2x keyframe interval. +# * 64k vorbis: 69.7% +# * 128k vorbis: 70.1% (used in subsequent tests) +# * 1 audio input: 64.3% +# * 0 audio inputs: 59.2% + +# how I did perf testing: add -to 00:00:30 to ffmpeg opts to +# conveniently exit after measurement. Then run: +# +# ffmpeg "${opts[@]}" & +# pid=$! +# sleep 29 +# ps -p $pid -o %cpu +# kill %% + +# filter for only 1 audio input: +#-filter_complex "[0]azmq,volume=precision=fixed;[1]zmq='b=tcp\://127.0.0.1\:5557',drawbox=color=0x262626,drawtext=fontsize=90: fontcolor=beige: x=40: y=40: text=''" +# filter with 0 audio input: +# -filter_complex "[0]zmq='b=tcp\://127.0.0.1\:5557',drawbox=color=0x262626,drawtext=fontsize=90: fontcolor=beige: x=40: y=40: text=''" + + +# When things weren't working, I did some checking on newer ffmpeg to +# see if that helped. It never did. I compiled the latest ffmpeg release +# tarball, 7.0.1, and tried the version in debian bullseye by schrooting +# before running ffmpeg. Building was just configure; make, but then I +# found some flags that were needed. gpl flags r just because I noticed them. +# ./configure --enable-libzmq --enable-libpulse --enable-libvorbis --enable-gpl --enable-version3 +# + +### end background/development docs ### + if ! test "$BASH_VERSION"; then echo "error: shell is not bash" >&2; exit 1; fi shopt -s inherit_errexit 2>/dev/null ||: # ignore fail in bash < 4.4 @@ -32,12 +131,27 @@ set -eE -o pipefail trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" exit status: $?, PIPESTATUS: ${PIPESTATUS[*]}" >&2' ERR -# 3 mountpoints: fsf-sysops (public), fsf (default, all staff), fsf-tech (tech team) -case $1 in - sysops|tech) - mount_suffix=-$1 - ;; -esac +debug=false +loglevel=fatal + +# 3 mountpoints: fsf-sysops (default, public), fsf (all staff), fsf-tech (tech team) +# # note: duplicated in ffp +mount_suffix=-sysops +while [[ $1 ]]; do + case $1 in + sysops|tech) + mount_suffix=-$1 + ;; + staff) + mount_suffix= + ;; + -d) + debug=true + loglevel=debug + ;; + esac + shift +done host=live.iankelling.org:8000 if [[ $(dig +short @10.2.0.1 -x 10.2.0.2 2>&1 ||:) == kd.b8.nz. ]] \ @@ -66,31 +180,111 @@ else stream_res=$primary_res fi +framerate=8 +keyframe_interval=$((framerate * 2)) + +# Monitor of default sink. +# eg: alsa_output.usb-Audio-gd_Audio-gd-00.analog-stereo +pa_sink=$(pacmd list-sinks | awk '/\*/ {getline; print $2}' | sed 's/^$//').monitor opts=( - # nice to have: be a little less verbose + # global options + # be relatively quiet. switch to debug when testing. + -v $loglevel -hide_banner + -nostats + + # note: ordering of inputs also affects zmqsend commands. + + ## audio input options + + -f pulse + -name ffs + # note: duplicated above + -thread_queue_size 160 + -fragment_size 512 + -i default + + -f pulse + # this is for ffmpeg warnings. doesnt seem to affect latency. + -thread_queue_size 160 + # pulse knows this name somewhere + -name ffsdesktop + # This fixes latency. i haven't tried tuning it, but going too low creates + # choppy output. + -fragment_size 512 + -i "$pa_sink" + + + ## video input options -video_size $stream_res -f x11grab - -framerate 4 - # input options come before -i + -framerate $framerate -i :0.0+$x_offset.0 - -vf drawbox=color=black + + # Video + audio filter. Note: this has only the things we actually need in it. + # + # volume=precision=fixed fixes this error: + # The following filters could not choose their formats: Parsed_amerge_4. + # + # Default volume precision is float. Our input is fixed. maybe ffmpeg + # thinks the input could change and so can't commit to an output. + # The error suggests using aformat, which seems like it would probably + # also fix the error. + # + # man page say zmq url default includes "localhost", but specifying a + # localhost url caused an error for me. + -filter_complex "[0]azmq,volume=precision=fixed: volume=0 [vol0]; +[1]azmq='b=tcp\://127.0.0.1\:5556',volume=precision=fixed: volume=0 [vol1]; +[vol0][vol1] amerge=inputs=2 [out]; +[2]zmq='b=tcp\://127.0.0.1\:5557',drawbox=color=0x262626,drawtext=fontsize=90: fontcolor=beige: x=40: y=40: text=''" + + # Based on error message and poking around, it seems ffmpeg is not + # smart enough to see that [vol0] and [vol1] are inputs to the amerge + # filter, and thus we would not want them as final outputs. So, we + # have to identify the amerge output and pass it to -out. This + # identifier is called an "output pad" in man ffmpeg-filters, and a + # "link label" in man ffmpeg. + -map '[out]' + + # video output options -vcodec libvpx - -g 8 + -g $keyframe_interval -quality realtime + # for 1080p, default 256k is poor quality. 500 is ok. 1500 is a bit better. + -b:v 1500k -threads 2 + -buffer_duration 10 -error-resilient 1 + + ## audio output options + -c:a libvorbis + -b:a 128k + # afaik, this ensures that the amerge doesn't make 4 channel output if + # our output format supported it. + -ac 2 + -content_type video/webm -f webm icecast://source:$pass@$host/fsf$mount_suffix.webm - ) +rm -f /tmp/iank-ffmpeg-interlude-toggle + +# start muted +pactl set-source-mute @DEFAULT_SOURCE@ true + +#echo executing: ffmpeg ${opts[@]} + +#{ sleep 1; ffp &>/dev/null & } + +if $debug; then + ffmpeg "${opts[@]}" + exit 0 +fi -rm -f /tmp/iank-ffmpeg -mkfifo -m 0600 /tmp/iank-ffmpeg -echo executing: ffmpeg -stdin ${opts[@]} -# ffmpeg sits and waits until we do this. dunno why. whatever. -echo >/tmp/iank-ffmpeg & -ffmpeg ${opts[@]}