Last active
August 12, 2024 22:16
-
-
Save jaggzh/f687be9a23d267e641dc7ff7a1967b9a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# gist-paste -u https://gist.github.com/jaggzh/f687be9a23d267e641dc7ff7a1967b9a spect | |
# Dependencies: | |
# ffmpeg (we extract audiosecs=60 for the spectrogram) | |
# sox (for spectrogram image creation) | |
# chafa (for conversion of spectrogram to text) | |
tmpdel_s=$((60)) # 5 minutes | |
def_maxh=5 | |
def_maxh_1=16 # Height for 1 file | |
def_maxh_2=10 # Height for each of 2 files | |
hw=$(stty size) | |
bin_chafa=$(which chafa) | |
if [[ -z $bin_chafa ]]; then | |
echo "You'll need to install chafa to generate the spectograms" >&2 | |
exit 1 | |
fi | |
if [[ -n $hw ]]; then | |
h=${hw% *} | |
[[ $h -gt $def_maxh ]] && h=$def_maxh | |
w=${hw#* } | |
else | |
w=140 | |
h=20 | |
echo "No term. Using default sizes: WxH ${w}x$h" | |
fi | |
# echo "Height: $h" | |
# echo "W: $w" | |
files=() | |
a=$1 | |
opt_h= | |
while shift; do | |
case "$a" in | |
-h|--help) h=$1; opt_h=$1; shift ;; | |
*) files+=("$a") | |
esac | |
a=$1 | |
done | |
if [[ ${#files[@]} -lt 1 ]]; then | |
echo "Display spectrogram in terminal" | |
echo "Usage: spect audio1.ext [..audioN.ext]" | |
exit | |
fi | |
if [[ -z $opt_h ]]; then | |
if [[ ${#files[@]} = 1 ]]; then | |
h=$def_maxh_1 | |
elif [[ ${#files[@]} = 2 ]]; then | |
h=$def_maxh_2 | |
fi | |
fi | |
clean_up() { | |
( | |
sleep "$tmpdel_s"; | |
[[ -f $of ]] && rm -f "$of"; | |
[[ -f $ofw ]] && rm -f "$ofw"; | |
) &> /dev/null & disown; | |
} | |
trap clean_up EXIT | |
umask 0177 | |
of=$(mktemp "/tmp/imgspec-XXXXXX.png") | |
ofw=$(mktemp "/tmp/imgspec-XXXXXX.wav") | |
# ls -l "$of" | |
audiosecs=60 | |
sw=$(((w*2)-1)) | |
for f in "${files[@]}"; do | |
# echo "Working on: $f" >&2 | |
fname=$f | |
if [[ $f = *.mp3 ]]; then | |
# Convert "$audiosecs" of $f and stores it in wav file named "$ofw" | |
# echo "Converting $f with ffmpeg..." >&2 | |
ffmpeg -hide_banner -y -i "$f" -t "$audiosecs" "$ofw" &>/dev/null </dev/null | |
f="$ofw" | |
if [[ ! -f $ofw ]]; then | |
echo "No output audio created by ffmpeg in conversion of mp3" >&2 | |
echo " Input: $f" >&2 | |
echo " Output: $ofw (not found)" >&2 | |
continue | |
fi | |
fi | |
samps=$(sox "$f" -n stat 2>&1 | grep 'Samples.read' | sed -e 's/^.*: *//') | |
if [[ $samps = 0 ]]; then | |
echo "Sox says file is 0 samples. Skipping: $fname" | |
else | |
sox "$f" \ | |
-q \ | |
-n trim 0 "$audiosecs" spectrogram \ | |
-x "$sw" \ | |
-y 64 \ | |
-r \ | |
-o "$of" &>/dev/null | |
soxrc=$? | |
if [[ $soxrc -ne 0 ]]; then | |
echo "Sox errored (rc: $soxrc) on file $f (it might be incomplete)" >&2 | |
elif [[ ! -f $of ]]; then | |
echo "No spectrogram found at: $of" >&2 | |
else | |
chafa -c full -f symbols \ | |
--stretch \ | |
-s ${w}x$h \ | |
"$of" | |
echo -e '\033[A^' | |
fi | |
fi | |
printf '%s\n' "$fname" | |
done | |
echo "Done. Temp spectrogram ($of) will be deleted in $tmpdel_s seconds." |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# gist-paste -u https://gist.github.com/jaggzh/f687be9a23d267e641dc7ff7a1967b9a | |
tmpdel_s=$((60)) # 5 minutes | |
def_maxh=5 | |
def_maxh_1=16 # Height for 1 file | |
def_maxh_2=10 # Height for each of 2 files | |
hw=$(stty size) | |
bin_chafa=$(which chafa) | |
if [[ -z $bin_chafa ]]; then | |
echo "You'll need to install chafa to generate the spectograms" >&2 | |
exit 1 | |
fi | |
if [[ -n $hw ]]; then | |
h=${hw% *} | |
[[ $h -gt $def_maxh ]] && h=$def_maxh | |
w=${hw#* } | |
else | |
w=140 | |
h=20 | |
echo "No term. Using default sizes: WxH ${w}x$h" | |
fi | |
# echo "Height: $h" | |
# echo "W: $w" | |
files=() | |
a=$1 | |
opt_h= | |
while shift; do | |
case "$a" in | |
-h|--help) h=$1; opt_h=$1; shift ;; | |
*) files+=("$a") | |
esac | |
a=$1 | |
done | |
if [[ ${#files[@]} -lt 1 ]]; then | |
echo "Display spectrogram in terminal" | |
echo "Usage: spect audio1.ext [..audioN.ext]" | |
exit | |
fi | |
if [[ -z $opt_h ]]; then | |
if [[ ${#files[@]} = 1 ]]; then | |
h=$def_maxh_1 | |
elif [[ ${#files[@]} = 2 ]]; then | |
h=$def_maxh_2 | |
fi | |
fi | |
clean_up() { | |
( | |
sleep "$tmpdel_s"; | |
[[ -f $of ]] && rm -f "$of"; | |
[[ -f $ofw ]] && rm -f "$ofw"; | |
) & disown; | |
} | |
trap clean_up EXIT | |
umask 0177 | |
of=$(mktemp "/tmp/imgspec-XXXXXX.png") | |
ofw=$(mktemp "/tmp/imgspec-XXXXXX.wav") | |
# ls -l "$of" | |
audiosecs=60 | |
sw=$(((w*2)-1)) | |
for f in "${files[@]}"; do | |
# echo "Working on: $f" >&2 | |
fname=$f | |
if [[ $f = *.mp3 ]]; then | |
# Convert "$audiosecs" of $f and stores it in wav file named "$ofw" | |
# echo "Converting $f with ffmpeg..." >&2 | |
ffmpeg -hide_banner -y -i "$f" -t "$audiosecs" "$ofw" &>/dev/null </dev/null | |
f="$ofw" | |
if [[ ! -f $ofw ]]; then | |
echo "No output audio created by ffmpeg in conversion of mp3" >&2 | |
echo " Input: $f" >&2 | |
echo " Output: $ofw (not found)" >&2 | |
continue | |
fi | |
fi | |
samps=$(sox "$f" -n stat 2>&1 | grep 'Samples.read' | sed -e 's/^.*: *//') | |
if [[ $samps = 0 ]]; then | |
echo "Sox says file is 0 samples. Skipping: $fname" | |
else | |
sox "$f" \ | |
-q \ | |
-n trim 0 "$audiosecs" spectrogram \ | |
-x "$sw" \ | |
-y 64 \ | |
-r \ | |
-o "$of" &>/dev/null | |
soxrc=$? | |
if [[ $soxrc -ne 0 ]]; then | |
echo "Sox errored (rc: $soxrc) on file $f (it might be incomplete)" >&2 | |
elif [[ ! -f $of ]]; then | |
echo "No spectrogram found at: $of" >&2 | |
else | |
chafa -c full -f symbols \ | |
--stretch \ | |
-s ${w}x$h \ | |
"$of" | |
echo -e '\033[A^' | |
fi | |
fi | |
printf '%s\n' "$fname" | |
done | |
echo "Done. Temp spectrogram ($of) will be deleted in $tmpdel_s seconds." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment