add "copy" destination type

This commit is contained in:
Vincent Riquer 2017-06-18 18:21:18 +02:00
parent 6c438c4c90
commit d16b31f479
10 changed files with 308 additions and 265 deletions

View File

@ -9,6 +9,9 @@ getConfigDestination() {
'mp3') 'mp3')
destinationformat["$destination"]=mp3 destinationformat["$destination"]=mp3
lameneeded=1 lameneeded=1
# MP3 can't handfle more than 2 channels
[[ -z ${destinationchannels["$destination"]} ]] \
&& destinationchannels["$destination"]=2
;; ;;
'opus') 'opus')
destinationformat["$destination"]=opus destinationformat["$destination"]=opus
@ -18,6 +21,9 @@ getConfigDestination() {
destinationformat["$destination"]=vorbis destinationformat["$destination"]=vorbis
oggencneeded=1 oggencneeded=1
;; ;;
'copy')
destinationformat["$destination"]=copy
;;
*) *)
echo "Unsupported destination format: $value" >&2 echo "Unsupported destination format: $value" >&2
exit $EFORMAT exit $EFORMAT

View File

@ -48,10 +48,10 @@ printConfig() {
EOF EOF
[ -n "${destinationskipmime["$destination"]}" ] \ [ -n "${destinationskipmime["$destination"]}" ] \
&& echo " |Skipped mime-types|${destinationskipmime["$destination"]//\|/ && echo " |Skipped mime-types|${destinationskipmime["$destination"]//\|/
||}" | | |}"
[ -n "${destinationmskipime["$destination"]}" ] \ [ -n "${destinationcopymime["$destination"]}" ] \
&& echo " |Copied mime-types|${destinationcopymime["$destination"]//\|/ && echo " |Copied mime-types|${destinationcopymime["$destination"]//\|/
||}" | | |}"
done done
}|column -t -s'|' }|column -t -s'|'
} }

View File

@ -63,8 +63,8 @@ path $sourcepath
# * path: Where files will be written # * path: Where files will be written
path ${destinationpath["$destination"]} path ${destinationpath["$destination"]}
# * format: ogg, opus or mp3. Other formats may appear in the future - feel # * format: copy, ogg, opus or mp3. Other formats may appear in the future -
# free to implement your preferred format. # feel free to implement your preferred format.
format ${destinationformat["$destination"]} format ${destinationformat["$destination"]}
EOCfg EOCfg

View File

