Tux

...making Linux just a little more fun!

2-cent tip: Convert your mp3 files into ogg

Mulyadi Santosa [mulyadi.santosa at gmail.com]


Sat, 26 Jan 2008 21:54:43 +0700

First, why? Easy, because mp3 is a patented format and ogg is an open source format. So, to guarantee your peace of mind (like what Cattano said to Frank Lucas in "American Gangster" :) ), use ogg.

To do it, first I assume you have mpg123 (http://www.mpg123.de/) installed and the binary is located in searchable path (check your $PATH).

Your mp3 files probably contain spaces, so use this script:

#!/bin/bash
 
for b in *; do (  cd $b; for a in *; do mv -v "$a" $(echo $a | sed s/\
/\_/g); done ) ; done

The script assumes your working directory has subdirectories that holds the mp3 files (think of it as albums). Outer loop lists the directories and inner loop "cd" into them and rename the files inside so they don't contain spaces anymore.

Finally, the real piece of work:

#!/bin/bash
 
for b in *;
do ( cd $b;
     for a in *;
            do test=$(echo $a | cut -f1 -d\.).wav ;
            mpg123 -v -w $test "$a";
            oggenc  $test ;
            rm -fv $test ;  rm -fv "$a" ;
     done );
done

In short, the script loops over your collections. It uses mpg123 to convert your mp3s into wavs. Then, oggenc converts it as ogg. The wav is then deleted since we don't need it anymore. Why create wav 1st, you might ask? Well, i tried to pipe mpg123 directly to oggenc but somehow it didn't work (at least in my case), so that's my workaround.

regards,

Mulyadi.


Top    Back


Ben Okopnik [ben at linuxgazette.net]


Sat, 26 Jan 2008 12:07:41 -0500

On Sat, Jan 26, 2008 at 09:54:43PM +0700, Mulyadi Santosa wrote:

> First, why? Easy, because mp3 is a patented format and ogg is an open
> source format. So, to guarantee your peace of mind (like what Cattano
> said to Frank Lucas in "American Gangster" :) ), use ogg.
> 
> To do it, first I assume you have mpg123 (http://www.mpg123.de/)
> installed and the binary is located in searchable path (check your
> $PATH).
> 
> Your mp3 files probably contain spaces, so use this script:
> #!/bin/bash
> 
> for b in *; do (  cd $b; for a in *; do mv -v "$a" $(echo $a | sed s/\
> /\_/g); done ) ; done
> 

If you want to loop over filenames that contain spaces without splitting on those spaces, the easiest way is to tell Bash not to use spaces as a delimiter. This is done via the $IFS (Internal Field Separator) variable, which initially consists of a space, a tab, and a newline:

ben@Tyr:~$ printf "$IFS"|od -ta
0000000  sp  ht  nl
0000003

If you set the IFS, remember to restore it if your script is going to continue after the loop:

# Save the IFS
old=$IFS
# Set the IFS to a hard-coded newline
IFS='
'
for n in *mp3
do
	# Doesn't matter much for 'echo', but it's a good idea to enclose
	# the filename in double-quotes; otherwise, other programs may get
	# confused about those spaces.
	echo "$n"
done
# Restore the IFS
IFS=$old

Of course, if you're exiting the script at this point, then restoring the IFS isn't necessary; the current definition will go away when the current child process (the script) exits, and the definition from the parent process will come into effect.

> The script assumes your working directory has subdirectories that
> holds the mp3 files (think of it as albums). Outer loop lists the
> directories and inner loop "cd" into them and rename the files inside
> so they don't contain spaces anymore.
> 
> Finally, the real piece of work:
> #!/bin/bash
> 
> for b in *;
> do ( cd $b;
>      for a in *;
>             do test=$(echo $a | cut -f1 -d\.).wav ;
>             mpg123 -v -w $test "$a";
>             oggenc  $test ;
>             rm -fv $test ;  rm -fv "$a" ;
>      done );
> done

Since you're using Bash, you could just use the parameter substitution mechanism to modify the filenames instead of using 'cut'.

mpg123 -v -w "${a%mp3}wav" "$a";

This will remove 'mp3' from the end of the content in "$a", and replace it with 'wav'. However, you should indeed be able to pipe the output of the MP3 decoder into the input of the OGG encoder, since the latter is significantly slower than the former.

> In short, the script loops over your collections. It uses mpg123 to
> convert your mp3s into wavs. Then, oggenc converts it as ogg. The wav
> is then deleted since we don't need it anymore. Why create wav 1st,
> you might ask? Well, i tried to pipe mpg123 directly to oggenc but
> somehow it didn't work (at least in my case), so that's my workaround.

The syntax can be a little tricky.

...
for a in *mp3
do
	mpg123 -w - "$a" | oggenc - -o "${a%mp3}wav" && \
done
...

I'd also want to test the newly-created OGGs before discarding the MP3s.

for n in *ogg
do
	# Play 10 seconds of the OGG
	ogg123 -K 10 "$a"
	printf "Delete \"${a%ogg}mp3\" [Yn]?"
	read answer
	if echo $ans|grep -iq '^y'
	then
		echo "Deleting ${a%ogg}mp3"
		rm "${a%ogg}mp3"
	fi
done
-- 
* Ben Okopnik * Editor-in-Chief, Linux Gazette * http://LinuxGazette.NET *


Top    Back


Ben Okopnik [ben at linuxgazette.net]


Sat, 26 Jan 2008 12:10:45 -0500

On Sat, Jan 26, 2008 at 12:07:41PM -0500, Benjamin Okopnik wrote:

> 
> ```
> for n in *ogg
> do
> 	# Play 10 seconds of the OGG
> 	ogg123 -K 10 "$a"
> 	printf "Delete \"${a%ogg}mp3\" [Yn]?"
> 	read answer
         ^^^^^^
Whoops - that would be 'read ans', of course. Or you could change the next line to '$answer'.

> 	if echo $ans|grep -iq '^y'
> 	then
> 		echo "Deleting ${a%ogg}mp3"
> 		rm "${a%ogg}mp3"
> 	fi
> done
> '''	
-- 
* Ben Okopnik * Editor-in-Chief, Linux Gazette * http://LinuxGazette.NET *


Top    Back


Mulyadi Santosa [mulyadi.santosa at gmail.com]


Mon, 28 Jan 2008 08:19:34 +0700

Hi....

On Jan 27, 2008 12:10 AM, Ben Okopnik <ben@linuxgazette.net> wrote:

> On Sat, Jan 26, 2008 at 12:07:41PM -0500, Benjamin Okopnik wrote:
> >
> > ```
> > for n in *ogg
> > do
> >       # Play 10 seconds of the OGG
> >       ogg123 -K 10 "$a"
> >       printf "Delete \"${a%ogg}mp3\" [Yn]?"
> >       read answer
>          ^^^^^^
>
> Whoops - that would be 'read ans', of course. Or you could change the
> next line to '$answer'.

I perfectly agree with you...sorry about my stupid bash knowledge :) Willing to share seems is not enough this time :D

