X-Git-Url: https://iankelling.org/git/?a=blobdiff_plain;f=ffs;h=253b83b9ec41e1585139c94e78daa69f6faa5738;hb=refs%2Fheads%2Fmaster;hp=0bb4ae7b94781a6c2792a078b91d58a0f227fc23;hpb=f27b67a1dfa58b5f101bba607b2f91a73e65299e;p=distro-setup diff --git a/ffs b/ffs index 0bb4ae7..728b77d 100755 --- a/ffs +++ b/ffs @@ -22,105 +22,9 @@ # ffs = ffmpeg stream -# todo: learn to start working in one corner of the screen. - -# potential improvement: it might be nice that we could have a tall terminal bug only use +# potential improvement: it might be nice that we could have a tall terminal but 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 @@ -130,12 +34,16 @@ trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" exit status: $?, PIPESTATUS: ${P usage() { cat <&2 + exit 1 + ;; + esac + ffp_args+=($1) +fi if $delay; then # 2500 gets us around a 4 second delay, up from 1.5s. @@ -215,12 +143,25 @@ fi ##### end command line parsing ######## -host=live.iankelling.org:8000 -if ip n show 10.2.0.1 | grep . &>/dev/null && \ - [[ $(dig +timeout=1 +short @10.2.0.1 -x 10.2.0.2 2>&1 ||:) == kd.b8.nz. ]]; then +host=live.iankelling.org:8443 +live_host=$(dig +timeout=1 +short @iankelling.org live.iankelling.org) +vps_host=$(dig +timeout=1 +short iankelling.org) +if [[ $live_host != "$vps_host" ]] && ip n show 10.2.0.1 | grep . &>/dev/null && \ + [[ $(dig +timeout=1 +short @10.2.0.1 -x 10.2.0.2 2>&1 ||:) == kd.b8.nz. ]]; then host=127.0.0.1:8000 + if ! pgrep '^icecast2$' >/dev/null; then + sudo systemctl start icecast2 + fi +else + find_prefix="ssh live.iankelling.org" fi +if $find_prefix find /var/icecast -type f | grep .; then + echo "warning: suggest clearing /var/icecast with icrmr or moving files. sleeping for 4 seconds" + sleep 4 +fi + + pass=$(sed -n 's/ *\([^<]*\).*/\1/p' /p/c/icecast.xml) @@ -248,7 +189,47 @@ else stream_res=$primary_res fi -framerate=8 +stream_x=${stream_res%x*} +stream_y=${stream_res#*x} + +# leave out our i3 window borders +stream_res=$(( stream_x - 4 ))x$(( stream_y - 4)) + + +# if hardware acceleration exists, use it to save power & cpu. +if vainfo |& grep -i VAProfileVP9Profile &>/dev/null; then + # 1500 seems almost flawless + bitrate_1080=1500 + + encode_settings=( + -c:v vp9_vaapi + # these options increase compression based on random internet reference. + -bsf:v vp9_raw_reorder,vp9_superframe + ) + # https://trac.ffmpeg.org/wiki/Hardware/VAAPI + global_extra_args=( + -vaapi_device /dev/dri/renderD128 + ) + extra_filter_arg=",format=nv12|vaapi,hwupload" +else + # 1000 is a bit blury, 1500 is pretty clear, 2000 makes scrolling + # adjust much faster, 2500 has marginal improvement on that. + # + # note https://livekit.io/webrtc/bitrate-guide (our framerate is lower) + bitrate_1080=2000 + + encode_settings=( + -vcodec libvpx + -quality realtime + -error-resilient 1 + ) +fi + +bitrate=$(( ( stream_x * stream_y ) / ( (1920*1080) / bitrate_1080 ) )) + + +# 8 seems fine. be conservative by going a bit higher. +framerate=10 keyframe_interval=$((framerate * 2)) # Monitor of default sink. @@ -267,6 +248,8 @@ opts=( -hide_banner -nostats + ${global_extra_args[@]} + # tested for decreasing latency: did not help. # -probesize 32 # tested for warning "Queue input is backward in time". did not help. @@ -312,13 +295,10 @@ opts=( # # 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]; + -filter_complex "[0]azmq,volume=precision=fixed: volume=$volume [vol0]; [1]azmq='b=tcp\://127.0.0.1\:5556',volume=precision=fixed: volume=0 [vol1]; [vol0][vol1] amerge=inputs=2; -[2]zmq='b=tcp\://127.0.0.1\:5557',drawbox=color=0x262626,drawtext=fontsize=90: fontcolor=beige: x=40: y=40: text=''${delay_arg}[out]" - -# [vol0][vol1] amerge=inputs=2,adelay=6000:all=1; - +[2]zmq='b=tcp\://127.0.0.1\:5557',drawbox=color=0x262626,drawtext=fontsize=90: fontcolor=beige: x=40: y=40: text=''${delay_arg}${extra_filter_arg}[out]" # An online source says to match a 5 second vid delay, we can do an # audio delay filter: "adelay=5000|5000". However, we already get @@ -335,13 +315,10 @@ opts=( -map '[out]' # video output options - -vcodec libvpx -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 - -error-resilient 1 + ${encode_settings[@]} + -b:v ${bitrate}k + ## audio output options -c:a libvorbis @@ -357,14 +334,15 @@ opts=( rm -f /tmp/iank-ffmpeg-interlude-toggle -# start muted -pactl set-source-mute @DEFAULT_SOURCE@ true +# system mute. disabled, just using application level mute atm. +# +# pactl set-source-mute @DEFAULT_SOURCE@ true if pkill -f ^ffmpeg.\*icecast://source.\*/fsf; then sleep 1 fi -#echo executing: ffmpeg ${opts[@]} +echo executing: ffmpeg ${opts[@]} #{ sleep 1; ffp &>/dev/null & } @@ -417,7 +395,7 @@ if [[ $mount_suffix == -sysops ]]; then touch $HOME/.iank-stream-on fi -echo true >$HOME/.iank-stream-muted +echo $volume >$HOME/.iank-stream-muted ffmpeg "${opts[@]}" & if $watch; then @@ -427,3 +405,95 @@ if $watch; then kill %% rm -f $HOME/.iank-stream-on fi + +### 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 +# + +# note: when playing back, text is going to look aliased unless you +# watch it in a window that is exactly as bit or bigger than the +# recording: tabbed i3 window shrinks things. or, use: mpv +# --video-unscaled + +### end background/development docs ###