First commit.
commit
8cdf42cedd
|
@ -0,0 +1,34 @@
|
||||||
|
# Required applications
|
||||||
|
|
||||||
|
* soxi
|
||||||
|
* ffmpeg
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
```Bash
|
||||||
|
get-tracks.sh rip audio-file time-file
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
`audio-file` can be in any format understood by `soxi` and `ffmpeg`
|
||||||
|
|
||||||
|
In the `time-file`:
|
||||||
|
|
||||||
|
```
|
||||||
|
0:00 First song
|
||||||
|
2:20 Second song
|
||||||
|
3:18 Awesome song
|
||||||
|
```
|
||||||
|
|
||||||
|
# Environment variables
|
||||||
|
|
||||||
|
* SIMULATION [0|1] do not invoke ffmpeg
|
||||||
|
* FORMAT [mp3,ogg,opus,…] for the song file format
|
||||||
|
* WITH_NUMBER [separator] if not null, write song number with this separator
|
||||||
|
example: WITH_NUMBER=_ Song names will be 1_song.opus 2_song.opus (...)
|
||||||
|
* QUIET: if set to any value, ffmpeg commands are not displayed
|
||||||
|
|
||||||
|
|
||||||
|
# More
|
||||||
|
|
||||||
|
Run `get-track.sh` without arguments.
|
|
@ -0,0 +1,158 @@
|
||||||
|
#!/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
|
Loading…
Reference in New Issue