Skip to content

Instantly share code, notes, and snippets.

@donnaken15
Last active December 12, 2025 21:42
Show Gist options
  • Select an option

  • Save donnaken15/98e665de860e95521f81c1fdb3907a8c to your computer and use it in GitHub Desktop.

Select an option

Save donnaken15/98e665de860e95521f81c1fdb3907a8c to your computer and use it in GitHub Desktop.

Revisions

  1. donnaken15 revised this gist Dec 12, 2025. 1 changed file with 83 additions and 51 deletions.
    134 changes: 83 additions & 51 deletions slopper_skimmer.zsh
    Original 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
    (($# == 0)) && { # LOL # $((?)) also works, amazing # NOT IN NORMAL SHELL
    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
    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";
    ); 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
    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
    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 ''"
    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
    }
    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/}"
    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 }'`"
    #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 ${delay}`:skim `timefmt ${limit}`:res 1/${cut_res}"
    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
    ffmpeg -hide_banner -hwaccel dxva2 -v info -nostats -ss "$delay" "${why[@]}" -lavfi "$scr" \
    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 '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"
    printf "$cut_fmt" "${cut[@]}" "$tc" "$cuts"
    ) &
    sil+=("${test//$cr/}")
    }
    @@ -123,54 +161,48 @@ for a in "$@"; do
    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))
    }; ((end=t))
    done; ((start!=-1)) && why+=("$start $end")
    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[@]}" | \
    '$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(
    --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];
    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 "$delay" -t "$limit" -i "$a" -loop 1 \
    #-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];
  2. donnaken15 revised this gist Dec 8, 2025. 1 changed file with 57 additions and 105 deletions.
    162 changes: 57 additions & 105 deletions slopper_skimmer.zsh
    Original file line number Diff line number Diff line change
    @@ -3,51 +3,48 @@
    ((# == 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)
    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 0 -arnr-strength 4 -arnr-maxframes 7 -arnr-type 3 -sharpness 4
    -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 66k
    -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'; 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
    ); 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"
    ((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
    #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 ))
    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%02d:%02d:%02d.%03d' "$2" $h $m $s $ms
    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 --date="TZ=\"%TZ%\" now" +'%F_%H-%M-%S.%3N' | readinto salt; salt="${salt//$cr/}"
    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
    # 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]")
    #"${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"
    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 |
    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"'
    "\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/}"
    #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" \
    ((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(
    "between(t," +
    (((.[0] + .[2]) * $tb | round / $tb) * $hate | floor / $hate | tostring) + "," +
    (((.[1] - .[2]) * $tb | round / $tb) * $hate | floor / $hate | tostring) +
    ")"
    ) | . + (
    $j | .mas | map(
    "between(t," +
    (.[0] - $ml | tostring) + "," +
    (.[1] + $mt | tostring) +
    ")"
    )
    ) + ["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
    '($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))'"
    # 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;
    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];
    !!
    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

    # %{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" \
    # -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
    #-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

  3. donnaken15 revised this gist Dec 8, 2025. 1 changed file with 84 additions and 43 deletions.
    127 changes: 84 additions & 43 deletions slopper_skimmer.zsh
    Original 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
    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
    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
    -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 -fflags nobuffer -blocksize 2048
    -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='{}'
    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
    sthres='-20.0dB'; ((sdur=0.16,srem=0.2,nick=0)); # figure this out like audacity duration and truncate to
    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
    bthres='blend=difference,blackframe=94:38' # trailing 200ms visibility left with this
    afix='pan=mono|c0=c0+c1,aresample=32k'
    profile=()
    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="tr -d '\r' | read -r -d ''"
    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
    }
    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
    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"
    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"
    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;"
    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
    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
    -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='{}'
    ((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
    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' ] && {
    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")
    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]* ]] && {
    "${profile[@]}" jq -nc --arg k "$k" --arg v "$v" --argjson b "$temp" "$ins" | readinto temp
    temp+=("[\"$k\",$v]")
    #"${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 |
    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+=("$temp")
    mas+=("${test//$cr/}")
    }
    continue
    }
    @@ -118,7 +126,8 @@ for a in "$@"; do
    fi
    fi
    done
    why=(); ((start=-1,end=-1,hate=100000,m_dist*=hate))
    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
    jq -c --argjson hate "$hate" '.mas = ($ARGS.positional | map(. | split(" ")))' --args "${why[@]}" | readinto base; base="${base//$cr/}"
    #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" \
    --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...)
    piss='setpts=N/FRAME_RATE/TB'
    ))'" # 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,"
    ((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
    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;
    # 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
  4. donnaken15 revised this gist Nov 21, 2025. 1 changed file with 54 additions and 30 deletions.
    84 changes: 54 additions & 30 deletions slopper_skimmer.zsh
    Original file line number Diff line number Diff line change
    @@ -1,31 +1,35 @@
    #!/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
    ((# == 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 -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
    -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 72k
    -frame_duration 120 -vbr:a on -flags:a +bitexact -compression_level:a 10
    -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='{}';
    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
    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 file: $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
    }
    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
    @@ -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 tb "$cut_res" --argjson j "$temp" '$j | [.start, .end, ([$r,(.duration - $r)] | max)] | map(. * $tb | round / $tb) | join(" ")' | tr -d '\r'))
    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)] | 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 --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 +'%F_%H-%M-%S.%3N' | readinto salt
    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 mt "$m_trail" --argjson j "$base" \
    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]) * $hate | floor / $hate | tostring) + "," +
    ((.[1] - .[2]) * $hate | floor / $hate | tostring) +
    (((.[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=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,
    [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" \
  5. donnaken15 revised this gist Nov 15, 2025. 1 changed file with 59 additions and 48 deletions.
    107 changes: 59 additions & 48 deletions slopper_skimmer.zsh
    Original 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.21
    delay=0 # seconds in
    limit=9999999 # seconds to shorten for skimming, for testing
    ((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
    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
    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 acounted for
    #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
    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
    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 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"
    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 j "$temp" '$j |
    "${profile[@]}" jq -ncr --argjson hate 1000 --argjson j "$temp" '$j |
    "\u001b[97mBAD: \u001b[91m"+
    (.t | strftime("%H:%M:%S.")+((.*1000%1000+1000)|tostring|.[1:]))+
    (.t | strftime("%H:%M:%S.")+((.*$hate%$hate+$hate)|tostring|.[1:]))+
    "\u001b[0m"'
    mas+=("$temp")
    }
    continue
    }
    echo "$k = $v"
    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
    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=1000,m_dist*=hate))
    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
    ((t*=hate))
    ((start<t-m_dist)) && {
    ((start!=-1)) && why+=("$start $end")
    ((start=t))
    }
    ((end=t))
    ((start<(t*=hate)-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 --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'
    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" \
    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(
    ([0.2,.duration] | min) as $trunc2 |
    "between(t," +
    (((.start + ($trunc2 / 2))*1000) | floor / 1000 | tostring) + "," +
    (((.end - ($trunc2 / 2))*1000) | floor / 1000 | tostring) +
    ((.[0] + .[2]) * $hate | floor / $hate | tostring) + "," +
    ((.[1] - .[2]) * $hate | floor / $hate | tostring) +
    ")"
    ) | . + (
    $j | .mas | map("between(t,"+(.[0] - $ml | tostring)+","+(.[1] + $mt | tostring)+")")
    ) + ["0"] | join("+")' | tr -d '\r'
    $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
    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;
    ((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,
  6. donnaken15 created this gist Nov 14, 2025.
    154 changes: 154 additions & 0 deletions slopper_skimmer.zsh
    Original 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