@ -1,39 +1,14 @@
#!/bin/bash #!/bin/bash
declare soxtaskid declare soxtaskid
decodeFile() { decodeFile() {
case "$mimetype" in if [[ ${destinationformat["$destination"]} == copy ]]
'video/'*) then
(( disablevideo )) && continue copied=1
extractAudio else
if (( ${destinationnormalize["$destination"]}))\ case "$mimetype" in
|| ( 'video/'*)
[ -n "${destinationfrequency["$destination"]}" ]\ (( disablevideo )) && continue
&& (( ${rate:-0} != ${destinationfrequency["$destination"]}))\ extractAudio
) || (
[ -n "${destinationchannels["$destination"]}" ]\
&& (( ${channels:-0} != ${destinationchannels["$destination"]} ))
)
then
sox_needed=1
fi
;;
'audio/mpeg')
if [[ ${destinationformat[$destination]} = mp3 ]] \
&& checkCopy
then
copied=1
else
decodeSox
fi
;;
'application/ogg opus')
if [[ ${destinationformat[$destination]} = opus ]] \
&& checkCopy
then
copied=1
else
(( disableopusdec )) && continue
decodeOpusdec
if (( ${destinationnormalize["$destination"]}))\ if (( ${destinationnormalize["$destination"]}))\
|| ( || (
[ -n "${destinationfrequency["$destination"]}" ]\ [ -n "${destinationfrequency["$destination"]}" ]\
@ -45,26 +20,24 @@ decodeFile() {
then then
sox_needed=1 sox_needed=1
fi fi
fi ;;
;; 'audio/mpeg')
'application/ogg'*) if [[ ${destinationformat[$destination]} = mp3 ]] \
if [[ ${destinationformat[$destination]} = vorbis ]] \ && checkCopy
&& checkCopy then
then copied=1
copied=1 else
else decodeSox
decodeSox fi
fi ;;
;; 'application/ogg opus')
'audio/x-flac') if [[ ${destinationformat[$destination]} = opus ]] \
decodeSox && checkCopy
;; then
*) copied=1
extendedtype=$(file -b "$sourcepath/$filename") else
case "$extendedtype" in (( disableopusdec )) && continue
*'Musepack '*) decodeOpusdec
(( disablempcdec )) && continue
decodeMpcdec
if (( ${destinationnormalize["$destination"]}))\ if (( ${destinationnormalize["$destination"]}))\
|| ( || (
[ -n "${destinationfrequency["$destination"]}" ]\ [ -n "${destinationfrequency["$destination"]}" ]\
@ -76,13 +49,26 @@ decodeFile() {
then then
sox_needed=1 sox_needed=1
fi fi
;; fi
*) ;;
if (( disablevideo )) 'application/ogg'*)
then if [[ ${destinationformat[$destination]} = vorbis ]] \
decodeSox && checkCopy
else then
extractAudio copied=1
else
decodeSox
fi
;;
'audio/x-flac')
decodeSox
;;
*)
extendedtype=$(file -b "$sourcepath/$filename")
case "$extendedtype" in
*'Musepack '*)
(( disablempcdec )) && continue
decodeMpcdec
if (( ${destinationnormalize["$destination"]}))\ if (( ${destinationnormalize["$destination"]}))\
|| ( || (
[ -n "${destinationfrequency["$destination"]}" ]\ [ -n "${destinationfrequency["$destination"]}" ]\
@ -94,41 +80,36 @@ decodeFile() {
then then
sox_needed=1 sox_needed=1
fi fi
fi ;;
;; *)
esac if (( disablevideo ))
;; then
esac decodeSox
if ! (( copied )) else
then extractAudio
if ! decodetaskid=$( if (( ${destinationnormalize["$destination"]}))\
Select tasks id <<<"key = $tmpfile" || (
) [ -n "${destinationfrequency["$destination"]}" ]\
&& (( ${rate:-0} != ${destinationfrequency["$destination"]}))\
) || (
[ -n "${destinationchannels["$destination"]}" ]\
&& (( ${channels:-0} != ${destinationchannels["$destination"]} ))
)
then
sox_needed=1
fi
fi
;;
esac
;;
esac
if ! (( copied ))
then then
decodetaskid=$( if ! decodetaskid=$(
Insert tasks <<-EOInsert
key $tmpfile
source_file $fileid
$(
for key in ${!commandline[@]}
do
echo "cmd_arg$key ${commandline[key]}"
done
)
status 0
EOInsert
)
progressSpin
fi
if (( sox_needed ))
then
cleanup="$tempdir/$tmpfile"
decodeSox "$tempdir/$tmpfile"
if ! soxtaskid=$(
Select tasks id <<<"key = $tmpfile" Select tasks id <<<"key = $tmpfile"
) )
then then
soxtaskid=$( decodetaskid=$(
Insert tasks <<-EOInsert Insert tasks <<-EOInsert
key $tmpfile key $tmpfile
source_file $fileid source_file $fileid
@ -138,14 +119,38 @@ decodeFile() {
echo "cmd_arg$key ${commandline[key]}" echo "cmd_arg$key ${commandline[key]}"
done done
) )
requires $decodetaskid
required $decodetaskid
status 0 status 0
cleanup $cleanup
EOInsert EOInsert
) )
progressSpin progressSpin
fi fi
if (( sox_needed ))
then
cleanup="$tempdir/$tmpfile"
decodeSox "$tempdir/$tmpfile"
if ! soxtaskid=$(
Select tasks id <<<"key = $tmpfile"
)
then
soxtaskid=$(
Insert tasks <<-EOInsert
key $tmpfile
source_file $fileid
$(
for key in ${!commandline[@]}
do
echo "cmd_arg$key ${commandline[key]}"
done
)
requires $decodetaskid
required $decodetaskid
status 0
cleanup $cleanup
EOInsert
)
progressSpin
fi
fi
fi fi
fi fi
} }

