Last active
December 12, 2025 21:42
-
-
Save donnaken15/98e665de860e95521f81c1fdb3907a8c to your computer and use it in GitHub Desktop.
Revisions
-
donnaken15 revised this gist
Dec 12, 2025 . 1 changed file with 83 additions and 51 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,11 +1,43 @@ #!/bin/zsh #set -e # exits early without pressing anything, POS (($# == 0)) && { # LOL # $((?)) also works, amazing # NOT IN NORMAL SHELL echo "No files entered"; exit 1 } function timefmt() { local h m s ms time="$(($1))" (( h = ((m = (s = (ms = ${time#-})) / 60) / 60) % 60, m %= 60, s %= 60, ms %= 1000, time < 0 )) && sign=- # wish i could cram this in one statement printf '%s%s%02d:%02d:%02d.%03d' "$2" "$sign" $h $m $s $ms #FIX!!: ##(( h = ((m = (s = ${time#-} / 1000) / 60) / 60) % 60, m %= 60, s %= 60, ms %= 1000, time < 0 )) && sign=- ##printf '%s%s%02d:%02d:%06.3f' "$2" "$sign" $h $m $s } function get_seconds() { valuefb="${(P)1:-${2:-00:00:00}}" if [[ "$valuefb" =~ ^((([0-9]+):)?([0-9]{1,2}):)?([0-9]{1,2}(\.[0-9]+)?)$ ]]; then (( $1 = ((match[3]*3600)+(match[4]*60)+match[5]) )) else (( $1 = "$valuefb" )) fi echo "Set $1 = `timefmt ${(P)1}`" } get_seconds start # seek to if [ ! -z "$end" ]; then get_seconds end "$start" (( limit = end - start )) else get_seconds limit '2:00:00' # seconds to shorten for skimming (testing) fi function userval() { export "$1"="${(P)1:-${2:-0}}" } # figure this out like audacity duration and truncate to userval sthres '-19.2dB' userval sdur 0.1 userval srem 0.1 userval nick 0 userval speed 1.19 (( limit <= 0 )) && exit 1; fargs=( # tfw draft preset -stats -stats_period 0.01 -c:v libvpx-vp9 -pix_fmt yuv444p -aspect 16:9 -crf 43 -qmin 28 -qmax 45 -vb 1100k -minrate 40k -maxrate 2500k -g 900 -bf 64 -refs 8 -threads 16 -tile-columns 6 -tile-rows 2 -row-mt 1 -deadline best -speed -16 -cpu-used -8 @@ -16,36 +48,40 @@ fargs=( # tfw draft preset -flags +qpel+mv4+aic+global_header -map_metadata -1 -ar 24k -c:a libopus -ab 56k -frame_duration 120 -vbr:a on -flags:a +bitexact -compression_level:a 10 -quality best -application voip -flush_packets 1 -max_muxing_queue_size 1 -blocksize 2048 ); cr=$'\r'; lf=$'\n'; imark='\[(silencedetect|Parsed_blackframe_[0-9]+) @ [0-9a-f]{16}\]' kv='( ([A-Za-z0-9_]+): ?([^ ]+))?'$cr?; god="( \|)?$kv"; timecode='([0-9]{2}):([0-9]{2}):([0-9]{2}\.[0-9]+)' comp='volume=-2dB,dynaudnorm' # broken (clips hardcore): acompressor=threshold=-9dB:ratio=5.1:attack=0.2:release=1.0:makeup=1 ((m_notice = 10.0)) # heads up warning (not using yet) ((m_lead = 0.3)) # seconds before/after detected frames ((m_trail = 1.9)) # minimal time skip (from last frame) because fatty has to get in that stupid word ((m_dist = 4.0)) # allowable distance between seconds before creating new cut, this should be a little more than reasonable ((cut_res = 30.0)) # trying hard to avoid video drifting, unironically doing more damage with more "bandaids" # bandages on my legs and my arms for you bandages bandages bandages # ive never had such strong contempt in my life for something as (ironically) insignificant as a freaking adjective # and its all because of you zoomer ******s, im on team flam now, oreo should neck fontparams='fontfile=c\\\:/g.ttf:fontsize=32' afix='pan=mono|c0=c0+c1,aresample=36k:async=0'; bthres='blend=difference,blackframe=94:38' # trailing 200ms visibility left with this # cut processing literally zooms when video is disabled, like a zoomer......... echo "\x1b[91mKILL FFMPEG IF IT GETS STUCK, BECAUSE IT'S BAD SOFTWARE!!!!!!\x1b[0m" alias readinto="read -r -d ''" cut_fmt='silence \x1b[92m%9.3f\x1b[97m ==> \x1b[92m%9.3f\x1b[0m, \x1b[97mcut \x1b[96m%6.3fs\x1b[0m, \x1b[97mtotal\x1b[0m: \x1b[95m%8.3f\x1b[0m, \x1b[97mcuts\x1b[0m: \x1b[93m%4d\x1b[0m\n' radixfn='# gemini, dgaf def shrinkint: def digits: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz !#$%&()*+,-./:;<=>?@^_`{|}~\u007f\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u0009\u000b\u000c\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f"; def radix: digits | length; def convert: if . == 0 then "" else ((. / radix | floor) | convert) + (digits[. % radix: (. % radix) + 1]) end; if . == 0 then "0" elif . > 0 then convert else error("shrinkint only works for non-negative integers") end;' #trap 'exit 1' INT TERM # leaves ffmpeg open # use kill -9 `jobs` if seriously trap 'wait; exit 1;' TERM # don't have cuts print past termination ((nick!=0)) && block=",drawbox=x=iw-w:y=ih-h+2:w=(iw*(1-0.66)):h=(ih*(1-0.58))+2:t=fill:c=red" for a in "$@"; do [ ! -f "$a" ] && { echo "Invalid or non-existent file: $a" continue } #date +'%F_%H-%M-%S.%3N' | readinto salt; salt="${salt//$cr/}" salt="$(timefmt "$((start+limit))" "`basename "$a"`_`timefmt "${start}"`--")"; salt="${salt//:/:}" base="`ffprobe -hide_banner -i "$a" -show_streams -print_format json | jq -c --arg start "$start" --arg limit "$limit" --arg "fname" "$a" '{ off: (\$start | tonumber), len: (\$limit | tonumber), sil: [], mas: [], str: .streams, fname: \$fname }'`" jq -nr --argjson base "$base" 'first($base.str.[] | select(.codec_type == "video")).index' | readinto v; v="${v//$cr/}" jq -ne --argjson base "$base" --argjson i "$v" '$base.str[$i].codec_type != "video"' >/dev/null && { echo 'This file does not have a video stream' @@ -58,7 +94,7 @@ for a in "$@"; do jq -n --indent 4 --argjson base "$base" '$base.str' continue } echo "offset `timefmt ${start}`:skim `timefmt ${limit}`:res 1/${cut_res}" scr="[0:a]$afix,$comp,silencedetect=n=$sthres:d=$sdur;"; sil=(); mas=(); tc=0.0 # total time cut # disable if not skimming nick's vods # 999999iq amogus: regex check to determine whose title is who's @@ -72,7 +108,8 @@ for a in "$@"; do #scr+="[1]nullsink" why=(-vn -t "$limit" -i "$a") fi cuts=0 ffmpeg -hide_banner -hwaccel dxva2 -v info -nostats -ss "$start" "${why[@]}" -lavfi "$scr" \ -threads 13 -f null nul 2>&1 | while read -r i; do # old: 96:32 if [[ "${i//$cr/}" =~ ${imark}${kv}${god}${god}${god}${god}${god} ]]; then @@ -89,10 +126,11 @@ for a in "$@"; do # inb4 associative array and fromentries to save time from subprocesses when building up item # or entries [ "$k" = 'silence_duration' ] && { (( cuts++ )) jq -nc --argjson r "$srem" '$ARGS.positional | map({key: .[0], value: .[1]}) | from_entries | . + {cut: ([$r,(.duration - $r)] | max)}' --jsonargs "${temp[@]}" | readinto test [[ "$test" =~ '"cut":'([0-9]+(\.[0-9]+)?) ]] && ((tc+=(match[1]))) && ( cut=($(jq -ncr --argjson r "$srem" --argjson j "$test" '$j | [.start, .end, .cut] | join(" ")' | tr -d '\r')) printf "$cut_fmt" "${cut[@]}" "$tc" "$cuts" ) & sil+=("${test//$cr/}") } @@ -123,54 +161,48 @@ for a in "$@"; do fi done wait why=(); (( hate=cut_res*1000, nick != 0 )) && { ((s=-1,end=-1,m_dist*=hate)) jq -nc -r '$ARGS.positional | .[].t' --jsonargs "${mas[@]}" | tr -d $'\r' | while read -r t; do ((s<(t*=hate)-m_dist)) && { ((s!=-1)) && why+=("$s $e"); ((s=t)) }; ((e=t)) done; ((s!=-1)) && why+=("$s $e") } jq -nc --argjson hate "$hate" --argjson r "$srem" --argjson j "$base" \ '$j|.sil = ($ARGS.positional | map([.start, .end, ([$r,.duration] | min/2)]))' --jsonargs "${sil[@]}" | \ jq -c --argjson hate "$hate" '.mas = ($ARGS.positional | map(. | split(" ")))' --args "${why[@]}" | readinto base; base="${base//$cr/}" echo 'writing detected data'; jq -nc --argjson j "$base" '$j' > "c:/skim_$salt.json" echo 'generating cut points'; jq -ncr \ --argjson hate "$((hate/cut_res))" --argjson ml "$m_lead" --argjson tb "$cut_res" \ --argjson mx "$limit" --argjson j "$base" --argjson mt "$m_trail" '($j | .sil | map( [ (.[0] + .[2]), (.[1] - .[2]) ] | map((. * $tb | round / $tb) * $hate | floor / $hate) ) | . + ( $j | .mas | map( [ (.[0] - $ml), (.[1] + $mt) ] ) ) ) | flatten | [0,0,0]+.+[$mx] | [ range(0; (length/2)) as $i | [ .[(2*$i)+0], .[(2*$i)+1], .[(2*$i)]-.[(2*$i)-1] ] ][1:] # i hate this language now, why cant this just be like actual javascript ' | readinto trim # halve silence buffer time and distribute (forgot what to write for why...probably something about preserving a little more of the end sound and start of a new one) # need to fix inverse ranges when srem < sdur splits="$(jq -nr --argjson t "$trim" '$t | length' | tr -d '\r')" blocks="$(jq -nr --argjson t "$trim" "$radixfn"'$t | to_entries | map("[a"+(.key | shrinkint)+"]") | join("")')" echo 'assembling graph' # crop=480:130:0:0 #range="trim='$start':'$((start+limit))'" tee "c:/skim_$salt.filt.txt" <<!! | ffmpeg -hide_banner -hwaccel dxva2 -v warning -stats -ss "$start" -t "$limit" -i "$a" -filter_complex_script pipe: "${fargs[@]}" -map '[right]' -map '[now]' "c:/skim_$salt.webm" -y && echo "--------- $a done (${pipestatus[@]})" [0:v]scale=640:-1,drawtext=text='%{pts\:hms}':${fontparams}:x=8:y=8:fontcolor=white:box=1:boxw=312:boxcolor=black@0.67,split=$splits${blocks}; [0:a]aformat=f=flt,asplit=$splits${blocks//\[a/[b};$(echo ' * splitting + trimming' >&2; jq -nr --arg fp "$fontparams" --argjson t "$trim" "$radixfn"'$t | to_entries | map( ("trim="+(.value | .[:2] | map(. | tostring) | join(":"))+",") as $trim | (.key | shrinkint) as $i | "[a"+$i+"]"+$trim+"setpts=PTS-STARTPTS,drawtext=text='$'\'''>> "+ ((.value[2] * 1000 | floor) | tostring | (((.|tonumber/1000|floor|tostring|length)-3) as $pad | " " | .[$pad:])+(("0"+.[0:-3]) | tonumber | tostring)+"."+(.[-3:]+"000" | .[:3]))+"s'$'\''':"+$fp+ ":x=180:y=8:fontcolor=lime[c"+$i+"];"+ "[b"+$i+"]a"+$trim+"asetpts=PTS-STARTPTS[d"+$i+"];" # \n <-- for "cleanliness" or something, even though \r and \n are part of radix now ) | join("")' | tr -d '\r')$(echo ' * concat-ing' >&2; jq -nr --argjson t "$trim" "$radixfn"'$t | to_entries | map((.key | shrinkint) as $i | ("[c"+$i+"][d"+$i+"]")) | join("")' | tr -d '\r'; echo 'rendering (no printing yet = seeking, maybe...)' >&2)concat=n=$splits:v=1:a=1[kys][die]; [kys]setpts='PTS/$speed'${block}[right];[die]$afix,$comp,atempo='$speed'[now]; !! # KILLS ITSELF AROUND 8 MINUTES (THE CRINGE IS THAT BAD), NO CRASH DUMP?! # offset pts done #-ss "$start" -t "$limit" -i "$a" -loop 1 \ # -i 'C:\dummy_target.jpg' -i 'C:\dummy_target2.jpg' -lavfi " # [0:a]$comp,silencedetect=n=-25dB:d=0.16,anullsink; # [1][0:v]scale2ref[why1][trash1]; -
donnaken15 revised this gist
Dec 8, 2025 . 1 changed file with 57 additions and 105 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -3,51 +3,48 @@ ((# == 0)) && { # LOL # $((?)) also works, amazing echo "No files entered"; exit 1 } hms=(00 00 00); (( speed=1.18, limit=9999999, delay=((hms[1]*3600)+(hms[2]*60)+hms[3]) )) # seek to unset hms; #limit=6000 # seconds to shorten for skimming (testing) fargs=( # tfw draft preset -stats -stats_period 0.01 -c:v libvpx-vp9 -pix_fmt yuv444p -aspect 16:9 -crf 43 -qmin 28 -qmax 45 -vb 1100k -minrate 40k -maxrate 2500k -g 900 -bf 64 -refs 8 -threads 16 -tile-columns 6 -tile-rows 2 -row-mt 1 -deadline best -speed -16 -cpu-used -8 -tune ssim -tune-content screen -corpus-complexity 10000 -enable-tpl 1 -rc_lookahead 25 -frame-parallel 0 -aq-mode 2 -arnr-strength 4 -arnr-maxframes 7 -arnr-type 3 -sharpness 4 -static-thresh 0 -color_primaries bt709 -color_trc bt709 -colorspace bt709 -auto-alt-ref 1 -color_range pc -bufsize 512M -lag-in-frames 25 -fflags +genpts+bitexact+nobuffer -flags +qpel+mv4+aic+global_header -map_metadata -1 -ar 24k -c:a libopus -ab 56k -frame_duration 120 -vbr:a on -flags:a +bitexact -compression_level:a 10 -quality best -application voip -flush_packets 1 -max_muxing_queue_size 1 -blocksize 2048 ); cr=$'\r'; lf=$'\n'; imark='\[(silencedetect|Parsed_blackframe_[0-9]+) @ [0-9a-f]{16}\]'; kv='( ([A-Za-z0-9_]+): ?([^ ]+))?'$cr?; god="( \|)?$kv"; comp='volume=-2dB,dynaudnorm' # broken (clips hardcore): acompressor=threshold=-9dB:ratio=5.1:attack=0.2:release=1.0:makeup=1 timecode='([0-9]{2}):([0-9]{2}):([0-9]{2}\.[0-9]+)'; sthres='-19.7dB'; ((sdur=0.13,srem=0.13,nick=0)); # figure this out like audacity duration and truncate to ((m_notice = 10.0)) # heads up warning (not using yet) ((m_lead = 0.3)) # seconds before/after detected frames ((m_trail = 1.9)) # minimal time skip (from last frame) because fatty has to get in that stupid word ((m_dist = 4.0)) # allowable distance between seconds before creating new cut, this should be a little more than reasonable ((cut_res = 30.0)) # trying hard to avoid video drifting, unironically doing more damage with more "bandaids" # bandages on my legs and my arms for you bandages bandages bandages # ive never had such strong contempt in my life for something as (ironically) insignificant as a freaking adjective # and its all because of you zoomer ******s, im on team flam now, oreo should neck fontparams='fontfile=e\\\:/Gossix.ttf:fontsize=32:box=1:boxcolor=black@0.6' afix='pan=mono|c0=c0+c1,aresample=32k:async=0'; bthres='blend=difference,blackframe=94:38' # trailing 200ms visibility left with this # cut processing literally zooms when video is disabled, like a zoomer......... echo "\x1b[91mKILL FFMPEG IF IT GETS STUCK, BECAUSE IT'S BAD SOFTWARE!!!!!!\x1b[0m" alias readinto="read -r -d ''" function timefmt() { local h m s ms time="$(($1))" (( h = ((m = (s = (ms = ${time#-})) / 60) / 60) % 60, m %= 60, s %= 60, ms %= 1000, time < 0 )) && sign=- # wish i could cram this in one statement printf '%s%s%02d:%02d:%02d.%03d' "$2" "$sign" $h $m $s $ms } #trap 'exit 1' INT TERM # leaves ffmpeg open # use kill -9 `jobs` if seriously trap 'wait; exit 1;' TERM # don't have cuts print past termination for a in "$@"; do [ ! -f "$a" ] && { echo "Invalid or non-existent file: $a" continue } date +'%F_%H-%M-%S.%3N' | readinto salt; salt="${salt//$cr/}" base="`ffprobe -hide_banner -i "$a" -show_streams -print_format json | jq -c --arg delay "$delay" --arg limit "$limit" --arg "fname" "$a" '{ off: (\$delay | tonumber), len: (\$limit | tonumber), sil: [], mas: [], str: .streams, fname: \$fname }'`" jq -nr --argjson base "$base" 'first($base.str.[] | select(.codec_type == "video")).index' | readinto v; v="${v//$cr/}" jq -ne --argjson base "$base" --argjson i "$v" '$base.str[$i].codec_type != "video"' >/dev/null && { @@ -66,7 +63,8 @@ for a in "$@"; do # disable if not skimming nick's vods # 999999iq amogus: regex check to determine whose title is who's # now that i think about it, graph time shouldnt be noticeable if printing is # nonblocking, so it'll keep going while the read loop takes its sweet @$$ time....maybe... # ...just going off the fact that cpu usage doesn't pause when marking if ((nick!=0)); then scr+="[1][0:v]scale2ref[why1][trash1];[trash1][why1]$bthres" why=( -t "$limit" -i "$a" -loop 1 -t "$limit" -i 'C:/dummy_target.jpg') @@ -88,28 +86,26 @@ for a in "$@"; do [ -z "$k" ] && break; [ "$k" = 'silence_start' -o "$k" = 'frame' ] && temp=() [[ "$k" = silence_* ]] && { # redundant temp+=("[\"${k:8}\",$v]") # inb4 associative array and fromentries to save time from subprocesses when building up item # or entries [ "$k" = 'silence_duration' ] && { jq -nc --argjson r "$srem" '$ARGS.positional | map({key: .[0], value: .[1]}) | from_entries | . + {cut: ([$r,(.duration - $r)] | max)}' --jsonargs "${temp[@]}" | readinto test [[ "$test" =~ '"cut":'([0-9]+(\.[0-9]+)?) ]] && ((tc+=(match[1]))) && ( cut=($(jq -ncr --argjson r "$srem" --argjson j "$test" '$j | [.start, .end, .cut] | join(" ")' | tr -d '\r')) printf 'silence \x1b[92m%9.3f\x1b[97m ==> \x1b[92m%9.3f\x1b[0m, \x1b[97mcut \x1b[96m%6.3fs\x1b[0m, total: \x1b[95m%8.3f\x1b[0m\n' "${cut[@]}" "$tc" ) & sil+=("${test//$cr/}") } continue } [[ "$filt" = Parsed_blackframe_[0-9]* ]] && { temp+=("[\"$k\",$v]") [ "$k" = 'last_keyframe' ] && { jq -nc '$ARGS.positional | from_entries' --jsonargs "${temp[@]}" | readinto test jq -ncr --argjson hate "$hate" --argjson j "$test" '$j | "\u001b[97mBAD: \u001b[91m"+ (.t | strftime("%H:%M:%S.")+((.*$hate%$hate+$hate)|tostring|.[1:]))+ "\u001b[0m"' & mas+=("${test//$cr/}") } continue @@ -137,94 +133,50 @@ for a in "$@"; do '$j|.sil = ($ARGS.positional | map([.start, .end, ([$r,.duration] | min/2)]))' \ --jsonargs "${sil[@]}" | \ jq -c --argjson hate "$hate" '.mas = ($ARGS.positional | map(. | split(" ")))' --args "${why[@]}" | readinto base; base="${base//$cr/}" echo 'writing detected data'; jq -nc --argjson j "$base" '$j' > "c:/skim_$salt.json" ((nick!=0)) && block=",drawbox=x=iw-w:y=ih-h+2:w=(iw*(1-0.66)):h=(ih*(1-0.58))+2:t=fill:c=red" echo 'generating cut points'; jq -ncr \ --argjson hate "$((hate/cut_res))" --argjson ml "$m_lead" --argjson tb "$cut_res" \ --argjson mx "$limit" --argjson j "$base" --argjson mt "$m_trail" \ '($j | .sil | map( [ (.[0] + .[2]), (.[1] - .[2]) ] | map((. * $tb | round / $tb) * $hate | floor / $hate) ) | . + ( $j | .mas | map( [ (.[0] - $ml), (.[1] + $mt) ] ) ) ) | flatten | [0,0,0]+.+[$mx] | [ range(0; (length/2)) as $i | [ .[(2*$i)+0], .[(2*$i)+1], .[(2*$i)]-.[(2*$i)-1] ] ][1:] # i hate this language now, why cant this just be like actual javascript ' | readinto trim # halve silence buffer time and distribute (forgot what to write for why...probably something about preserving a little more of the end sound and start of a new one) # need to fix inverse ranges when srem < sdur splits="$(jq -nr --argjson t "$trim" '$t | length' | tr -d '\r')" blocks="$(jq -nr --argjson t "$trim" '$t | to_entries | map("[v"+(.key | tostring)+"s]") | join("")')" echo 'assembling graph, rendering (no printing yet = seeking, maybe...)' # crop=480:130:0:0 #range="trim='$delay':'$((delay+limit))'" tee "c:/skim_$salt.filt.txt" <<!! | ffmpeg -hide_banner -hwaccel dxva2 -v warning -stats -ss "$delay" -t "$limit" -i "$a" -filter_complex_script pipe: "${fargs[@]}" -map '[right]' -map '[now]' "c:/skim_$salt.webm" -y && echo "--------- $a done (${pipestatus[@]})" [0:v]scale=-1:360,drawtext=text='%{pts\:hms}':${fontparams}:x=8:y=8:fontcolor=white${block}, split=$splits${blocks}; [0:a]aformat=f=flt,asplit=$splits${blocks//v/a}; $(jq -nr --arg fp "$fontparams" --argjson t "$trim" ' $t | to_entries | map( ("trim="+(.value | .[:2] | map(. | tostring) | join(":"))+",") as $trim | (.key | tostring) as $i | "[v"+$i+"s]"+$trim+"setpts=PTS-STARTPTS,drawtext=text='$'\''' >> "+ ((.value[2] * 1000 | floor) | tostring | (((.|tonumber/1000|floor|tostring|length)-3) as $pad | " " | .[$pad:])+(("0"+.[0:-3]) | tonumber | tostring)+"."+(.[-3:]+"000" | .[:3]))+"s'$'\''':"+$fp+ ":x=162:y=8:fontcolor=lime[v"+$i+"c];"+ "[a"+$i+"s]a"+$trim+"asetpts=PTS-STARTPTS[a"+$i+"c];\n" ) | join("")' | tr -d '\r')$(jq -nr --argjson t "$trim" ' $t | to_entries | map((.key | tostring) as $i | ("[v"+$i+"c][a"+$i+"c]")) | join("")' | tr -d '\r')concat=n=$splits:v=1:a=1[kys][die]; [kys]setpts='PTS/$speed'[right]; [die]$afix,$comp,atempo='$speed'[now]; !! # KILLS ITSELF AROUND 8 MINUTES (THE CRINGE IS THAT BAD), NO CRASH DUMP?! # offset pts done #-ss "$delay" -t "$limit" -i "$a" -loop 1 \ # -i 'C:\dummy_target.jpg' -i 'C:\dummy_target2.jpg' -lavfi " # [0:a]$comp,silencedetect=n=-25dB:d=0.16,anullsink; # [1][0:v]scale2ref[why1][trash1]; # [2][trash1]scale2ref[why2][trash2]; # [trash1][why1]$bthresh,nullsink; # [trash2][why2]$bthresh #" -f null nul 2>&1 | while read -r i; do # USES 7 GB COMMIT JUST FOR A SECOND COMPARISON FRAME WTFFFFFFF -
donnaken15 revised this gist
Dec 8, 2025 . 1 changed file with 84 additions and 43 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,11 +1,10 @@ #!/bin/zsh #set -e # exits early without pressing anything, POS ((# == 0)) && { # LOL # $((?)) also works, amazing echo "No files entered"; exit 1 } # accodomate for instances of <> 30fps or figure out how to change fps before processing my full graph hms=(00 00 00); (( speed=1.18, limit=9999999, delay=((hms[1]*3600)+(hms[2]*60)+hms[3]) )) # seek to unset hms; limit=5400 # seconds to shorten for skimming (testing) fargs=( # tfw draft preset -stats -stats_period 0.01 -c:v libvpx-vp9 -pix_fmt yuv444p -aspect 16:9 @@ -14,51 +13,56 @@ fargs=( # tfw draft preset -tune ssim -tune-content screen -corpus-complexity 10000 -enable-tpl 1 -rc_lookahead 25 -frame-parallel 0 -aq-mode 0 -arnr-strength 4 -arnr-maxframes 7 -arnr-type 3 -sharpness 4 -static-thresh 0 -color_primaries bt709 -color_trc bt709 -colorspace bt709 -auto-alt-ref 1 -color_range pc -bufsize 512M -lag-in-frames 25 -fflags +genpts+bitexact+nobuffer -flags +qpel+mv4+aic+global_header -map_metadata -1 -ar 24k -c:a libopus -ab 66k -frame_duration 120 -vbr:a on -flags:a +bitexact -compression_level:a 10 -quality best -application voip -flush_packets 1 -max_muxing_queue_size 1 -blocksize 2048 ) cr=$'\r'; lf=$'\n'; ins='$b + { $k: ($v|tonumber? // .) }'; imark='\[(silencedetect|Parsed_blackframe_[0-9]+) @ [0-9a-f]{16}\]' kv='( ([A-Za-z0-9_]+): ?([^ ]+))?'$cr?; stupid='( \|)?'; god="$stupid$kv"; temp='{}'; profile=(); getdur='.streams[$v] | .tags.DURATION // .duration' comp='volume=-2dB,dynaudnorm' # broken: acompressor=threshold=-9dB:ratio=5.1:attack=0.2:release=1.0:makeup=1 #trap 'exit 1' INT TERM # leaves ffmpeg open # use kill -9 `jobs` if seriously timecode='([0-9]{2}):([0-9]{2}):([0-9]{2}\.[0-9]+)'; sthres='-20.1dB'; ((sdur=0.16,srem=0.2,nick=0)); # figure this out like audacity duration and truncate to ((m_notice = 10.0)) # heads up warning (not using yet) ((m_lead = 0.3)) # seconds before/after detected frames ((m_trail = 1.9)) # minimal time skip (from last frame) because fatty has to get in that stupid word ((m_dist = 4.0)) # allowable distance between seconds before creating new cut, this should be a little more than reasonable ((cut_res = 30.0)) # trying hard to avoid video drifting, unironically doing more damage with more "bandaids" # ive never had such strong contempt in my life for something as (ironically) insignificant as a freaking adjective # and its all because of you zoomer ******s, im on team flam now, oreo should neck afix='pan=mono|c0=c0+c1,aresample=32k:async=0'; bthres='blend=difference,blackframe=94:38' # trailing 200ms visibility left with this #profile=(time -f"%E") # not useful rn, keeps showing 0.01s, probably if subprocess management stuff isn't actually accounted for # cut processing literally zooms when video is disabled, like a zoomer......... echo "\x1b[91mKILL FFMPEG IF IT GETS STUCK, BECAUSE IT'S BAD SOFTWARE!!!!!!\x1b[0m" alias readinto="read -r -d ''" function timefmt() { local h m s ms time (( h = ((m = (s = (ms = $(($1)))) / 60) / 60) % 60, m %= 60, s %= 60, ms %= 1000 )) # wish i could cram this in one statement printf '%s%02d:%02d:%02d.%03d' "$2" $h $m $s $ms } trap 'wait; exit 1;' TERM # don't have cuts print past termination for a in "$@"; do [ ! -f "$a" ] && { echo "Invalid or non-existent file: $a" continue } date --date="TZ=\"%TZ%\" now" +'%F_%H-%M-%S.%3N' | readinto salt; salt="${salt//$cr/}" base="`ffprobe -hide_banner -i "$a" -show_streams -print_format json | jq -c --arg delay "$delay" --arg limit "$limit" --arg "fname" "$a" '{ off: (\$delay | tonumber), len: (\$limit | tonumber), sil: [], mas: [], str: .streams, fname: \$fname }'`" jq -nr --argjson base "$base" 'first($base.str.[] | select(.codec_type == "video")).index' | readinto v; v="${v//$cr/}" jq -ne --argjson base "$base" --argjson i "$v" '$base.str[$i].codec_type != "video"' >/dev/null && { echo 'This file does not have a video stream' jq -n --indent 4 --argjson base "$base" '$base.str' continue } cut_res="$(jq -nr --argjson base "$base" --argjson i "$v" '$base.str[$i].r_frame_rate' | tr -d '\r')" && \ echo "FPS eval: $cut_res" && cut_res=$(($cut_res)) || { echo 'Something went wrong when parsing frame rate' jq -n --indent 4 --argjson base "$base" '$base.str' continue } echo "offset `timefmt ${delay}`:skim `timefmt ${limit}`:res 1/${cut_res}" scr="[0:a]$afix,$comp,silencedetect=n=$sthres:d=$sdur;"; sil=(); mas=(); tc=0.0 # total time cut # disable if not skimming nick's vods # 999999iq amogus: regex check to determine whose title is who's # now that i think about it, graph time shouldnt be noticeable if printing is @@ -70,9 +74,8 @@ for a in "$@"; do #scr+="[1]nullsink" why=(-vn -t "$limit" -i "$a") fi ffmpeg -hide_banner -hwaccel dxva2 -v info -nostats -ss "$delay" "${why[@]}" -lavfi "$scr" \ -threads 13 -f null nul 2>&1 | while read -r i; do # old: 96:32 if [[ "${i//$cr/}" =~ ${imark}${kv}${god}${god}${god}${god}${god} ]]; then filt="${match[1]}" @@ -81,28 +84,33 @@ for a in "$@"; do Parsed_blackframe_[0-9]*) ;& silencedetect) for ((y=0;y<6;y++)); do ((x=3+(y*4))); k="${match[x]}"; v="${match[++x]}" [ -z "$k" ] && break; [ "$k" = 'silence_start' -o "$k" = 'frame' ] && temp=() [[ "$k" = silence_* ]] && { # redundant temp+=("[\"${k:8}\",$v]") #"${profile[@]}" jq -nc --arg k "${k:8}" --arg v "$v" --argjson b "$temp" "$ins" | readinto temp # inb4 associative array and fromentries to save time from subprocesses when building up item # or entries [ "$k" = 'silence_duration' ] && { jq -nc --argjson r "$srem" '$ARGS.positional | map({key: .[0], value: .[1]}) | from_entries | . + {cut: ([$r,(.duration - $r)] | max)}' --jsonargs "${temp[@]}" | readinto test [[ "$test" =~ '"cut":'([0-9]+(\.[0-9]+)?) ]] && ((tc+=(match[1]))) && ( cut=($(jq -ncr --argjson r "$srem" --argjson j "$test" '$j | [.start, .end, .cut] | join(" ")' | tr -d '\r')) "${profile[@]}" printf 'silence \x1b[92m%9.3f\x1b[97m ==> \x1b[92m%9.3f\x1b[0m, \x1b[97mcut \x1b[96m%6.3fs\x1b[0m, total: \x1b[95m%8.3f\x1b[0m\n' "${cut[@]}" "$tc" ) & sil+=("${test//$cr/}") } continue } [[ "$filt" = Parsed_blackframe_[0-9]* ]] && { temp+=("[\"$k\",$v]") #"${profile[@]}" jq -nc --arg k "$k" --arg v "$v" --argjson b "$temp" "$ins" | readinto temp [ "$k" = 'last_keyframe' ] && { jq -nc '$ARGS.positional | from_entries' --jsonargs "${temp[@]}" | readinto test "${profile[@]}" jq -ncr --argjson hate "$hate" --argjson j "$test" '$j | "\u001b[97mBAD: \u001b[91m"+ (.t | strftime("%H:%M:%S.")+((.*$hate%$hate+$hate)|tostring|.[1:]))+ "\u001b[0m"' mas+=("${test//$cr/}") } continue } @@ -118,7 +126,8 @@ for a in "$@"; do fi fi done wait why=(); ((start=-1,end=-1,hate=cut_res*100000,m_dist*=hate)) jq -nc -r '$ARGS.positional | .[].t' --jsonargs "${mas[@]}" | tr -d $'\r' | while read -r t; do ((start<(t*=hate)-m_dist)) && { ((start!=-1)) && why+=("$start $end"); ((start=t)) @@ -127,13 +136,12 @@ for a in "$@"; do jq -nc --argjson hate "$hate" --argjson r "$srem" --argjson j "$base" \ '$j|.sil = ($ARGS.positional | map([.start, .end, ([$r,.duration] | min/2)]))' \ --jsonargs "${sil[@]}" | \ jq -c --argjson hate "$hate" '.mas = ($ARGS.positional | map(. | split(" ")))' --args "${why[@]}" | readinto base; base="${base//$cr/}" #jq -nc --tab --argjson j "$base" '$j' echo 'writing detected data'; jq -nc --argjson j "$base" '$j' > "c:/skim_$salt.json" echo 'generating cut points'; trim="select='not($(jq -ncr \ --argjson hate "$hate" --argjson ml "$m_lead" --argjson tb "$cut_res" \ --argjson mx "$limit" --argjson j "$base" --argjson mt "$m_trail" \ '$j | .sil | map( "between(t," + (((.[0] + .[2]) * $tb | round / $tb) * $hate | floor / $hate | tostring) + "," + @@ -147,18 +155,51 @@ for a in "$@"; do ")" ) ) + ["0"] | "\n"+join("+")' | tr -d '\r' ))'" # halve silence buffer time and distribute (forgot what to write for why...probably something about preserving a little more of the end sound and start of a new one) # need to fix inverse ranges #range="trim='$delay':'$((delay+limit))'" # life saver: https://stackoverflow.com/questions/64866231 # everyone/everything else is so unhelpful and useless ((nick!=0)) && block=",drawbox=x=iw-w:y=ih-h+2:w=(iw*(1-0.66)):h=(ih*(1-0.58))+2:t=fill:c=red" # sounds stupid and is probably impossible but try outputting to nul # to get the video and audio stream lengths.........???????? does bsf apply afterwards? likely would have to echo 'rendering (no printing yet = seeking, maybe...)' # crop=480:130:0:0 # FFMPEG 8 COMPLETELY BREAKS ASELECT, WHY WHY WHY WHY WHY WHY WHY WHY WHY WHY WHY?!?!?!?!?!?!?!?!?! tee "c:/skim_$salt.filt.txt" <<!! | ffmpeg7 -hide_banner -hwaccel dxva2 -v warning -stats -ss "$delay" -t "$limit" -i "$a" -filter_complex_script pipe: "${fargs[@]}" "c:/skim_$salt.webm" -y && echo "--------- $a done (${pipestatus[1]}|${pipestatus[2]})" [0:v]scale=560:-1, drawtext=text='%{pts\:hms}':fontfile=e\\\:/Gossix.ttf:fontsize=32:fontcolor=white:x=8:y=8:box=1:boxcolor=black@0.6, ${trim},setpts=(N/FRAME_RATE/TB)/$speed${block}; [0:a]aformat=f=flt,$afix,a${trim},atempo=$speed,$comp; !! for s in v0 a1; do echo "${s[0]},${s[1]}" tl="${s:0:1}l" ffprobe -v error -i "c:/skim_$salt.webm" -show_streams -print_format json | \ jq -r --argjson v "${s:1:1}" "$getdur" | tr -d $'\r' | readinto "$tl" if [[ "${(P)tl}" =~ $timecode ]]; then # merge into above probably (( ${tl} = (match[1]*3600) + (match[2]*60) + match[3] )) elif [[ "${(P)tl}" =~ [0-9]+\.[0-9]+ ]]; then : ${(P)tl::=$MATCH} else continue fi done #if [[ "$vl" =~ $timecode ]]; then # merge into above probably # (( vl = (match[1]*3600) + (match[2]*60) + match[3] )) #elif [[ "$vl" =~ [0-9]+\.[0-9]+ ]]; then # vl="${MATCH}" #else # continue #fi; if [[ "$al" =~ $timecode ]]; then # (( al = (match[1]*3600) + (match[2]*60) + match[3] )) #elif [[ "$al" =~ [0-9]+\.[0-9]+ ]]; then # al="${MATCH}" #else # continue #fi echo "desync: v=`timefmt $vl` a=`timefmt $al` drift=`timefmt $((vl-al))`" ffmpeg -hide_banner -v warning -i "c:/skim_$salt.webm" -c:v copy -c:a copy -bsf:v "setts=PTS/$(((vl/al)*1.02))" "c:/skim__$salt.webm" -y cp -f "c:/skim__$salt.webm" "c:/skim_$salt.webm"; rm -f "c:/skim__$salt.webm" # KILLS ITSELF AROUND 8 MINUTES (THE CRINGE IS THAT BAD), NO CRASH DUMP?! # offset pts done -
donnaken15 revised this gist
Nov 21, 2025 . 1 changed file with 54 additions and 30 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,31 +1,35 @@ #!/bin/zsh #set -e # exits early without pressing anything, POS ((# == 0)) && { # LOL # $((?)) also works, amazing echo "No files entered" exit 1 } # accodomate for instances of <> 30fps or figure out how to change fps before processing my full graph hms=(01 22 05); (( speed=1.18, limit=9999999, delay=((hms[1]*3600)+(hms[2]*60)+hms[3]) )) # seek to unset hms; limit=5400 # seconds to shorten for skimming (testing) fargs=( # tfw draft preset -stats -stats_period 0.01 -c:v libvpx-vp9 -pix_fmt yuv444p -aspect 16:9 -crf 43 -qmin 28 -qmax 45 -vb 1100k -minrate 40k -maxrate 2500k -g 900 -bf 64 -refs 8 -threads 16 -tile-columns 6 -tile-rows 2 -row-mt 1 -deadline best -speed -16 -cpu-used -8 -tune ssim -tune-content screen -corpus-complexity 10000 -enable-tpl 1 -rc_lookahead 25 -frame-parallel 0 -aq-mode 0 -arnr-strength 4 -arnr-maxframes 7 -arnr-type 3 -sharpness 4 -static-thresh 0 -color_primaries bt709 -color_trc bt709 -colorspace bt709 -auto-alt-ref 1 -color_range pc -bufsize 512M -lag-in-frames 25 -fflags +genpts+bitexact -flags +qpel+mv4+aic+global_header -map_metadata -1 -ar 24k -c:a libopus -ab 66k -frame_duration 120 -vbr:a on -flags:a +bitexact -compression_level:a 10 -quality best -application voip -flush_packets 1 -max_muxing_queue_size 1 -fflags nobuffer -blocksize 2048 ) cr=$'\r'; lf=$'\n'; ins='$b + { $k: ($v|tonumber? // .) }' imark='\[(silencedetect|Parsed_blackframe_[0-9]+) @ [0-9a-f]{16}\]' kv='( ([A-Za-z0-9_]+): ?([^ ]+))?'$cr?; stupid='( \|)?'; god="$stupid$kv"; temp='{}' comp='volume=-2dB,dynaudnorm' # broken: acompressor=threshold=-9dB:ratio=5.1:attack=0.2:release=1.0:makeup=1 #trap 'exit 1' INT TERM # leaves ffmpeg open # use kill -9 `jobs` if seriously sthres='-20.0dB'; ((sdur=0.16,srem=0.2,nick=0)); # figure this out like audacity duration and truncate to ((m_notice = 10.0)) # heads up warning (not using yet) ((m_lead = 0.3)) # seconds before/after detected frames ((m_trail = 1.9)) # minimal time skip (from last frame) because fatty has to get in that stupid word ((m_dist = 4.0)) # allowable distance between seconds before creating new cut, this should be a little more than reasonable ((cut_res = 30.0)) # trying hard to avoid video drifting, unironically doing more damage with more "bandaids" # ive never had such strong contempt in my life for something as (ironically) insignificant as a freaking adjective # and its all because of you zoomer ******s, im on team flam now, oreo should neck bthres='blend=difference,blackframe=94:38' # trailing 200ms visibility left with this @@ -37,10 +41,22 @@ echo "\x1b[91mKILL FFMPEG IF IT GETS STUCK, BECAUSE IT'S BAD SOFTWARE!!!!!!\x1b[ alias readinto="tr -d '\r' | read -r -d ''" for a in "$@"; do [ ! -f "$a" ] && { echo "Invalid or non-existent file: $a" continue } base="`ffprobe -hide_banner -i "$a" -show_streams -print_format json | jq -c --arg delay "$delay" --arg limit "$limit" '{ off: (\$delay | tonumber), len: (\$limit | tonumber), sil: [], mas: [], str: .streams }'`" jq -nr --argjson base "$base" 'first($base.str.[] | select(.codec_type == "video")).index' | readinto v jq -ne --argjson base "$base" --argjson i "$v" '$base.str[$i].codec_type != "video"' >/dev/null && { echo "This file does not have a video stream" jq -n --indent 4 --argjson base "$base" '$base.str' continue } cut_res="$(jq -nr --argjson base "$base" --argjson i "$v" '$base.str[$i].r_frame_rate' | tr -d '\r')" && \ echo "FPS eval: $cut_res" && cut_res=$(($cut_res)) || { echo "Something went wrong when parsing frame rate" jq -n --indent 4 --argjson base "$base" '$base.str' continue } sil=(); mas=(); tc=0.0 # total time cut scr="[0:a]$afix,$comp,silencedetect=n=$sthres:d=$sdur;" # disable if not skimming nick's vods @@ -71,8 +87,9 @@ for a in "$@"; do [[ "$k" = silence_* ]] && { # redundant "${profile[@]}" jq -nc --arg k "${k:8}" --arg v "$v" --argjson b "$temp" "$ins" | readinto temp # inb4 associative array and fromentries to save time from subprocesses when building up item # or entries [ "$k" = 'silence_duration' ] && { cut=($(jq -ncr --argjson r "$srem" --argjson j "$temp" '$j | [.start, .end, ([$r,(.duration - $r)] | max)] | join(" ")' | tr -d '\r')) "${profile[@]}" printf 'silence \x1b[92m%9.3f\x1b[97m ==> \x1b[92m%9.3f\x1b[0m, \x1b[97mcut \x1b[96m%6.3fs\x1b[0m, total: \x1b[95m%8.3f\x1b[0m\n' "${cut[@]}" "$((tc+=(cut[3])))" sil+=("$temp") } @@ -107,16 +124,20 @@ for a in "$@"; do ((start!=-1)) && why+=("$start $end"); ((start=t)) }; ((end=t)) done; ((start!=-1)) && why+=("$start $end") jq -nc --argjson hate "$hate" --argjson r "$srem" --argjson j "$base" \ '$j|.sil = ($ARGS.positional | map([.start, .end, ([$r,.duration] | min/2)]))' \ --jsonargs "${sil[@]}" | \ jq -c --argjson hate "$hate" '.mas = ($ARGS.positional | map(. | split(" ")))' --args "${why[@]}" | readinto base #jq -nc --tab --argjson j "$base" '$j' date --date="TZ=\"%TZ%\" now" +'%F_%H-%M-%S.%3N' | readinto salt echo 'writing detected data'; jq -nc --argjson j "$base" '$j' > "c:/skim_$salt.json" echo 'generating cut points'; trim="select='not($(jq -ncr \ --argjson hate "$hate" --argjson ml "$m_lead" --argjson tb "$cut_res" \ --argjson j "$base" --argjson mt "$m_trail" \ '$j | .sil | map( "between(t," + (((.[0] + .[2]) * $tb | round / $tb) * $hate | floor / $hate | tostring) + "," + (((.[1] - .[2]) * $tb | round / $tb) * $hate | floor / $hate | tostring) + ")" ) | . + ( $j | .mas | map( @@ -126,21 +147,24 @@ for a in "$@"; do ")" ) ) + ["0"] | "\n"+join("+")' | tr -d '\r' ))'" # halve silence buffer time and distribute (forgot what to write for why...) piss='setpts=N/FRAME_RATE/TB' # life saver: https://stackoverflow.com/questions/64866231 # everyone/everything else is so unhelpful and useless ((nick!=0)) && block="drawbox=x=iw-w:y=ih-h+2:w=(iw*(1-0.66)):h=(ih*(1-0.58))+2:t=fill:c=red," echo 'rendering (no printing yet = seeking, maybe...)' # crop=480:130:0:0 tee "c:/skim_$salt.filt.txt" <<!! | ffmpeg -hide_banner -hwaccel dxva2 -v verbose -stats -ss "$delay" -i "$a" -t "$(((limit/speed)-tc))" -filter_complex_script pipe: "${fargs[@]}" "c:/skim_$salt.webm" -y [0:v]scale=-1:360,${block} drawtext=text='%{pts\:hms}':fontfile=e\\\:/Gossix.ttf:fontsize=32:fontcolor=white:x=0:y=16:box=1:boxcolor=black@0.6, ${trim},setpts=N/FRAME_RATE/TB,setpts=PTS/$speed; [0:a]$afix,aformat=f=flt,a${trim},asetpts=N/FRAME_RATE/TB,atempo=$speed,$comp; !! # KILLS ITSELF AROUND 8 MINUTES (THE CRINGE IS THAT BAD), NO CRASH DUMP?! # offset pts done # %{localtime} # -vf "scale=480:-1,drawbox=x=iw-w:y=ih-h+2:w=(iw*(1-0.66)):h=(ih*(1-0.58))+2:t=fill:c=red, # drawtext=text='%{pts\:hms}':fontfile=e\\\:/Gossix.ttf:fontsize=32:fontcolor=white:x=8:y=8:box=1:boxcolor=black@0.6, # ${trim},${piss},setpts=PTS/$speed" \ -
donnaken15 revised this gist
Nov 15, 2025 . 1 changed file with 59 additions and 48 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,8 +1,7 @@ #!/bin/zsh #set -e # exits early without pressing anything, POS ((speed=1.18,limit=9999999,delay=900)) # seconds in limit=2400 # seconds to shorten for skimming (testing) fargs=( -stats -stats_period 0.01 -c:v libvpx-vp9 -pix_fmt yuv444p -crf 43 -qmin 28 -qmax 45 -vb 1100k -minrate 40k -maxrate 2500k -g 900 -bf 64 -refs 8 @@ -20,18 +19,20 @@ cr=$'\r'; lf=$'\n'; ins='$b + { $k: ($v|tonumber? // .) }' imark='\[(silencedetect|Parsed_blackframe_[0-9]+) @ [0-9a-f]{16}\]' kv='( ([A-Za-z0-9_]+): ?([^ ]+))?'$cr?; stupid='( \|)?'; god="$stupid$kv"; temp='{}'; comp='volume=-2dB,dynaudnorm' # broken: acompressor=threshold=-9dB:ratio=5.1:attack=0.2:release=1.0:makeup=1 #trap 'exit 1' INT TERM # leaves ffmpeg open # use kill -9 `jobs` if seriously sthres='-20dB'; ((sdur=0.16,srem=0.18,nick=0)); ((m_notice = 10.0 )) # heads up warning ((m_lead = 0.3 )) # seconds before/after detected frames ((m_trail = 1.9 )) # minimal time skip (from last frame) because fatty has to get in that stupid word ((m_dist = 4 )) # allowable distance between seconds before creating new cut, this should be a little more than reasonable ((cut_res = 30 )) # trying hard to avoid video drifting # ive never had such strong contempt in my life for something as (ironically) insignificant as a freaking adjective # and its all because of you zoomer ******s, im on team flam now, oreo should neck bthres='blend=difference,blackframe=94:38' # trailing 200ms visibility left with this afix='pan=mono|c0=c0+c1,aresample=32k' profile=() #profile=(time -f"%E") # not useful rn, keeps showing 0.01s, probably if subprocess management stuff isn't actually accounted for # cut processing literally zooms when video is disabled, like a zoomer......... echo "\x1b[91mKILL FFMPEG IF IT GETS STUCK, BECAUSE IT'S BAD SOFTWARE!!!!!!\x1b[0m" alias readinto="tr -d '\r' | read -r -d ''" for a in "$@"; do @@ -41,12 +42,21 @@ for a in "$@"; do } base="`ffprobe -hide_banner -i "$a" -show_streams -print_format json | jq -c --arg delay "$delay" '{ off: (\$delay | tonumber), sil: [], mas: [], str: .streams }'`" sil=(); mas=(); tc=0.0 # total time cut scr="[0:a]$afix,$comp,silencedetect=n=$sthres:d=$sdur;" # disable if not skimming nick's vods # 999999iq amogus: regex check to determine whose title is who's # now that i think about it, graph time shouldnt be noticeable if printing is # nonblocking, so it'll keep going while the read loop takes its sweet @$$ time if ((nick!=0)); then scr+="[1][0:v]scale2ref[why1][trash1];[trash1][why1]$bthres" why=( -t "$limit" -i "$a" -loop 1 -t "$limit" -i 'C:/dummy_target.jpg') else #scr+="[1]nullsink" why=(-vn -t "$limit" -i "$a") fi echo "offset ${delay}:skim ${limit}s" ffmpeg -hide_banner -hwaccel dxva2 -v info -nostats -ss "$delay" "${why[@]}" -lavfi "$scr" \ -f null nul 2>&1 | while read -r i; do # old: 96:32 if [[ "${i//$cr/}" =~ ${imark}${kv}${god}${god}${god}${god}${god} ]]; then filt="${match[1]}" @@ -62,72 +72,73 @@ for a in "$@"; do "${profile[@]}" jq -nc --arg k "${k:8}" --arg v "$v" --argjson b "$temp" "$ins" | readinto temp # inb4 associative array and fromentries to save time from subprocesses when building up item [ "$k" = 'silence_duration' ] && { cut=($(jq -ncr --argjson r "$srem" --argjson tb "$cut_res" --argjson j "$temp" '$j | [.start, .end, ([$r,(.duration - $r)] | max)] | map(. * $tb | round / $tb) | join(" ")' | tr -d '\r')) "${profile[@]}" printf 'silence \x1b[92m%9.3f\x1b[97m ==> \x1b[92m%9.3f\x1b[0m, \x1b[97mcut \x1b[96m%6.3fs\x1b[0m, total: \x1b[95m%8.3f\x1b[0m\n' "${cut[@]}" "$((tc+=(cut[3])))" sil+=("$temp") } continue } [[ "$filt" = Parsed_blackframe_[0-9]* ]] && { "${profile[@]}" jq -nc --arg k "$k" --arg v "$v" --argjson b "$temp" "$ins" | readinto temp [ "$k" = 'last_keyframe' ] && { "${profile[@]}" jq -ncr --argjson hate 1000 --argjson j "$temp" '$j | "\u001b[97mBAD: \u001b[91m"+ (.t | strftime("%H:%M:%S.")+((.*$hate%$hate+$hate)|tostring|.[1:]))+ "\u001b[0m"' mas+=("$temp") } continue } echo "?????: $k = $v" done ;; *) echo "Uncaught $filt: $MATCH" ;; esac else if ! [[ "${i:l}" =~ ^(metadata|m(aj|in)or_|encoder|output \#|stream \#[0-9]:[0-9](\[[0-9]x[0-9]\([a-z]*\)\])?: [av]|duration: |handler_|vendor|compati) ]]; then printf "\x1b[90m%s\x1b[0m\n" "${i//$cr/}" fi fi done why=(); ((start=-1,end=-1,hate=100000,m_dist*=hate)) jq -nc -r '$ARGS.positional | .[].t' --jsonargs "${mas[@]}" | tr -d $'\r' | while read -r t; do ((start<(t*=hate)-m_dist)) && { ((start!=-1)) && why+=("$start $end"); ((start=t)) }; ((end=t)) done; ((start!=-1)) && why+=("$start $end") jq -nc --argjson hate "$hate" --argjson r "$srem" --argjson j "$base" '$j|.sil = ($ARGS.positional | map([.start, .end, ([$r,.duration] | min/2)] | map(. * $hate | round / $hate)))' --jsonargs "${sil[@]}" | \ jq -c --argjson hate "$hate" --argjson tb "$cut_res" '.mas = ($ARGS.positional | map(. | split(" ") | map(tonumber / $hate * $tb | round / $tb)))' --args "${why[@]}" | readinto base #jq -nc --tab --argjson j "$base" '$j' date +'%F_%H-%M-%S.%3N' | readinto salt echo 'writing detected data'; jq -nc --argjson j "$base" '$j' > "c:/skim_$salt.json" echo 'generating cut points'; trim="select='not($(jq -ncr --argjson hate "$hate" --argjson ml "$m_lead" --argjson mt "$m_trail" --argjson j "$base" \ '$j | .sil | map( "between(t," + ((.[0] + .[2]) * $hate | floor / $hate | tostring) + "," + ((.[1] - .[2]) * $hate | floor / $hate | tostring) + ")" ) | . + ( $j | .mas | map( "between(t," + (.[0] - $ml | tostring) + "," + (.[1] + $mt | tostring) + ")" ) ) + ["0"] | "\n"+join("+")' | tr -d '\r' ))'" piss='setpts=N/FRAME_RATE/TB' # life saver: https://stackoverflow.com/questions/64866231 # everyone/everything else is so unhelpful and useless ((nick!=0)) && block="drawbox=x=iw-w:y=ih-h+2:w=(iw*(1-0.66)):h=(ih*(1-0.58))+2:t=fill:c=red," echo 'rendering (no printing yet = seeking, maybe...)' # crop=480:130:0:0 tee "c:/skim_$salt.filt.txt" <<!! | ffmpeg -hide_banner -hwaccel dxva2 -v verbose -stats -ss "$delay" -i "$a" -t "$(((limit/speed)-tc))" -filter_complex_script pipe: "${fargs[@]}" "c:/skim_$salt.webm" -y [0:v]scale=480:-1,${block} drawtext=text='%{pts\:hms}':fontfile=e\\\:/Gossix.ttf:fontsize=32:fontcolor=white:x=8:y=8:box=1:boxcolor=black@0.6, ${trim},setpts=N/FRAME_RATE/TB,setpts=PTS/$speed; [0:a]$afix,aformat=f=flt,a${trim},asetpts=N/FRAME_RATE/TB,atempo=$speed,$comp; !! # KILLS ITSELF AROUND 8 MINUTES (THE CRINGE IS THAT BAD), NO CRASH DUMP?! done # -vf "scale=480:-1,drawbox=x=iw-w:y=ih-h+2:w=(iw*(1-0.66)):h=(ih*(1-0.58))+2:t=fill:c=red, -
donnaken15 created this gist
Nov 14, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,154 @@ #!/bin/zsh #set -e # exits early without pressing anything, POS speed=1.21 delay=0 # seconds in limit=9999999 # seconds to shorten for skimming, for testing fargs=( -stats -stats_period 0.01 -c:v libvpx-vp9 -pix_fmt yuv444p -crf 43 -qmin 28 -qmax 45 -vb 1100k -minrate 40k -maxrate 2500k -g 900 -bf 64 -refs 8 -threads 16 -tile-columns 6 -tile-rows 2 -row-mt 1 -speed -16 -cpu-used -8 -tune ssim -tune-content screen -corpus-complexity 10000 -enable-tpl 1 -deadline best -auto-alt-ref 1 -quality best -rc_lookahead 25 -sharpness 4 -frame-parallel 0 -aq-mode 0 -arnr-strength 4 -arnr-maxframes 7 -arnr-type 3 -static-thresh 0 -color_primaries bt709 -color_trc bt709 -colorspace bt709 -color_range pc -bufsize 512M -lag-in-frames 25 -fflags +genpts+bitexact -flags +qpel+mv4+aic+global_header -map_metadata -1 -ar 24k -c:a libopus -ab 72k -frame_duration 120 -vbr:a on -flags:a +bitexact -compression_level:a 10 -application voip -flush_packets 1 -max_muxing_queue_size 1 -fflags nobuffer -blocksize 2048 ) cr=$'\r'; lf=$'\n'; ins='$b + { $k: ($v|tonumber? // .) }' imark='\[(silencedetect|Parsed_blackframe_[0-9]+) @ [0-9a-f]{16}\]' kv='( ([A-Za-z0-9_]+): ?([^ ]+))?'$cr?; stupid='( \|)?'; god="$stupid$kv"; temp='{}'; comp='volume=-2dB,dynaudnorm' # broken: acompressor=threshold=-9dB:ratio=5.1:attack=0.2:release=1.0:makeup=1 sthres='-22dB' sdur=0.16 #trap 'exit 1' INT TERM # leaves ffmpeg open # use kill -9 `jobs` if seriously m_notice=10 # heads up warning m_lead=0.2 # seconds before/after detected frames m_trail=2.0 # minimal time skip (from last frame) because fatty has to get in that stupid word m_dist=4 # allowable distance between seconds before creating new cut, this should be a little more than reasonable # ive never had such strong contempt in my life for something as (ironically) insignificant as a freaking adjective # and its all because of you zoomer ******s, im on team flam now, oreo should neck bthres='blend=difference,blackframe=94:38' # trailing 200ms visibility left with this profile=() #profile=(time -f"%E") # not useful rn, keeps showing 0.01s, probably if subprocess management stuff isn't actually acounted for echo "\x1b[91mKILL FFMPEG IF IT GETS STUCK, BECAUSE IT'S BAD SOFTWARE!!!!!!\x1b[0m" alias readinto="tr -d '\r' | read -r -d ''" for a in "$@"; do [ ! -f "$a" ] && { echo "Invalid file: $a" continue } base="`ffprobe -hide_banner -i "$a" -show_streams -print_format json | jq -c --arg delay "$delay" '{ off: (\$delay | tonumber), sil: [], mas: [], str: .streams }'`" sil=(); mas=(); tc=0.0 # total time cut ffmpeg -hide_banner -hwaccel dxva2 -v info -nostats \ -ss "$delay" -t "$limit" -i "$a" -loop 1 -i 'C:\dummy_target.jpg' -lavfi " [0:a]$comp,silencedetect=n=$sthres:d=$sdur,anullsink; [1][0:v]scale2ref[why1][trash1]; [trash1][why1]$bthres " -f null nul 2>&1 | while read -r i; do # old: 96:32 if [[ "${i//$cr/}" =~ ${imark}${kv}${god}${god}${god}${god}${god} ]]; then filt="${match[1]}" #echo "--- $filt ---" case "$filt" in Parsed_blackframe_[0-9]*) ;& silencedetect) for ((y=0;y<6;y++)); do ((x=3+(y*4))) k="${match[$x]}"; v="${match[$((++x))]}" [ -z "$k" ] && break; [ "$k" = 'silence_start' -o "$k" = 'frame' ] && temp='{}' [[ "$k" = silence_* ]] && { # redundant "${profile[@]}" jq -nc --arg k "${k:8}" --arg v "$v" --argjson b "$temp" "$ins" | readinto temp # inb4 associative array and fromentries to save time from subprocesses when building up item [ "$k" = 'silence_duration' ] && { cut=($(jq -ncr --argjson j "$temp" '$j | [.start, .end, ([0.2,(.duration - 0.2)] | max)] | join(" ")' | tr -d '\r')) ((tc+=(cut[3]))) "${profile[@]}" printf 'silence \x1b[92m%9.3f\x1b[97m ==> \x1b[92m%9.3f\x1b[0m, \x1b[97mcut \x1b[96m%4.3fs\x1b[0m, total: %8.3f\n' "${cut[@]}" "$tc" sil+=("$temp") } continue } [[ "$filt" = Parsed_blackframe_[0-9]* ]] && { "${profile[@]}" jq -nc --arg k "$k" --arg v "$v" --argjson b "$temp" "$ins" | readinto temp [ "$k" = 'last_keyframe' ] && { "${profile[@]}" jq -ncr --argjson j "$temp" '$j | "\u001b[97mBAD: \u001b[91m"+ (.t | strftime("%H:%M:%S.")+((.*1000%1000+1000)|tostring|.[1:]))+ "\u001b[0m"' mas+=("$temp") } continue } echo "$k = $v" done ;; *) echo "Uncaught $filt: $MATCH" ;; esac else if ! [[ "$i" =~ ^(Metadata|m(aj|in)or_|encoder|Output \#|Stream \#[0-9]:[0-9](\[[0-9]x[0-9]\([a-z]*\)\])?: [AV]|Duration: |handler_|vendor|compati) ]]; then printf "\x1b[90m%s\x1b[0m\n" "${i//$cr/}" fi fi done why=(); ((start=-1,end=-1,hate=1000,m_dist*=hate)) jq -nc -r '$ARGS.positional | .[].t' --jsonargs "${mas[@]}" | tr -d $'\r' | while read -r t; do ((t*=hate)) ((start<t-m_dist)) && { ((start!=-1)) && why+=("$start $end") ((start=t)) } ((end=t)) done; ((start!=-1)) && why+=("$start $end") jq -nc --argjson j "$base" '$j|.sil = $ARGS.positional' --jsonargs "${sil[@]}" | \ jq -c '.mas = ($ARGS.positional | map(. | split(" ") | map(tonumber / $hate)))' --argjson hate "$hate" --args "${why[@]}" | readinto base #jq -nc --tab --argjson j "$base" '$j' salt="$RANDOM$RANDOM$RANDOM" echo 'writing detected data'; jq -n --tab --argjson j "$base" '$j' > "c:/skim_$salt.json" echo 'generating cut points'; trim="select='not($(jq -ncr --argjson ml "$m_lead" --argjson mt "$m_trail" --argjson j "$base" \ '$j | .sil | map( ([0.2,.duration] | min) as $trunc2 | "between(t," + (((.start + ($trunc2 / 2))*1000) | floor / 1000 | tostring) + "," + (((.end - ($trunc2 / 2))*1000) | floor / 1000 | tostring) + ")" ) | . + ( $j | .mas | map("between(t,"+(.[0] - $ml | tostring)+","+(.[1] + $mt | tostring)+")") ) + ["0"] | join("+")' | tr -d '\r' ))'" # life saver: https://stackoverflow.com/questions/64866231 # everyone/everything else is so unhelpful and useless piss="setpts=N/FRAME_RATE/TB" echo 'rendering (no printing yet = seeking maybe...)' # crop=480:130:0:0 ffmpeg -hide_banner -hwaccel dxva2 -v warning -stats -ss "$delay" -t "$limit" -i "$a" \ -filter_complex_script pipe: "${fargs[@]}" "c:/skim_$salt.webm" -y <<!! [0:v]scale=480:-1,drawbox=x=iw-w:y=ih-h+2:w=(iw*(1-0.66)):h=(ih*(1-0.58))+2:t=fill:c=red, drawtext=text='%{pts\:hms}':fontfile=e\\\:/Gossix.ttf:fontsize=32:fontcolor=white:x=8:y=8:box=1:boxcolor=black@0.6, ${trim},${piss},setpts=PTS/$speed; [0:a]pan=mono|c0=c0+c1,aresample=32k,aformat=f=flt,a${trim},a${piss},atempo=$speed,$comp; !! done # -vf "scale=480:-1,drawbox=x=iw-w:y=ih-h+2:w=(iw*(1-0.66)):h=(ih*(1-0.58))+2:t=fill:c=red, # drawtext=text='%{pts\:hms}':fontfile=e\\\:/Gossix.ttf:fontsize=32:fontcolor=white:x=8:y=8:box=1:boxcolor=black@0.6, # ${trim},${piss},setpts=PTS/$speed" \ # -af "pan=mono|c0=c0+c1,aresample=32k,aformat=f=flt,a${trim},a${piss},atempo=$speed,$comp" # ffmpeg -hide_banner -hwaccel dxva2 -stats -ss 5:00 -i "F:\New folder\The Worst iDubbbz Interview Ever , Caleb Hammer VS Jake Weddle 2 & Pokimane [AULY1qhyRRQ].mp4" -loop 1 -i C:\dummy_target.jpg -an -lavfi "[0][1]scale2ref,blend=difference,blackframe=96:32" -f null nul # ffmpeg -hide_banner -hwaccel dxva2 -stats -ss 10:00 -i "Ethan Klein's Full Response To Ian Jomha (iDubbbz) [Anisa Jomha's Husband] [fnHgShT1qlE].mp4" -loop 1 -i C:\dummy_target.jpg -an -lavfi "[0][1]scale2ref,blend=difference,blackframe=96:32" -f null nul # ffprobe -v info -f lavfi -i "movie=die_foss:sp=600:dec_threads=15,select=gte(n\,0)[trash_stream];movie='c\:\\dummy_target.jpg',loop=loop=-1:size=1:start=0[nhyper];[trash_stream][nhyper]scale2ref,blend=difference,blackframe=96:32" -show_frames -print_format json | grep blackframe # minimal case: 00:41:23.377 -- 00:41:25.458 #-ss "$delay" -t "$limit" -i "$a" -loop 1 \ # -i 'C:\dummy_target.jpg' -i 'C:\dummy_target2.jpg' -lavfi " # [0:a]$comp,silencedetect=n=-25dB:d=0.16,anullsink; # [1][0:v]scale2ref[why1][trash1]; # [2][trash1]scale2ref[why2][trash2]; # [trash1][why1]$bthresh,nullsink; # [trash2][why2]$bthresh #" -f null nul 2>&1 | while read -r i; do # USES 7 GB COMMIT JUST FOR A SECOND COMPARISON FRAME WTFFFFFFF # probably useless: sha256sum skim.json | cut -d' ' -f1 | xxd -r -p | base64 -w 110