get-tracks/get-tracks.sh

159 lines
3.2 KiB
Bash
Executable File

#!/usr/bin/env sh
get_time(){
echo "$*" | sed "s/[ \t].*//"
}
get_title(){
echo "$*" | cut -d ' ' -f 2-
}
reverse_word_order(){
local result=
for word in $@; do
result="$word $result"
done
echo "$result"
}
# bc is mandatory: arythmetic operations are very limited in ash.
get_seconds(){
local n=0
local v=0
values=$(echo "$*" | sed 's/:/\
/g' | sed "s/^0//")
for i in $(reverse_word_order $values); do
case $n in
0) v=$(echo "$v + $i " | bc);;
1) v=$(echo "$v + (60 * $i)" | bc);;
2) v=$(echo "$v + (3600 * $i)" | bc);;
*) echo "invalid timecode $*"; exit 1;;
esac
n=$((n+1))
done
echo $v
}
# Get a more usable time representation for the beginning and the end of songs.
get_values(){
audio_file="$1"
time_file="$2"
total_length=$(soxi -D "${audio_file}" | sed "s/\..*//") # integer values only
n=0
while read X; do
if [ $n -ne 0 ]; then
to=$(get_time $X)
to_s=$(get_seconds $to)
echo -e "$from_s\t$to_s\t$title"
fi
#echo $X
from=$(get_time $X)
from_s=$(get_seconds $from)
title=$(get_title $X)
if [ -z "${WITH_NUMBER}" ]; then
:
else
title="${n}${WITH_NUMBER}${title}"
fi
n=$(echo $n + 1 | bc)
done < "${time_file}"
echo -e "$from_s\t$total_length\t$title"
}
run_ffmpeg(){
local file=$1
local from=$2
local duration=$3
local title=$4
if [ "${SIMULATION}" -eq 1 ]; then
[ -z "${QUIET}" ] && echo "ffmpeg -loglevel error -ss '$from' -t '$duration' -i '${file}' '${title}'"
else
[ -z "${QUIET}" ] && echo "ffmpeg -loglevel error -ss '$from' -t '$duration' -i '${file}' '${title}'"
$(< /dev/null ffmpeg -loglevel quiet -ss "$from" -t "$duration" -i "${file}" "${title}")
fi
}
rip(){
n=0
from=0
to=0
audio_file="$1"
time_file="$2"
[ "$FORMAT" = "" ] && echo "default format: opus" && FORMAT="opus"
#echo "from to duration title"
get_values "$audio_file" "$time_file" | while read LINE; do
from=$(echo $LINE | cut -d ' ' -f 1)
to=$(echo $LINE | cut -d ' ' -f 2)
title=$(echo $LINE | cut -d ' ' -f 3-)
duration=$(echo "$to - $from" | bc)
run_ffmpeg "${audio_file}" "${from}" "${duration}" "${title}.${FORMAT}"
n=$((n + 1))
done
}
usage(){
echo "usage: $0 command"
echo "command: show <single-file-playlist> <song-list>"
echo "command: rip <single-file-playlist> <song-list>"
echo
echo "song-list line format example: 1:30 My second track of the playlist"
echo "show output format: start end title"
echo
echo "envvar: SIMULATION [0|1] (do not invoke ffmpeg)"
echo "envvar: FORMAT [mp3,ogg,opus,…] (see the ffmpeg documentation)"
echo "envvar: WITH_NUMBER [separator] (not null = write song number, with this separator)"
echo " example: WITH_NUMBER=_ Song names will be 1_song.opus 2_song.opus…"
echo "envvar: QUIET (if set to any value, ffmpeg commands are not displayed)"
}
if [ $# -lt 1 ]; then
usage
exit 0
fi
command=$1
shift
case "x-${command}" in
x-show)
# Takes the audio file in first parameter
if [ $# -ne 2 ]; then
echo "Usage: $0 show music-file time-stamps-file"
exit 1
fi
get_values "$1" "$2"
;;
x-rip)
# Takes the audio file in first parameter
if [ $# -ne 2 ]; then
echo "Usage: $0 show music-file time-stamps-file"
exit 1
fi
rip "$1" "$2"
;;
*)
usage 1>&2
exit 1
esac