LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   FLAC decoding script (https://www.linuxquestions.org/questions/programming-9/flac-decoding-script-745243/)

jamesan 08-05-2009 05:19 AM

FLAC decoding script
 
Hi,

I have a library of FLAC files which I need to convert to WAVs. The FLAC files are in a folder called FLAC, with each album in a uniquely named folder. The WAV files will be in a folder called WAV, again with each album in its own folder, named the same as the FLAC album folder.

So I guess I need to know how to recursively descend into folders and decode the FLAC files into similar directory structures elsewhere.

/home/FLAC/Album1/track1.flac becomes /home/WAV/Album1/track1.wav
/home/FLAC/Album1/track2.flac becomes /home/WAV/Album1/track2.wav
/home/FLAC/Album2/track1.flac becomes /home/WAV/Album2/track1.wav

...etc

This code is currently working for a single album folder:

Code:

#!/bin/bash
LIST="$(ls /home/FLAC/)"
for file in "$LIST"; do
LIST2="$(ls /home/FLAC/$file/)"
for ffile in "$LIST2"; do
cd /home/FLAC/$file/
flac -d --output-prefix=/home/WAV/$file/ $ffile
done
done

But is fails with this error when there are two or more albums to decode:

Code:

[root@server52870 bms002]# flacdecode

flac 1.2.1, Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007  Josh Coalson
flac comes with ABSOLUTELY NO WARRANTY.  This is free software, and you are
welcome to redistribute it under certain conditions.  Type `flac' for details.

: ERROR: can't open output file /home/WAV/bms001bms002/.wav: No such file or directory

bms002:: ERROR initializing decoder
        init status = FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE

An error occurred opening the input file; it is likely that it does not exist
or is not readable.
bms001:: ERROR: can't open output file /home/WAV/bms001/home/FLAC/bms001:.wav: No such file or directory
bms001_01.flac: done
ERROR: output file /home/WAV/bms001bms001_01.wav already exists, use -f to override
bms001_02.flac: done
ERROR: output file /home/WAV/bms001bms001_02.wav already exists, use -f to override
bms001_03.flac: done
ERROR: output file /home/WAV/bms001bms001_03.wav already exists, use -f to override

bms002: ERROR while decoding metadata
        state = FLAC__STREAM_DECODER_ABORTED

I'm sure that spells out a very obvious logic error to someone... any pointers much appreciated!

vonbiber 08-05-2009 06:01 AM

you might try this (test it first, then remove the comments
and the echo lines)

assuming your flac cmd works as: flac inputfile outputfile

### cut and paste into a shell script ###
#!/bin/sh

TOP=replace_here_by_the_folder_above_both_FLAC_n_WAV
FLAC=$TOP/FLAC
WAV=$TOP/WAV

find $FLAC/* | while read f
do
cmd="echo $f | sed 's?^$FLAC?$WAV?'"
g="$(eval $cmd)"
d=${g%/*}
echo "mkdir -p $WAV/$d"
# mkdir -p $WAV/$d
if [ -d $f ]; then
continue
fi
ext=${f##*.}
if [ "$ext" == "flac" ]; then
echo "flac $f $g || exit 1"
# flac $f $g || exit 1
fi
done

#### end of script

jamesan 08-05-2009 06:32 AM

Hi vonbiber,

Thanks for the reply - can you explain what the code does? I think it's very close to what I need but currently doesn't quite do it...

Here's my script:

Code:

#!/bin/sh

TOP=/media_library
FLAC=$TOP/98
WAV=$TOP/12

find $FLAC/* | while read f
do
cmd="echo $f | sed 's?^$FLAC?$WAV?'"
g="$(eval $cmd)"
d=${g%/*}
echo "mkdir -p $WAV/$d"
# mkdir -p $WAV/$d
if [ -d $f ]; then
continue
fi
ext=${f##*.}
if [ "$ext" == "flac" ]; then
echo "flac -d $f $g || exit 1"
# flac -d $f $g || exit 1
fi
done

And here's the output:

Code:

mkdir -p /media_library/12//media_library/12
mkdir -p /media_library/12//media_library/12/bms001
mkdir -p /media_library/12//media_library/12/bms001
flac -d /media_library/98/bms001/bms001_03.flac /media_library/12/bms001/bms001_03.flac || exit 1
mkdir -p /media_library/12//media_library/12/bms001
flac -d /media_library/98/bms001/bms001_02.flac /media_library/12/bms001/bms001_02.flac || exit 1
mkdir -p /media_library/12//media_library/12/bms001
flac -d /media_library/98/bms001/bms001_01.flac /media_library/12/bms001/bms001_01.flac || exit 1
mkdir -p /media_library/12//media_library/12
mkdir -p /media_library/12//media_library/12/bms002
flac /media_library/98/bms002/bms002_01.flac /media_library/12/bms002/bms002_01.flac || exit 1
mkdir -p /media_library/12//media_library/12/bms002
flac -d /media_library/98/bms002/bms002_02.flac /media_library/12/bms002/bms002_02.flac || exit 1
mkdir -p /media_library/12//media_library/12/bms002
flac -d /media_library/98/bms002/bms002_03.flac /media_library/12/bms002/bms002_03.flac || exit 1
mkdir -p /media_library/12//media_library/12


jamesan 08-05-2009 07:02 AM

Sussed it! Probably a weird hack, but works... thanks loads for your help vonbiber. Here's what worked in the end:


Code:

#!/bin/sh

TOP=/media_library
FLAC=$TOP/flacfiles
WAV=$TOP/wavfiles

find $FLAC/* | while read f
do
cmd="echo $f | sed 's?^$FLAC?$WAV?'"
g="$(eval $cmd)"
d=${g%/*}
# echo "mkdir -p $d"
mkdir -p $d
if [ -d $f ]; then
continue
fi
ext=${f##*.}
if [ "$ext" == "flac" ]; then
BASEFLAC=`basename $f`
FLACDIR=`dirname $f`
WAVDIR=`dirname $g`
# echo "cd $FLACDIR"
cd $FLACDIR
# echo "flac -d $BASEFLAC --output-prefix=$WAVDIR/ || exit 1"
flac -d $BASEFLAC --output-prefix=$WAVDIR/
fi
done


unSpawn 08-05-2009 07:39 AM

FWIW and not that it has any bearing on your script or would apply if your .flac don't have any information, or if .wav is not just an intermediate conversion stage, but FLAC can store quite a lot of information and a flac->wav conversion won't transfer it. As in 'metaflac --export-tags.*'.

vonbiber 08-05-2009 07:45 AM

Quote:

Originally Posted by jamesan (Post 3632141)

TOP=/media_library
FLAC=$TOP/flacfiles
WAV=$TOP/wavfiles

find $FLAC/* | while read f
do
cmd="echo $f | sed 's?^$FLAC?$WAV?'"
g="$(eval $cmd)"
d=${g%/*}
# echo "mkdir -p $d"
mkdir -p $d
if [ -d $f ]; then
continue
fi
ext=${f##*.}
if [ "$ext" == "flac" ]; then
BASEFLAC=`basename $f`
FLACDIR=`dirname $f`
WAVDIR=`dirname $g`
# echo "cd $FLACDIR"
cd $FLACDIR
# echo "flac -d $BASEFLAC --output-prefix=$WAVDIR/ || exit 1"
flac -d $BASEFLAC --output-prefix=$WAVDIR/
fi
done[/CODE]

that's the reason why you must test (thru echo) before
actually doing the conversion

I'll try to explain
The idea is to store the output files in a tree similar to
the input files (except for the top directory which
for the input files is $FLAC and it exists
for the output files is $WAV and it doesn't necessarily exists

1. first we look for all files/folders/subfolders in the input
directory $FLAC
find $FLAC/* | while read f
do
...
done

2.
cmd="echo $f | sed 's?^$FLAC?$WAV?'"
g="$(eval $cmd)"

the 2 lines above help us form the target path
we can't directly do g=$(echo $f | sed 's?^$FLAC?$WAV?'")
that wouldn't work (eval replaces the variables FLAC and WAV
by their actual values before executing sed)

d=${g%/*}
this one forms the directory part of the complete path $g

so for instance, if the input file is
/media_library/flacfiles/folder0/folderA/file.avi

g is gonna be
/media_library/wavefiles/folder0/folderA/file.avi

and d: /media_library/wavefiles/folder0/folderA

mkdir -p $d
we create the directory $d if it doesn't already exist

if [ -d $f ]; then
continue
fi
if $f is a directory proceed, do nothing

ext=${f##*.}
this store the extension of the file in the variable ext
if the test below is true
if [ "$ext" == "flac" ]; then
do the conversion
...

These shell constructions are quite useful (and more efficient
than the commands 'basename', 'sed', etc.) so whenever you can use
them do so

g=${f##*/} : filename (without the directory part)
n=${g%.*} : name (without the extension)

hope this is clear enough


All times are GMT -5. The time now is 05:28 PM.