regards,

Mulyadi.


Top    Back


Ben Okopnik [ben at linuxgazette.net]


Sun, 27 Jan 2008 21:08:16 -0500

On Mon, Jan 28, 2008 at 08:19:34AM +0700, Mulyadi Santosa wrote:

> Hi....
> 
> On Jan 27, 2008 12:10 AM, Ben Okopnik <ben@linuxgazette.net> wrote:
> > On Sat, Jan 26, 2008 at 12:07:41PM -0500, Benjamin Okopnik wrote:
> > >
> > > ```
> > > for n in *ogg
> > > do
> > >       # Play 10 seconds of the OGG
> > >       ogg123 -K 10 "$a"
> > >       printf "Delete \"${a%ogg}mp3\" [Yn]?"
> > >       read answer
> >          ^^^^^^
> >
> > Whoops - that would be 'read ans', of course. Or you could change the
> > next line to '$answer'.
> 
> I perfectly agree with you...sorry about my stupid bash knowledge :)
> Willing to share seems is not enough this time :D

Mulyadi, if you hadn't shared this tip, you wouldn't have had this opportunity to improve your Bash knowledge. By doing so, you've also given other people a) ideas about how to play with shell scripting and b) a chance to learn a few tricks. This is precisely why tips need to go to TAG rather than being directly submitted like articles: The Answer Gang is where tips get sharpened, polished, and vetted for errors.

You have nothing to be sorry about, and no reason to feel stupid; everything worked exactly as it was supposed to. "Stupid" would be beating up on yourself when you've done everything right and achieved a good result. :)

-- 
* Ben Okopnik * Editor-in-Chief, Linux Gazette * http://LinuxGazette.NET *


Top    Back