View File

@ -38,6 +38,25 @@ getDestDir() {
) )
) )
then then
if (( ${destinationascii["$destination"]} ))
then
echo "$album" >&${toascii[1]}
read -r -u${toascii[0]} album
echo "$albumartist" >&${toascii[1]}
read -r -u${toascii[0]} albumartist
echo "$artist" >&${toascii[1]}
read -r -u${toascii[0]} artist
echo "$genre" >&${toascii[1]}
read -r -u${toascii[0]} genre
echo "$title" >&${toascii[1]}
read -r -u${toascii[0]} title
echo "$tracknumber" >&${toascii[1]}
read -r -u${toascii[0]} tracknumber
echo "$year" >&${toascii[1]}
read -r -u${toascii[0]} year
echo "$disc" >&${toascii[1]}
read -r -u${toascii[0]} disc
fi
replace=$(sanitizeFile "$album" dir) replace=$(sanitizeFile "$album" dir)
destdir+="${destinationrenamepath[$destination]//?(\[)%\{album\}?(\])/$replace}" destdir+="${destinationrenamepath[$destination]//?(\[)%\{album\}?(\])/$replace}"
replace=$(sanitizeFile "$albumartist" dir) replace=$(sanitizeFile "$albumartist" dir)
@ -60,15 +79,16 @@ getDestDir() {
part=${filename#*/} part=${filename#*/}
while [[ $part =~ / ]] while [[ $part =~ / ]]
do do
destdir+="/$(sanitizeFile "${part%%/*}" dir)" thispart="${part%%/*}"
if (( ${destinationascii["$destination"]} ))
then
echo "$thispart" >&${toascii[1]}
read -r -u${toascii[0]} thispart
fi
destdir+="/$(sanitizeFile "$thispart" dir)"
part=${part#*/} part=${part#*/}
done done
fi fi
if (( ${destinationascii["$destination"]} ))
then
echo "$destdir" >&${toascii[1]}
read -r -u${toascii[0]} destdir
fi
if ! [ -d "$destdir" ] if ! [ -d "$destdir" ]
then then
mkdir -p "$destdir" mkdir -p "$destdir"

View File

@ -13,7 +13,7 @@ sanitizeFile() {
string=${string//>/ } string=${string//>/ }
string=${string//:/ } string=${string//:/ }
string=${string//\*/ } string=${string//\*/ }
string=${string//|/ } string=${string//\|/ }
string=${string//\"/ } string=${string//\"/ }
# Filenames can't begin or end with ' ' # Filenames can't begin or end with ' '

View File

@ -4,7 +4,7 @@ setupDestination() {
cat <<-EODesc cat <<-EODesc
Format: Format:
vorbis, opus or mp3. Other formats may appear in the future. copy, vorbis, opus or mp3. Other formats may appear in the future.
EODesc EODesc
comeagain() { comeagain() {
read \ read \
@ -25,6 +25,9 @@ setupDestination() {
destinationformat["$destination"]=vorbis destinationformat["$destination"]=vorbis
oggencneeded=1 oggencneeded=1
;; ;;
'copy')
destinationformat["$destination"]=copy
;;
*) *)
echo "Unsupported destination format: $value" >&2 echo "Unsupported destination format: $value" >&2
comeagain comeagain
@ -44,6 +47,9 @@ setupDestination() {
${destinationpath["$destination"]+-i"${destinationpath["$destination"]}"}\ ${destinationpath["$destination"]+-i"${destinationpath["$destination"]}"}\
destinationpath["$destination"] destinationpath["$destination"]
case ${destinationformat["$destination"]} in case ${destinationformat["$destination"]} in
copy)
:
;;
vorbis) vorbis)
cat <<-EODesc cat <<-EODesc
@ -199,39 +205,42 @@ setupDestination() {
Now you will have the opportunity to configure "advanced" parameters Now you will have the opportunity to configure "advanced" parameters
for $destination. You may leave any of these fields blank. for $destination. You may leave any of these fields blank.
EODesc EODesc
cat <<-EODesc if [[ ${destinationformat["$destination"]} != copy ]]
then
cat <<-EODesc
Normalize (boolean): Normalize (boolean):
Normalize output files. Normalize output files.
EODesc EODesc
case ${destinationnormalize["$destination"]} in case ${destinationnormalize["$destination"]} in
0) initialvalue=n ;; 0) initialvalue=n ;;
1) initialvalue=y ;; 1) initialvalue=y ;;
*) unset initialvalue ;; *) unset initialvalue ;;
esac
comeagain() {
read \
-e \
${initialvalue+-i $initialvalue}\
-p'Normalize (y/N): ' \
value
case $value in
[yY])
[[ $initialvalue == n ]] \
&& setupRegen normalize
destinationnormalize["$destination"]=1
;;
''|[nN])
[[ $initialvalue == y ]] \
&& setupRegen normalize
destinationnormalize["$destination"]=0
;;
*)
comeagain
;;
esac esac
} comeagain() {
comeagain read \
-e \
${initialvalue+-i $initialvalue}\
-p'Normalize (y/N): ' \
value
case $value in
[yY])
[[ $initialvalue == n ]] \
&& setupRegen normalize
destinationnormalize["$destination"]=1
;;
''|[nN])
[[ $initialvalue == y ]] \
&& setupRegen normalize
destinationnormalize["$destination"]=0
;;
*)
comeagain
;;
esac
}
comeagain
fi
cat <<-EODesc cat <<-EODesc
Rename (string): Rename (string):
@ -362,134 +371,137 @@ setupDestination() {
fi fi
done done
unset skippedmimes unset skippedmimes
cat <<-EODesc if [[ ${destinationformat["$destination"]} != copy ]]
Copy mime-type (mime-type, string):
Files with mime-type <mime-type> will be copied as-is to the
destination. E.g. image/* will copy covers and other images to the
destination. The '*' character is a wildcard.
This prompt will loop until an empty string is encountered.
EODesc
while [[ ${destinationcopymime["$destination"]} =~ \| ]]
do
copiedmimes+=("${destinationcopymime["$destination"]%%|*}")
destinationcopymime["$destination"]="${destinationcopymime["$destination"]#*|}"
done
[ -n "${destinationcopymime["$destination"]}" ] \
&& copiedmimes+=("${destinationcopymime["$destination"]}")
count=${#copiedmimes[@]}
unset destinationcopymime["$destination"]
for (( i=0 ; 1 ; i++ ))
do
read \
-e \
${copiedmimes[i]+-i"${copiedmimes[i]}"} \
-p 'Copy mime-type: ' \
value
if [ -n "$value" ]
then
destinationcopymime[$destination]="${destinationcopymime[$destination]:+${destinationcopymime[$destination]}|}$value"
elif (( i < count ))
then
continue
else
break
fi
done
unset copiedmimes
cat <<-EODesc
Channels (integer):
Produced files should have this many channels, no more, no less.
EODesc
expr='^[0-9]*$'
comeagain() {
read \
-e \
${destinationchannels["$destination"]+-i${destinationchannels["$destination"]}}\
-p'Channel count: ' \
value
if ! [[ $value =~ $expr ]]
then
echo "Invalid channel count: $value" >&2
comeagain
fi
}
comeagain
if [ -n "${destinationchannels["$destination"]}" ] \
&& (( value != ${destinationchannels["$destination"]} ))
then
setupRegen channels
fi
destinationchannels["$destination"]=$value
cat <<-EODesc
Sampling rate (Hertz, integer):
Files will be resampled as needed to the specified sampling-rate.
Shoutcast/Icecast streams require a constant sampling-rate.
Telephony systems often require a sampling-rate of 8000Hz.
EODesc
if [[ ${destinationformat["$destination"]} == opus ]]
then then
cat <<-EODesc cat <<-EODesc
Please note that Opus supports only the following sample-rates: Copy mime-type (mime-type, string):
8000, 12000, 16000, 24000, and 48000 Hz. So don't set Files with mime-type <mime-type> will be copied as-is to the
resampling on an Opus destination to any other value or files destination. E.g. image/* will copy covers and other images to the
will be resampled twice. destination. The '*' character is a wildcard.
This prompt will loop until an empty string is encountered.
EODesc EODesc
fi while [[ ${destinationcopymime["$destination"]} =~ \| ]]
comeagain() { do
read \ copiedmimes+=("${destinationcopymime["$destination"]%%|*}")
-e \ destinationcopymime["$destination"]="${destinationcopymime["$destination"]#*|}"
${destinationfrequency["$destination"]+-i${destinationfrequency["$destination"]}}\ done
-p'Sampling-rate: ' \ [ -n "${destinationcopymime["$destination"]}" ] \
value && copiedmimes+=("${destinationcopymime["$destination"]}")
if ! [[ $value =~ $expr ]] count=${#copiedmimes[@]}
then unset destinationcopymime["$destination"]
echo "Invalid frequency value: $value" >&2 for (( i=0 ; 1 ; i++ ))
comeagain do
fi read \
} -e \
comeagain ${copiedmimes[i]+-i"${copiedmimes[i]}"} \
if [ -n "${destinationfrequency["$destination"]}" ] \ -p 'Copy mime-type: ' \
&& (( value != ${destinationfrequency["$destination"]} )) value
then if [ -n "$value" ]
setupRegen frequency then
fi destinationcopymime[$destination]="${destinationcopymime[$destination]:+${destinationcopymime[$destination]}|}$value"
destinationfrequency["$destination"]=$value elif (( i < count ))
cat <<-EODesc then
continue
else
break
fi
done
unset copiedmimes
cat <<-EODesc
Higher-Than (bitrate, integer): Channels (integer):
Only reencode files with bitrates higher then <bitrate>kbps. This Produced files should have this many channels, no more, no less.
only applies if sample-rate, channel count and of course format are EODesc
equal. If unset, only files with bitrates equal to that of the expr='^[0-9]*$'
target will be copied (actually, hardlinking will be attempted comeagain() {
first). read \
-e \
As Ogg Vorbis target quality is not defined by its bitrate, Ogg ${destinationchannels["$destination"]+-i${destinationchannels["$destination"]}}\
Vorbis files will always be reencoded if unset. -p'Channel count: ' \
EODesc value
comeagain() { if ! [[ $value =~ $expr ]]
read \ then
-e \ echo "Invalid channel count: $value" >&2
${destinationmaxbps["$destination"]+-i${destinationmaxbps["$destination"]}}\ comeagain
-p'Higher-Than: ' \ fi
value }
if ! [[ $value =~ $expr ]] comeagain
if [ -n "${destinationchannels["$destination"]}" ] \
&& (( value != ${destinationchannels["$destination"]} ))
then then
echo "Invalid higher-than bitrate value: $value" >&2 setupRegen channels
comeagain
fi fi
} destinationchannels["$destination"]=$value
comeagain cat <<-EODesc
if [ -n "${destinationmaxbps["$destination"]}" ] \
&& (( value != ${destinationmaxbps["$destination"]} )) Sampling rate (Hertz, integer):
then Files will be resampled as needed to the specified sampling-rate.
setupRegen maxbps Shoutcast/Icecast streams require a constant sampling-rate.
Telephony systems often require a sampling-rate of 8000Hz.
EODesc
if [[ ${destinationformat["$destination"]} == opus ]]
then
cat <<-EODesc
Please note that Opus supports only the following sample-rates:
8000, 12000, 16000, 24000, and 48000 Hz. So don't set
resampling on an Opus destination to any other value or files
will be resampled twice.
EODesc
fi
comeagain() {
read \
-e \
${destinationfrequency["$destination"]+-i${destinationfrequency["$destination"]}}\
-p'Sampling-rate: ' \
value
if ! [[ $value =~ $expr ]]
then
echo "Invalid frequency value: $value" >&2
comeagain
fi
}
comeagain
if [ -n "${destinationfrequency["$destination"]}" ] \
&& (( value != ${destinationfrequency["$destination"]} ))
then
setupRegen frequency
fi
destinationfrequency["$destination"]=$value
cat <<-EODesc
Higher-Than (bitrate, integer):
Only reencode files with bitrates higher then <bitrate>kbps. This
only applies if sample-rate, channel count and of course format are
equal. If unset, only files with bitrates equal to that of the
target will be copied (actually, hardlinking will be attempted
first).
As Ogg Vorbis target quality is not defined by its bitrate, Ogg
Vorbis files will always be reencoded if unset.
EODesc
comeagain() {
read \
-e \
${destinationmaxbps["$destination"]+-i${destinationmaxbps["$destination"]}}\
-p'Higher-Than: ' \
value
if ! [[ $value =~ $expr ]]
then
echo "Invalid higher-than bitrate value: $value" >&2
comeagain
fi
}
comeagain
if [ -n "${destinationmaxbps["$destination"]}" ] \
&& (( value != ${destinationmaxbps["$destination"]} ))
then
setupRegen maxbps
fi
destinationmaxbps[$destination]="$value"
unset regen
unset expr
fi fi
destinationmaxbps[$destination]="$value"
unset regen
unset expr
} }

View File

@ -65,7 +65,7 @@ setupDestinations() {
expr='^[A-z0-9]*$' expr='^[A-z0-9]*$'
comeagain() { comeagain() {
read -p'Name: ' value read -p'Name: ' value
[ -z "$value" ] && break [ -z "$value" ] && return 1
if ! [[ $value =~ $expr ]] if ! [[ $value =~ $expr ]]
then then
echo "Invalid name $value. Please use" \ echo "Invalid name $value. Please use" \
@ -73,7 +73,7 @@ setupDestinations() {
comeagain comeagain
fi fi
} }
comeagain comeagain || break
destination="$value" destination="$value"
setupDestination setupDestination
done done

View File

@ -2,5 +2,5 @@
extractAudio() { extractAudio() {
tmpfile="${fileid}ffmpeg.wav" tmpfile="${fileid}ffmpeg.wav"
commandline=(${ionice}ffmpeg -v 0 -vn -y) commandline=(${ionice}ffmpeg -v 0 -vn -y)
commandline+=(-i "$sourcepath/$filename" "$tempdir/$tmpfile") commandline+=(-i "$sourcepath/$filename" -map a:0 "$tempdir/$tmpfile")
} }

View File

@ -92,7 +92,7 @@ master() {
if (( remaining == 0 )) if (( remaining == 0 ))
then then
sleep 0.1 sleep 0.1
continue return 0
elif (( active == 0 && ready == 0 )) elif (( active == 0 && ready == 0 ))
then then
dumpfile=tasks-$(date +%Y%m%d%H%M%S).csv dumpfile=tasks-$(date +%Y%m%d%H%M%S).csv