View previous topic :: View next topic |
Author |
Message |
geki Advocate
Joined: 13 May 2004 Posts: 2387 Location: Germania
|
Posted: Sat Mar 16, 2024 6:00 pm Post subject: Merge part'ed mp3s or how to loop files, process with ffmpeg |
|
|
I bought an album in mp3 format on Amazon and I just wanted to create a little script to merge the titles into single mp3s as these titles are splitted into parts like this:
Quote: | '20 - Caruso muntert alle auf - Teil 1.mp3'
'21 - Caruso muntert alle auf - Teil 2.mp3'
'22 - Caruso muntert alle auf - Teil 3.mp3' | Now then, easily done with ffmpeg's concat demuxer, one may think. But stop, if you want to do it the right way, mind the gaps These gaps most of you may already know, I guess. Just in case for the curious I post an example here- to somewhat properly loop over files and
- to manage own stdin for the loop
- to keep tools like ffmpeg or ssh working without special stdin handling
- to allow unsafe filenames processed by ffmpeg's concat demuxer allow whitespace characters
Yes, you can tell ffmpeg or ssh to ignore stdin, but that is just a bad workaround. Better do not use stdin for your loops in the first place. In the end- use the zero (null) record delimiter to work wth most special characters allowed in filenames
- use own file descriptor to pipe input through loop to keep stdin freely usable for the tools like ffmpeg or ssh
and be happy
/usr/local/bin/mergemp3: | #!/bin/bash
usage()
{
local exe="$(basename "${0}")"
echo "Usage: ${exe} '<delimiter string>' '<awk field(s) to merge>' <path to mp3 files>"
echo
echo "For example with filenames like:"
echo
echo -e "\tAlbum/22 - Caruso muntert alle auf - Teil 3.mp3"
echo
echo "You run this: ${exe} ' - ' '\$2' Album/"
exit 1
}
[ ${#} -ne 3 ] && usage
[ ! -d "${3}" ] && usage
delimiter="${1}"
awk_fields="${2}"
path="$(realpath "${3}")"
mkdir -p "${path}-merged"
pushd "${path}" >/dev/null
# read unique titles from fd 5
# keep stdin/out/err intact for programs like ffmpeg, ssh, etc
while IFS= read -u 5 -d $'\0' -r title
do
echo "title: ${title}"
rm -f "${path}-merged/${title}".{mp3,txt}
# read parts of title from fd 6
# keep stdin/out/err intact for programs like ffmpeg, ssh, etc
while IFS= read -u 6 -d $'\0' -r part
do
part="$(printf "%q" "${part}")"
echo "file ${part}" >> "${title}".txt
done 6< <(ls --zero -1 *"${title}"*.mp3 | \
sort --zero-terminated -u)
# close fd 6
exec 6<&-
# allow whitespace characters in filenames with '-safe 0'
ffmpeg -loglevel error -f concat -safe 0 \
-i "${title}".txt -c copy \
"${path}-merged/${title}".mp3
r=${?}; if [ ${r} -ne 0 ]
then
cat "${title}".txt
rm -f "${title}".txt
exit ${r}
fi
mv "${title}".txt "${path}-merged/${title}".txt
echo "merged: ${path}-merged/${title}.mp3"
done 5< <(ls --zero -1 | \
gawk -F "${delimiter}" 'BEGIN { RS="\0" ; ORS="\0" } ; {print '${awk_fields}'}' | \
sort --zero-terminated -u)
# close fd 5
exec 5<&-
popd >/dev/null
unset r delimiter awk_fields path title part |
_________________ hear hear |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|