generated from me/template-mit
Compare commits
51
Commits
main
..
ffbf55c1ed
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ffbf55c1ed | ||
|
|
ccdc7ea5ed | ||
|
|
f3da185fb6 | ||
|
|
933e00556c | ||
|
|
a47d1ab9f8 | ||
|
|
9a85425c3f | ||
|
|
95ea82e842 | ||
|
|
99b5d6fd6d | ||
|
|
62f0f072f4 | ||
|
|
6e9288e5c2 | ||
|
|
5f0144ed1d | ||
|
|
1f5d51e45a | ||
|
|
a5e1dd6a36 | ||
|
|
274d4fadef | ||
|
|
5d6338533d | ||
|
|
da0d15348c | ||
|
|
9ce76da18d | ||
|
|
c3d845e98e | ||
|
|
5f13c6624b | ||
|
|
13c542b888 | ||
|
|
694767abd5 | ||
|
|
0a88e173fb | ||
|
|
2ee0fd2c31 | ||
|
|
fd2720eb6c | ||
|
|
6f2e18e2f1 | ||
|
|
8e4919b689 | ||
|
|
0f42f92eaf | ||
|
|
2b7253ade2 | ||
|
|
224e112340 | ||
|
|
be5251ae3a | ||
|
|
fa11113b2c | ||
|
|
3ac932e42b | ||
|
|
701dfbcc96 | ||
|
|
da0be0ab41 | ||
|
|
7463e4a9b8 | ||
|
|
8279cb8618 | ||
|
|
ea0c329d3b | ||
|
|
4b34fd3fd3 | ||
|
|
c2c04ead5d | ||
|
|
c8b0684433 | ||
|
|
f0e8125109 | ||
|
|
3c01ed7331 | ||
|
|
94415ac734 | ||
|
|
5755261150 | ||
|
|
0eb5c6ea70 | ||
|
|
4b647d5e09 | ||
|
|
5e1505ce0a | ||
|
|
c3afb3fcf8 | ||
|
|
bb08f1ef94 | ||
|
|
a105916ab5 | ||
|
|
753611fb67 |
+935
-15
@@ -326,6 +326,8 @@ function send-masters {
|
||||
}
|
||||
alias push-masters="send-masters"
|
||||
alias sync-masters="send-masters"
|
||||
alias push-all="send-masters"
|
||||
alias send-all="send-masters"
|
||||
|
||||
function pull-clones {
|
||||
echo -e "`date` - Looping through clone directories."
|
||||
@@ -339,6 +341,8 @@ function pull-clones {
|
||||
}
|
||||
alias get-clones="pull-clones"
|
||||
alias sync-clones="pull-clones"
|
||||
alias pull-all="pull-clones"
|
||||
alias get-all="pull-clones"
|
||||
|
||||
function sync-all {
|
||||
push-masters
|
||||
@@ -771,6 +775,499 @@ alias vta="v2a"
|
||||
alias pull-audio="v2a"
|
||||
alias pa="v2a"
|
||||
|
||||
# Run all the different codecs, wrappers, bitrates, etc on a file.
|
||||
function pv-test {
|
||||
echo -e "Welcome! Let's get your tests set up...\n"
|
||||
|
||||
## Input ##
|
||||
|
||||
filename_in="$1"
|
||||
while [[ -z "$filename_in" ]]; do
|
||||
read -p "Please provide the filename: " filename_in
|
||||
done
|
||||
|
||||
# Existing Functions #
|
||||
|
||||
declare -l pv{,2}="n"
|
||||
typeset -l test_pv{,2}
|
||||
|
||||
read -p "Create a test with current 'pv' function? (y/N) " test_pv
|
||||
if [[ "$test_pv" == "y"* ]]; then
|
||||
pv="y"
|
||||
echo " great, will run pv"
|
||||
else
|
||||
echo " skipping"
|
||||
fi
|
||||
echo " "
|
||||
read -p "Create a test with current 'pv2' function? (y/N) " test_pv2
|
||||
if [[ "$test_pv2" == "y"* ]]; then
|
||||
pv2="y"
|
||||
echo " great, will run pv2"
|
||||
else
|
||||
echo " skipping"
|
||||
fi
|
||||
echo " "
|
||||
|
||||
# Loop Data #
|
||||
|
||||
declare -l {vpreset,crf,vbr,abr,achannel,afreq,over,under}s="default"
|
||||
|
||||
echo -e " * * Loop Settings * * \n"
|
||||
|
||||
basename="`basename "$filename_in"`"
|
||||
basename_in=""
|
||||
read -p "Would you like to specify a basename? [$basename] " basename_in
|
||||
if [[ -n "$basename_in" ]]; then
|
||||
basename="$basename_in"
|
||||
fi
|
||||
echo -e " basename: '$basename'\n"
|
||||
|
||||
typeset -i size_in
|
||||
read -p "What display ratio would you like to use? [720] " size_in
|
||||
if (( $size_in == 0 )); then
|
||||
size_in=720
|
||||
fi
|
||||
echo -e " size: '$size_in'\n"
|
||||
|
||||
vcodecs="libsvtav1"
|
||||
read -p "Please provide the video codecs to test: [$vcodecs] " test_vcodecs
|
||||
if [[ -n "$test_vcodecs" ]]; then
|
||||
vcodecs="$test_vcodecs"
|
||||
fi
|
||||
echo -e " video codecs: '$vcodecs'\n"
|
||||
|
||||
echo "Please provide any presets to use."
|
||||
echo "(if testing both H264 and AV1, please select from: vsl slr slw med fst fsr vft)"
|
||||
read -p "Add any presets? [$vpresets] " test_vpresets
|
||||
if [[ -n "$test_vpresets" ]]; then
|
||||
vpresets="$test_vpresets"
|
||||
fi
|
||||
echo -e " presets: '$vpresets'\n"
|
||||
|
||||
read -p "Please provide any CRFs to test: [default] " test_crfs
|
||||
if [[ -n "$test_crfs" ]]; then
|
||||
crfs="$test_crfs"
|
||||
fi
|
||||
echo -e " CRFs: '$crfs'\n"
|
||||
|
||||
read -p "Please provide any video bitrates to test: [default] " test_vbrs
|
||||
if [[ -n "$test_vbrs" ]]; then
|
||||
vbrs="$test_vbrs"
|
||||
fi
|
||||
echo -e " video bitrates: '$vbrs'\n"
|
||||
|
||||
if [[ "$vcodecs" == *"libsvtav1"* ]]; then
|
||||
read -p "Please provide any over percentages for libsvtav1: [default] " test_overs
|
||||
if [[ -n "$test_overs" ]]; then
|
||||
overs="$test_overs"
|
||||
fi
|
||||
echo -e " over percentages: '$overs'\n"
|
||||
|
||||
read -p "Please provide any under percentages for libsvtav1: [default] " test_unders
|
||||
if [[ -n "$test_unders" ]]; then
|
||||
unders="$test_unders"
|
||||
fi
|
||||
echo -e " under percentages: '$unders'\n"
|
||||
fi
|
||||
|
||||
acodecs="libopus"
|
||||
read -p "Please provide the audio codecs to test: [$acodecs] " test_acodecs
|
||||
if [[ -n "$test_acodecs" ]]; then
|
||||
acodecs="$test_acodecs"
|
||||
fi
|
||||
echo -e " audio codecs: '$acodecs'\n"
|
||||
|
||||
read -p "Please provide any audio bitrates to test: [default] " test_abrs
|
||||
if [[ -n "$test_abrs" ]]; then
|
||||
abrs="$test_abrs"
|
||||
fi
|
||||
echo -e " audio bitrates: '$abrs'\n"
|
||||
|
||||
read -p "Test both mono and stereo audio channels? (y/N) " test_achannels
|
||||
if [[ "$test_achannels" == "y"* ]]; then
|
||||
achannels="1 2" # 1 is mono, 2 is stereo
|
||||
fi
|
||||
echo -e " audio channels: '$achannels'\n"
|
||||
|
||||
read -p "Test both 48 and 44.1 kHz audio frequencies? (y/N) " test_afreqs
|
||||
if [[ "$test_afreqs" == "y"* ]]; then
|
||||
afreqs="48000 44100" # 48 typically found in videos, 44.1 in audio.
|
||||
fi
|
||||
echo -e " audio frequencies: '$afreqs'\n"
|
||||
|
||||
normalize=""
|
||||
typeset -u normalize_in
|
||||
read -p "Would you like to normalize the audio? (Y/n) " normalize_in
|
||||
if [[ "$normalize_in" != "N"* && $normalize_in != "F"* ]]; then
|
||||
normalize="-filter:a dynaudnorm=f=33:g=65:p=0.66:m=33.3"
|
||||
fi
|
||||
echo -e " normalize: '$normalize'\n"
|
||||
|
||||
exts="mkv"
|
||||
read -p "Please provide the containers to test with: [$exts] " test_exts
|
||||
if [[ -n "$test_exts" ]]; then
|
||||
exts="$test_exts"
|
||||
fi
|
||||
echo -e " extensions: '$exts'\n"
|
||||
|
||||
bitrate_check=""
|
||||
typeset -u bitrate_in
|
||||
read -p "Would you like to append the bitrate to the filename? (Y/n) " bitrate_in
|
||||
if [[ "$bitrate_in" != "N"* && $bitrate_in != "F"* ]]; then
|
||||
bitrate_check="Y"
|
||||
fi
|
||||
echo -e " bitrate_check: '$bitrate_check'\n"
|
||||
|
||||
# Final Check #
|
||||
|
||||
echo -e " * * Confirmation * * \n"
|
||||
|
||||
ffprobe -i "$filename_in"
|
||||
echo -e "\n * Testing against '$filename_in' above. * \n"
|
||||
|
||||
typeset -i guess
|
||||
guess=$(( \
|
||||
`wc -w <<< $vcodecs` * `wc -w <<< $vpresets` * `wc -w <<< $crfs` \
|
||||
* `wc -w <<< $vbrs` * `wc -w <<< $overs` * `wc -w <<< $unders` \
|
||||
* `wc -w <<< $acodecs` * `wc -w <<< $abrs` \
|
||||
* `wc -w <<< $achannels` * `wc -w <<< $afreqs` \
|
||||
))
|
||||
if (( $guess > 0 )); then
|
||||
plural=""
|
||||
if (( $guess != 1 )); then
|
||||
plural="s"
|
||||
fi
|
||||
echo -e "Expecting ${guess} loop${plural}.\n"
|
||||
else
|
||||
echo "ERROR: Something went wrong, got 0 loops, exiting."
|
||||
return 1
|
||||
fi
|
||||
|
||||
typeset -u okay
|
||||
read -p "Does everything look okay? (Y/n) " okay
|
||||
if [[ "$okay" == "N" || "$okay" == "F"* ]]; then
|
||||
echo " Not okay, aborting."
|
||||
return 1
|
||||
fi
|
||||
echo -e "Sounds good, here we go!\n"
|
||||
|
||||
## Main ##
|
||||
|
||||
if [[ "$pv" == "y" ]]; then
|
||||
echo " * Starting pv... * "
|
||||
filename_pv="$(basename "${filename_in}-pv.mkv")"
|
||||
if [[ -e "$filename_pv" ]]; then
|
||||
mv -v "$filename_pv" ~/TRASH
|
||||
fi
|
||||
pv "$filename_in" "$filename_pv"
|
||||
echo -e " * Testing with 'pv' complete! * \n"
|
||||
fi
|
||||
if [[ "$pv2" == "y" ]]; then
|
||||
echo " * Starting pv2... * "
|
||||
filename_pv2="$(basename "${filename_in}-pv2.mkv")"
|
||||
if [[ -e "$filename_pv2" ]]; then
|
||||
mv -v "$filename_pv2" ~/TRASH
|
||||
fi
|
||||
pv "$filename_in" "$filename_pv2"
|
||||
echo -e " * Testing with 'pv2' complete! * \n"
|
||||
fi
|
||||
|
||||
typeset -i count
|
||||
unset vcodec vpreset crf vbr acodec abr ext
|
||||
for vcodec in $vcodecs; do for vpreset in $vpresets; do for crf in $crfs; do
|
||||
for vbr in $vbrs; do for over in $overs; do for under in $unders; do
|
||||
for acodec in $acodecs; do for abr in $abrs;
|
||||
do for achannel in $achannels; do for afreq in $afreqs; do
|
||||
for ext in $exts; do
|
||||
(( count++ ))
|
||||
|
||||
preset=""
|
||||
if [[ "$vpreset" != "default" ]]; then
|
||||
if [[ "$vcodec" == "libsvtav1" ]]; then
|
||||
# Scale goes from 0 to 13, 0 being like x264's "placebo", above 8 being destructive.
|
||||
# Each step down is about 2x as slow, so 6 to 4 is ~4x slower, 6 to 2 is ~16x slower.
|
||||
case $vpreset in
|
||||
vsl) preset="2" ;; # best quality; quite slow, but still feasible
|
||||
slr) preset="3" ;; # nearly the same as 4 but twice as slow
|
||||
slw) preset="4" ;; # great quality; decent speed
|
||||
med) preset="6" ;; # good quality; great speed
|
||||
fst) preset="8" ;; # default; quite fast
|
||||
fsr) preset="9" ;; # rough drafts only
|
||||
vft) preset="10" ;; # real time encoding for livestreams
|
||||
*) preset="$vpreset" ;;
|
||||
esac
|
||||
else
|
||||
case $vpreset in
|
||||
vsl) preset="veryslow" ;;
|
||||
slr) preset="slower" ;;
|
||||
slw) preset="slow" ;;
|
||||
med) preset="medium" ;; # default
|
||||
fst) preset="fast" ;;
|
||||
fsr) preset="faster" ;;
|
||||
vft) preset="veryfast" ;;
|
||||
*) preset="$vpreset" ;;
|
||||
esac
|
||||
fi
|
||||
if [[ -n "$preset" ]]; then
|
||||
preset="-preset $preset"
|
||||
fi
|
||||
fi
|
||||
|
||||
bitrate=""
|
||||
if [[ "$crf" != "default" ]]; then
|
||||
bitrate="-crf $crf"
|
||||
fi
|
||||
declare {o,u}fn=""
|
||||
if [[ "$vbr" != "default" ]]; then
|
||||
if [[ "$vcodec" == "libsvtav1" ]]; then
|
||||
#bitrate="$bitrate -svtav1-params rc=1:tbr=$vbr:overshoot-pct=0:undershoot-pct=100"
|
||||
|
||||
declare {o,u}=""
|
||||
if [[ "$over" != "default" ]]; then
|
||||
o=":overshoot-pct=${over}"
|
||||
ofn="-o${over}"
|
||||
fi
|
||||
if [[ "$under" != "default" ]]; then
|
||||
u=":undershoot-pct=${under}"
|
||||
ufn="-u${under}"
|
||||
fi
|
||||
|
||||
if [[ "$crf" == "default" ]]; then
|
||||
# Variable Bitrate, rate passed should be the TARGET, not the max.
|
||||
# Can control the params which allow the target to go up and down, but defaults are okay.
|
||||
# Seems better to not try and force this to imitate "-b:v -minrate -maxrate -bufsize"
|
||||
# Will definitely want to use a slower preset to ensure the quality stays consistent.
|
||||
|
||||
# Can be done like this if not changing over or under.
|
||||
#bitrate="-b:v $vbr"
|
||||
|
||||
# Prefer this method so we know we're doing VBR (rc=1) not CBR (rc=2).
|
||||
# rc=1, over defaults to 25, under defaults to 50
|
||||
# rc=2, over defaults to 25, under defaults to 25
|
||||
bitrate="-svtav1-params rc=1:tbr=${vbr}${o}${u}"
|
||||
else
|
||||
# Capped CRF, when both a CRF and bitrate are passed.
|
||||
# Better to use high CRF with low BR than high BR with low CRF (produces artifacts/tearing).
|
||||
bitrate="-svtav1-params rc=0:crf=${crf}:mbr=${vbr}${o}${u}"
|
||||
fi
|
||||
else
|
||||
bitrate="$bitrate -b:v $vbr -minrate 0 -maxrate $vbr -bufsize $vbr"
|
||||
fi
|
||||
fi
|
||||
|
||||
fidelity=""
|
||||
if [[ "$abr" != "default" ]]; then
|
||||
fidelity="-b:a $abr"
|
||||
fi
|
||||
|
||||
channel=""
|
||||
if [[ "$achannel" != "default" ]]; then
|
||||
channel="-ac $achannel"
|
||||
fi
|
||||
|
||||
frequency=""
|
||||
if [[ "$afreq" != "default" ]]; then
|
||||
if [[ "$acodec" == "libopus" ]]; then
|
||||
case $afreq in
|
||||
48000) ;; 24000) ;; 16000) ;; 12000) ;; 8000) ;;
|
||||
*) echo -e "ERROR: libopus cannot do this, skipping frequency ${afreq}."
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
frequency="-ar $afreq"
|
||||
fi
|
||||
|
||||
ext=".$ext"
|
||||
newfile="_${size_in}p_${vcodec}-${vpreset}-${crf}-${vbr}${ofn}${ufn}_${acodec}-${abr}-${achannel}-${afreq}${ext}"
|
||||
echo -e " * [Loop $count/$guess] Parameters for this test: $newfile * \n"
|
||||
|
||||
if [[ -e "$newfile" ]]; then
|
||||
mv -v "$newfile" ~/TRASH/
|
||||
echo -e "Removed unfinished version of this file.\n"
|
||||
fi
|
||||
if [[ `ls *"${newfile//$ext/}"*"$ext"* 2>/dev/null` ]]; then
|
||||
echo -e "Completed version of this file already exists, skipping.\n"
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "$(date) - Starting run..."
|
||||
|
||||
start=$SECONDS
|
||||
set -x
|
||||
ffmpeg -nostdin -hide_banner -loglevel level+warning \
|
||||
-i "$filename_in" \
|
||||
-filter:v scale=-1:$size_in \
|
||||
-c:v $vcodec \
|
||||
$preset \
|
||||
$bitrate \
|
||||
-c:a $acodec \
|
||||
$fidelity \
|
||||
$channel \
|
||||
$frequency \
|
||||
$normalize \
|
||||
-movflags +faststart \
|
||||
"$newfile"
|
||||
status="$?"
|
||||
set +x
|
||||
finish=$SECONDS
|
||||
|
||||
minutes=$(( (finish - start) / 60 ))
|
||||
seconds=$(( (finish - start) % 60 ))
|
||||
printf -v padded_mins "%03d" "$minutes"
|
||||
printf -v padded_secs "%02d" "$seconds"
|
||||
|
||||
bitrate=""; bitrate_padded="";
|
||||
if [[ "$bitrate_check" == "Y" ]]; then
|
||||
j=""
|
||||
for i in `ffprobe "$newfile" 2>&1 | grep bitrate`; do
|
||||
# Previous loop was the 'bitrate' label, so get bitrate now.
|
||||
if [[ "$j" == 'bitrate:' ]]; then
|
||||
bitrate="$i"
|
||||
#printf -v bitrate_padded "%05d" "$bitrate"
|
||||
fi
|
||||
# Previous loop was the bitrate, so get the units now.
|
||||
if [[ "$j" == "$bitrate" ]]; then
|
||||
#bitrate="_""$bitrate_padded${i//\//p}"
|
||||
bitrate="_""$bitrate${i//\//p}"
|
||||
fi
|
||||
j="$i"
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ "$status" == 0 && -s "$newfile" ]]; then
|
||||
mv -v "$newfile" "${basename}_${padded_mins}m${padded_secs}s${newfile//$ext/$bitrate$ext}"
|
||||
else
|
||||
echo "ERROR: ffmpeg exited with status $status, not renaming file."
|
||||
fi
|
||||
|
||||
echo -e "\n * Finished in ${minutes}m${seconds}s! * \n"
|
||||
done
|
||||
done done
|
||||
done done
|
||||
done done done
|
||||
done done done
|
||||
|
||||
## Finish ##
|
||||
|
||||
plural=""
|
||||
if (( $count != 1 )); then
|
||||
plural="s"
|
||||
fi
|
||||
echo "Completed tests after ${count} loop${plural}! :)"
|
||||
}
|
||||
|
||||
# 20260914 - After playing with pv-test for a while.
|
||||
function pv3 {
|
||||
org="$1"
|
||||
out="$2"
|
||||
echo "Processing '$org' to '$out' using AV1 and OPUS."
|
||||
|
||||
## Versions ##
|
||||
|
||||
# v0
|
||||
scale=-1:720
|
||||
preset=0 # took 20 minutes where preset 2 was under 2 minutes
|
||||
crf=18
|
||||
vbr=2000k # this is creating 2Mbps files, not maxxing at 2.
|
||||
overshoot=0
|
||||
undershoot=100
|
||||
|
||||
# v1
|
||||
preset=2 # WAY faster and still great.
|
||||
crf=28 # much smaller filesize
|
||||
|
||||
# v2
|
||||
# Try to mimic h264 better.
|
||||
vbr=1000k
|
||||
overshoot=100
|
||||
|
||||
# v3
|
||||
# Fix weird aspect ratios.
|
||||
scale="1280:720,setsar=1"
|
||||
|
||||
# v4
|
||||
# Assuming it was just a weird Pixel phone video issue.
|
||||
scale=-1:720
|
||||
# Remove CRF since we are using VBR.
|
||||
crf=""
|
||||
# Still not 100% on these but seems like a good ballpark.
|
||||
preset=6
|
||||
vbr=800k
|
||||
overshoot=50
|
||||
undershoot=100
|
||||
# Add audio bitrate.
|
||||
abr=128k
|
||||
|
||||
# v5
|
||||
# 800k had some visible degradation compared to pv. Up it a bit more.
|
||||
vbr=1200k
|
||||
preset=2
|
||||
|
||||
# v6
|
||||
# 4 does way better than 2 or 6, at least on laptop, but phone and laptop
|
||||
# scores have stayed very very similar. Also, overshoot of 100 is giving
|
||||
# smaller files than less, and also allows more if needed, so keeping that.
|
||||
preset=4
|
||||
vbr=1200k
|
||||
overshoot=100
|
||||
undershoot=100
|
||||
abr=128k
|
||||
|
||||
## Main ##
|
||||
|
||||
echo -e "\n * Original File * \n"
|
||||
ffprobe -i "$org"
|
||||
|
||||
echo -e "\n * Starting Processing *\n"
|
||||
date
|
||||
set -x
|
||||
ffmpeg -nostdin -hide_banner -loglevel level+warning \
|
||||
-i "$org" \
|
||||
-c:v libsvtav1 \
|
||||
-preset $preset \
|
||||
-filter:v scale=$scale \
|
||||
-svtav1-params rc=1:tbr=${vbr}:overshoot-pct=${overshoot}:undershoot-pct=${undershoot} \
|
||||
-c:a libopus \
|
||||
-filter:a dynaudnorm=f=33:g=65:p=0.66:m=33.3 \
|
||||
-b:a $abr \
|
||||
-movflags +faststart \
|
||||
"$out"
|
||||
status="$?"
|
||||
set +x
|
||||
# -crf $crf \
|
||||
|
||||
if [[ "$status" != 0 || ! -s "$out" ]]; then
|
||||
echo "Failed, deleting output."
|
||||
mv -v "$out" ~/TRASH/
|
||||
return $status
|
||||
fi
|
||||
|
||||
echo -e "\n * Success! *"
|
||||
}
|
||||
|
||||
# 20260915 - Stack 2 videos for comparing quality. TBD: Move to Ansible?
|
||||
function vcompare {
|
||||
vid1="$1"
|
||||
vid2="$2"
|
||||
if [[ -z $vid1 || -z $vid2 ]]; then
|
||||
echo "ERROR: Missing vid1 ('$vid1') or vid2 ('$vid2'). "
|
||||
return 1
|
||||
fi
|
||||
|
||||
orientation="$3"
|
||||
if [[ -z $orientation || ($orientation != "h" && $orientation != "v") ]]; then
|
||||
echo -n "NOTICE: Received '$orientation' for orientation, using vertical instead. "
|
||||
orientation="v"
|
||||
echo "'$orientation'"
|
||||
fi
|
||||
|
||||
mpv --lavfi-complex="[vid1][vid2]${orientation}stack[vo];[aid1][aid2]amix[ao]" \
|
||||
"$vid1" \
|
||||
--external-file="$vid2"
|
||||
}
|
||||
alias vcomp="vcompare "
|
||||
|
||||
|
||||
### Web ###
|
||||
|
||||
@@ -860,25 +1357,25 @@ function git-check {
|
||||
echo "Checking '$dir' for git changes."
|
||||
ls -d "$dir"/* | while read project; do
|
||||
if [[ ! -d $project ]]; then
|
||||
continue
|
||||
continue
|
||||
fi
|
||||
echo -e "\n*** `basename $project` ***"
|
||||
cd $project
|
||||
if [[ -d .git ]]; then
|
||||
git ls-remote --exit-code --heads origin dev
|
||||
dev_exists="$?"
|
||||
if [[ "$dev_exists" == 0 ]]; then
|
||||
git switch dev
|
||||
elif [[ "$dev_exists" == 2 ]]; then
|
||||
git switch main
|
||||
git ls-remote --exit-code --heads origin dev
|
||||
dev_exists="$?"
|
||||
if [[ "$dev_exists" == 0 && "$dir" != *".wiki" ]]; then
|
||||
git switch dev
|
||||
elif [[ "$dev_exists" == 2 || "$dir" == *".wiki" ]]; then
|
||||
git switch main
|
||||
else
|
||||
echo "ERROR: Unknown status for dev_exists, '$dev_exists'."
|
||||
continue
|
||||
fi
|
||||
git pull
|
||||
git push
|
||||
else
|
||||
echo "ERROR: Unknown status for dev_exists, '$dev_exists'."
|
||||
continue
|
||||
fi
|
||||
git pull
|
||||
git push
|
||||
else
|
||||
echo "Not a Git project, skipping!"
|
||||
echo "Not a Git project, skipping!"
|
||||
fi
|
||||
done
|
||||
echo -e "\nDone!"
|
||||
@@ -908,8 +1405,431 @@ alias colors="check-colors"
|
||||
alias term-colors="check-colors"
|
||||
alias display-colors="check-colors"
|
||||
|
||||
### LLMs ###
|
||||
|
||||
## Finalize ##
|
||||
function ollama_stop() {
|
||||
for model in `ollama ps | tail -n +2 | awk '{print $1}'`; do
|
||||
echo "Stopping ${model}..."
|
||||
ollama stop $model
|
||||
done
|
||||
}
|
||||
alias ollama-stop="ollama_stop"
|
||||
alias ollama-kill="ollama_stop"
|
||||
alias ollama-killall="ollama_stop"
|
||||
alias ollama-kill-all="ollama_stop"
|
||||
alias ollama-stop-all="ollama_stop"
|
||||
|
||||
function ollama_models() {
|
||||
for model in `ollama ls | grep -v NAME | awk '{print $1;}'`; do
|
||||
echo $model
|
||||
ollama show $model | grep -E "architecture|context length|quantization"
|
||||
done
|
||||
}
|
||||
alias ollama-models="ollama_models "
|
||||
alias ollama-show-models="ollama_models "
|
||||
alias ollama-show="ollama_models "
|
||||
alias ollama-dense="ollama_models "
|
||||
alias ollama-moe="ollama_models "
|
||||
alias show-models="ollama_models "
|
||||
alias list-models="ollama_models "
|
||||
|
||||
function ollama_sizes() {
|
||||
# VAR1 - Format. Choices are Markdown or Spaces.
|
||||
typeset -l fmt="$1"
|
||||
if [[ -z "$fmt" ]]; then
|
||||
fmt=s
|
||||
fi
|
||||
if [[ "$fmt" != "s"* && "$fmt" != "m"* ]]; then
|
||||
echo "ERROR: Format incorrect, choose Markdown or Spaces."
|
||||
return 1
|
||||
fi
|
||||
sep=""
|
||||
if [[ $fmt == "m"* ]]; then
|
||||
sep="|"
|
||||
fi
|
||||
|
||||
# VAR2 - Context
|
||||
typeset -i num_ctx="$2"
|
||||
context=""
|
||||
if [[ -n $num_ctx ]]; then
|
||||
context=',"options":{"num_ctx":'$num_ctx'}'
|
||||
fi
|
||||
|
||||
# Column Formatting
|
||||
col1=25
|
||||
col2=12
|
||||
col3=8
|
||||
col4=12
|
||||
spacing="$sep %-${col1}s $sep %${col2}s $sep %${col3}s $sep %${col4}s $sep"
|
||||
|
||||
#echo " Stopping all ollama usage..."
|
||||
#sudo sv restart ollama >/dev/null 2>&1
|
||||
|
||||
#echo -e "\n Checking model disk and RAM sizes...\n"
|
||||
|
||||
printf "$spacing\n" "Model Name" "HDD (ls)" "Context" "RAM (ps)"
|
||||
if [[ $fmt == "m"* ]]; then
|
||||
printf "$spacing\n" ":------------------------" "-----------:" "-------:" "-----------:"
|
||||
fi
|
||||
|
||||
for model in `ollama ls | grep -v NAME | awk '{print $1}'`; do
|
||||
#ollama run $model "" --format json >/dev/null 2>&1
|
||||
curl -s http://localhost:11434/api/generate \
|
||||
-d '{"model":"'$model'","prompt":"","stream":false,"keep_alive":"1m"'$context'}' \
|
||||
>/dev/null 2>&1
|
||||
status=$?
|
||||
|
||||
hdd="`ollama ls | grep $model | awk '{print $3 $4}'`"
|
||||
ram="`ollama ps | grep $model | awk '{print $3 $4}'`"
|
||||
ctx="`ollama ps | grep $model | awk '{print $7}'`"
|
||||
|
||||
if [[ "$status" != 0 ]]; then
|
||||
ram="TOO LARGE $ram"
|
||||
ctx="FAIL $ctx"
|
||||
sleep 10
|
||||
fi
|
||||
|
||||
printf "$spacing\n" "$model" "$hdd" "$ctx" "$ram"
|
||||
|
||||
ollama stop $model >/dev/null 2>&1
|
||||
while ollama ps | grep $model; do
|
||||
sleep 1
|
||||
done
|
||||
done
|
||||
|
||||
#echo "Done!!"
|
||||
}
|
||||
alias ollama-sizes="ollama_sizes "
|
||||
alias model-sizes="ollama_sizes "
|
||||
alias model-memory="ollama_sizes "
|
||||
alias model-mem="ollama_sizes "
|
||||
|
||||
function ollama_threads() {
|
||||
# VAR1 - Model
|
||||
model="$1"
|
||||
if [[ -z $model ]]; then
|
||||
model="qwen3.5:4b"
|
||||
fi
|
||||
|
||||
# VAR2 - Context
|
||||
typeset -i num_ctx="$2"
|
||||
context=""
|
||||
if [[ -n $num_ctx ]]; then
|
||||
context=',"num_ctx":'$num_ctx''
|
||||
fi
|
||||
|
||||
# Physical CPU Count (no longer using ansible_processor_vcpus, {{ ansible_processor_vcpus }})
|
||||
# Will be something like 0-7, then get expanded to 0 1 2 3 4 5 6 7.
|
||||
# Runnning with 0 causes default behavior, 1 per physical core, 8!
|
||||
cores=$(cat /sys/devices/cpu_core/cpus | tr ',' '\n' | sed 's/-/ /' | xargs -L1 seq)
|
||||
|
||||
# Flatten the output (trims newlines and extra spacing).
|
||||
cores=$(echo $cores)
|
||||
|
||||
# Take out useless tests. 1 CPU is silly. If we have 8 physical then
|
||||
# only need to look at 4, 6, 7, and 8 (which is done by 0/default).
|
||||
cores=${cores/ 1 / }
|
||||
if [[ "$cores" == *" 7" ]]; then
|
||||
cores=${cores/ 2 / }
|
||||
cores=${cores/ 3 / }
|
||||
cores=${cores/ 5 / }
|
||||
fi
|
||||
|
||||
# Do the 0 test last.
|
||||
cores="${cores/0 / } 0"
|
||||
|
||||
#echo " Stopping all ollama usage..."
|
||||
#sudo sv restart ollama >/dev/null 2>&1
|
||||
|
||||
# Benchmark Thread Count
|
||||
for t in $cores; do
|
||||
start=$SECONDS
|
||||
echo -n "`date` - $model w/ $t Thread(s): "
|
||||
|
||||
speed=$(curl -s http://localhost:11434/api/generate \
|
||||
-d '{"model":"'$model'","prompt":"Hello","stream":false,"keep_alive":"1m","options":{"num_thread":'$t$context'}}' \
|
||||
| jq '.eval_count * 1000000000 / .eval_duration'
|
||||
)
|
||||
finish=$SECONDS
|
||||
ctx="`ollama ps | grep $model | awk '{print $7}'`"
|
||||
time=$(( $finish - $start ))
|
||||
|
||||
#echo "tokens/sec: $speed @ context=$ctx, time: $time secs"
|
||||
printf "%-32s %18s %16s\n" "tokens/sec: $speed" "@ context=$ctx," "time: $time secs"
|
||||
|
||||
ollama stop $model >/dev/null 2>&1
|
||||
done
|
||||
}
|
||||
alias ollama-threads="ollama_threads "
|
||||
alias ollama-cpus="ollama_threads "
|
||||
alias ollama-cpu="ollama_threads "
|
||||
|
||||
function ollama_benchmark_usage() {
|
||||
cat <<- EOF
|
||||
USAGE: ollama-benchmark CONTEXTS [THREADS] [IGPUS] [MODELS] [-h | --help]
|
||||
|
||||
Tests installed models at a certain context, thread count, and iGPU setting.
|
||||
|
||||
PARAMETERS
|
||||
|
||||
CONTEXTS
|
||||
Sent as num_ctx to ollama. No default.
|
||||
THREADS
|
||||
Sent as num_threads to ollama. Defaults to 0.
|
||||
IGPUS
|
||||
Values to set OLLAMA_IGPU_ENABLE to. Defaults to 1.
|
||||
MODELS
|
||||
Model names to test. Defaults to all of `ollama ls`.
|
||||
|
||||
EXAMPLES:
|
||||
|
||||
Test models with at a context of 32000, default threads, and iGPU enabled.
|
||||
ollama-benchmark 32000 0 1
|
||||
|
||||
Test qwen3.5:4b with at a context of 128k, 4 threads, and iGPU disabled.
|
||||
ollama-benchmark 128000 4 0 qwen3.5:4b
|
||||
|
||||
Variables can also be specified through variables:
|
||||
|
||||
context=64000 threads=7 igpu=0 ollama-benchmark
|
||||
context=64000 threads=7 ollama-benchmark
|
||||
context=64000 igpu=0 ollama-benchmark
|
||||
context=64000 model=qwen3.5:4b ollama-benchmark
|
||||
|
||||
The parameters can also act as arrays to cause extra looping.
|
||||
|
||||
ollama-benchmark "32000 64000 128000 256000" "4 7 0" "0 1" \
|
||||
"qwen3.8:27b qwen3.6:35b qwen3.6:27b qwen3.5:35b qwen3.5:27b"
|
||||
|
||||
Aliases:
|
||||
|
||||
ollama-test
|
||||
EOF
|
||||
}
|
||||
|
||||
function ollama_benchmark() {
|
||||
# Parameters
|
||||
|
||||
if [[ "$@" == *"-h"* || "$@" == *"--help"* ]]; then
|
||||
ollama_benchmark_usage
|
||||
return 0
|
||||
fi
|
||||
|
||||
contexts="${1:-$contexts}"
|
||||
if [[ -z "$contexts" ]]; then
|
||||
echo " ERROR: Context is required."
|
||||
ollama_benchmark_usage
|
||||
return 1
|
||||
fi
|
||||
|
||||
threads="${2:-$threads}"
|
||||
if [[ -z $threads ]]; then
|
||||
threads=0
|
||||
fi
|
||||
|
||||
igpus="${3:-$igpus}"
|
||||
if [[ -z "$igpus" ]] ; then
|
||||
igpus=1
|
||||
fi
|
||||
|
||||
models="${4:-$models}"
|
||||
if [[ -z "$models" ]]; then
|
||||
models="`ollama ls | grep -v NAME | awk '{print $1}'`"
|
||||
fi
|
||||
|
||||
DEBUG="${DEBUG}"
|
||||
QUIET="${QUIET}"
|
||||
[[ -z "$QUIET" ]] && echo -e "\n Sharing run parameters..."
|
||||
[[ -z "$QUIET" ]] && cat <<- EOF
|
||||
DEBUG=$DEBUG
|
||||
QUIET=$QUIET
|
||||
context=$context
|
||||
threads=$threads
|
||||
igpu=$igpu
|
||||
model=$model
|
||||
EOF
|
||||
[[ -z "$QUIET" ]] && echo " Done!"
|
||||
|
||||
# Variables
|
||||
|
||||
col_mdl=25
|
||||
col_hdd=6
|
||||
col_ctx=8
|
||||
col_ram=6
|
||||
col_thr=7
|
||||
col_gpu=4
|
||||
col_cpu=9
|
||||
col_spd=11 col_spd_round=2
|
||||
col_tim=8
|
||||
|
||||
log_file="ollama_benchmark.log.txt"
|
||||
[[ -z "$QUIET" ]] && echo -e "\n Logging ollama to '$log_file'..."
|
||||
|
||||
declare champ_{s,t}_{mdl,num,ctx,thr}
|
||||
|
||||
# Functions
|
||||
|
||||
function wait_for_ollama() {
|
||||
while ! ollama ps >/dev/null 2>&1; do
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
|
||||
# Main
|
||||
|
||||
if [[ ! -d /sdcard && -d /etc/sv ]]; then
|
||||
[[ -z "$QUIET" ]] && echo -e "\n Stopping ollama runit service..."
|
||||
sudo sv disable ollama >/dev/null 2>&1
|
||||
sudo sv stop ollama >/dev/null 2>&1
|
||||
sleep 5
|
||||
[[ -z "$QUIET" ]] && echo " Done!"
|
||||
fi
|
||||
|
||||
[[ -z "$QUIET" ]] && echo -e "\n Starting main loop... \n"
|
||||
|
||||
declare GRY="`tput setaf 8`" WHT="`tput setaf 7`" RST="`tput sgr0`"
|
||||
|
||||
printf "$WHT| %-${col_mdl}s | %${col_hdd}s | %${col_ctx}s | %${col_ram}s | %${col_thr}s | %${col_gpu}s | %${col_cpu}s | %${col_spd}s | %${col_tim}s |\n" \
|
||||
"Model" "HDD" "Context" "RAM" "Threads" "iGPU" "Processor" "Speed (t/s)" "Time (s)"
|
||||
|
||||
printf "| %-${col_mdl}s | %${col_hdd}s | %${col_ctx}s | %${col_ram}s | %${col_thr}s | %${col_gpu}s | %${col_cpu}s | %${col_spd}s | %${col_tim}s |$RST\n" \
|
||||
":------------------------" "-----:" "-------:" "-----:" "------:" "---:" "--------:" "----------:" "-------:"
|
||||
|
||||
|
||||
last_igpu=""
|
||||
count=0
|
||||
for model in $models; do
|
||||
for context in $contexts; do
|
||||
for thread in $threads; do
|
||||
for igpu in $igpus; do
|
||||
if [[ -z "$last_igpu" || "$last_igpu" != "$igpu" ]]; then
|
||||
killall ollama >/dev/null 2>&1
|
||||
sleep 5
|
||||
export OLLAMA_IGPU_ENABLE=$igpu
|
||||
export OLLAMA_VULKAN=$igpu
|
||||
(ollama serve >$log_file 2>&1 &)
|
||||
wait_for_ollama
|
||||
sleep 5
|
||||
fi
|
||||
last_igpu="$igpu"
|
||||
|
||||
declare CLR="$WHT"
|
||||
if (( count % 2 == 1 )); then
|
||||
CLR="$GRY"
|
||||
fi
|
||||
(( count++ ))
|
||||
|
||||
hdd="`ollama ls | grep $model | awk '{print $3 $4}'`"
|
||||
printf "$CLR| %-${col_mdl}s | %${col_hdd}s | " "$model" "$hdd"
|
||||
|
||||
# Start the model and store the response.
|
||||
start=$SECONDS
|
||||
speed_json=$(curl -s http://localhost:11434/api/generate \
|
||||
-d '{"model":"'$model'","prompt":"Hello","stream":false,"keep_alive":"1m","options":{"num_ctx":'$context',"num_thread":'$thread'}}' \
|
||||
2>/dev/null
|
||||
)
|
||||
status_ollama=$?
|
||||
finish=$SECONDS
|
||||
|
||||
[[ -n "$DEBUG" ]] && echo "DEBUG: status_ollama=$status_ollama"
|
||||
|
||||
time=$(( $finish - $start ))
|
||||
|
||||
# Calculate the values if we got a successful response.
|
||||
declare ram cpu ctx speed status_jq=0
|
||||
if [[ "$status_ollama" == 0 ]]; then
|
||||
speed=$(echo "$speed_json" | jq '.eval_count * 1000000000 / .eval_duration' 2>/dev/null)
|
||||
status_jq=$?
|
||||
[[ -n "$DEBUG" ]] && echo "DEBUG: status_jq=$status_jq"
|
||||
if [[ "$status_jq" != 0 ]]; then
|
||||
speed=0
|
||||
fi
|
||||
else
|
||||
[[ -n "$DEBUG" ]] && echo "DEBUG: Using failed values. (ollama)"
|
||||
ctx="OLLAMA"
|
||||
ram="DIED"
|
||||
cpu="FAIL"
|
||||
speed=0
|
||||
killall ollama
|
||||
(ollama serve >>$log_file 2>&1 &)
|
||||
wait_for_ollama
|
||||
fi
|
||||
|
||||
if [[ "$status_jq" != 0 ]]; then
|
||||
[[ -n "$DEBUG" ]] && echo "DEBUG: Using failed values. (jq)"
|
||||
ctx="RESPONSE"
|
||||
ram="MLFRMD"
|
||||
cpu="FAIL"
|
||||
speed=0
|
||||
fi
|
||||
|
||||
if [[ "$status_jq" == 0 && "$status_jq" == 0 ]]; then
|
||||
[[ -n "$DEBUG" ]] && echo "DEBUG: Using successful values."
|
||||
ram="`ollama ps | grep $model | awk '{print $3 $4}'`"
|
||||
cpu="`ollama ps | grep $model | awk '{print $5 $6}'`"
|
||||
ctx="`ollama ps | grep $model | awk '{print $7}'`"
|
||||
|
||||
[[ -n "$DEBUG" ]] && echo "DEBUG: champ_s_num=$champ_s_num, speed=$speed"
|
||||
if [[ -z "$champ_s_num" ]] \
|
||||
|| awk -v a="$speed" -v b="$champ_s_num" 'BEGIN { exit !(a > b) }'
|
||||
then
|
||||
[[ -n "$DEBUG" ]] && echo "DEBUG: New speed champ!"
|
||||
champ_s_num="$speed"
|
||||
champ_s_mdl="$model"
|
||||
champ_s_ctx="$ctx"
|
||||
champ_s_thr="$thr"
|
||||
fi
|
||||
|
||||
[[ -n "$DEBUG" ]] && echo "DEBUG: champ_t_num=$champ_t_num, time=$time"
|
||||
if [[ -z "$champ_t_num" ]] \
|
||||
|| awk -v a="$time" -v b="$champ_t_num" 'BEGIN { exit !(a < b) }'
|
||||
then
|
||||
[[ -n "$DEBUG" ]] && echo "DEBUG: New time champ!"
|
||||
champ_t_num="$time"
|
||||
champ_t_mdl="$model"
|
||||
champ_t_ctx="$ctx"
|
||||
champ_t_thr="$thr"
|
||||
fi
|
||||
fi
|
||||
|
||||
printf "%${col_ctx}s | %${col_ram}s | %${col_thr}s | %${col_gpu}s | %${col_cpu}s | %${col_spd}.${col_spd_round}f | %${col_tim}s |$RST\n" \
|
||||
"$ctx" "$ram" "$thread" "$igpu" "$cpu" "$speed" "$time"
|
||||
|
||||
ollama stop $model >/dev/null 2>&1
|
||||
while ollama ps | grep "$model"; do
|
||||
[[ -n "DEBUG" ]] && echo "DEBUG: Waiting for model to finish..."
|
||||
sleep 1
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
|
||||
echo -e "\n Done!! :D \n"
|
||||
cat <<- EOF
|
||||
Speed Champion: $champ_s_mdl at ${champ_s_thr}-$champ_s_ctx with a tokens/seconds of ${champ_s_num}!
|
||||
Time Champion: $champ_t_mdl at ${champ_t_thr}-$champ_t_ctx with a time of ${champ_t_num}!
|
||||
EOF
|
||||
|
||||
# Finish
|
||||
|
||||
[[ -z "$QUIET" ]] && echo -e "\n Killing local ollama serve..."
|
||||
killall ollama
|
||||
[[ -z "$QUIET" ]] && echo " Done!"
|
||||
|
||||
if [[ ! -d /sdcard && -d /etc/sv ]]; then
|
||||
[[ -z "$QUIET" ]] && echo -e "\n Restarting runit service..."
|
||||
sudo sv enable ollama >/dev/null 2>&1
|
||||
sudo sv start ollama >/dev/null 2>&1
|
||||
[[ -z "$QUIET" ]] && echo " Done!"
|
||||
fi
|
||||
|
||||
[[ -z "$QUIET" ]] && echo -e "\n Done!!! :)"
|
||||
}
|
||||
alias ollama-benchmark="ollama_benchmark "
|
||||
alias ollama-test="ollama_benchmark "
|
||||
|
||||
### Finalize ###
|
||||
|
||||
# Export all functions! #
|
||||
eval "$(declare -F | grep -v _ | sed 's/-f /-fx /')"
|
||||
|
||||
Reference in new issue
Block a user