Wednesday, May 13, 2009

FLAC To .ogg Vorbis

Funny how things go full circle sometimes. I initially worked on converting all of my music CDs to Vorbis files, a tedious and rather boring adventure in itself. I was reminded during a conversation on slashdot that it might be wiser to convert to FLAC first and then I could transcode into lesser quality codecs when needed. I thought it was a reasonable idea—too bad I had all my music in Vorbis format at the time! There's no way of going up in quality...

Time went by. I started another media-shift project, this time CD to FLAC, as I should have done in the first place. Now I actually have items in that collection that I need to transfer down to Vorbis! Ironic... such is life.

Enter our friend oggenc. Simple & effective, yet how to do entire directories in one shot? Fret not, there is nothing to it:

cd /dir/with/flacs
oggenc -q6 *.flac

I'm transcoding some files now that don't appear to have any tag info, so I'm not sure that transfers, but otherwise it is working swimmingly.

Here's a perl script option that might be more useful, but I haven't tried it so your mileage may vary:

# Copyright (c) 2004 - Jason L. Buberel - jason@xxxxxxxxxxx
# Licensed under the GNU GPL.
# Modified by Dax Kelson to run on a native UNIX/Linux box.

use Getopt::Long;
use File::stat;

$sourceDirPrefix = "/export/media/music/flacs";
$destDirPrefix = "/export/media/music/oggs";
$quality = 5;
GetOptions ( "source:s" => \$sourceDirPrefix,
"dest:s" => \$destDirPrefix,
"quality:i" => \$quality,
"force" => \$force );

# Commands
$oggCommand = "oggenc";
$flacCommand = "flac";

@dirs = `cd "$sourceDirPrefix" && find . -type d -print`;
@files = `cd "$sourceDirPrefix" && find . -type f -name "*.flac" -print`;

# Check to see if our find command found anything to convert.
if ( scalar @files == 0 ) {
die "Found no .flac files to convert!";

# recreate the directory hierarchy
foreach $dir (@dirs) {
$dir =~ s/\n$//;
$dir =~ s/^\.\///;

# check to see if the destination dir already exists
if ( !(stat ("$destDirPrefix/$dir")) ) {
# stat failed so create the directory
print "Creating output dir:\n $destDirPrefix/$dir\n";
$dir =~ s/\`/\'/g;
$result = `cd "$destDirPrefix" && mkdir -p "$dir"`;


# now process the actual sound files.
foreach $file (@files) {
$file =~ s/\n$//;
$file =~ s/^\.\///;

# figure out what the destination file would be...
$destinationFile = $file;
$destinationFile =~ s/\.flac*/\.ogg/;

# now stat the destinationFile, and see if it's date is more recent
# than that of the original file. If so, we re-encode.
# we also re-encode if the user supplied --force
$srcInfo = stat ("$sourceDirPrefix/$file");
$srcModTime = $srcInfo->mtime;
$destInfo = stat ("$destDirPrefix/$destinationFile");
if ( $destInfo ) {
$destModTime = $destInfo->mtime;
print "Skipping current file: $destDirPrefix/$destinationFile\n";
# if the destination file does not exist, or the user specified force,
# or the srcfile is more recent then the dest file, we encode.
if ( !$destInfo || $force || ( $srcModTime > $destModTime) ) {
$file =~ s/\`/\'/g;
$inFile = "$sourceDirPrefix/$file";
$outFile = "$destDirPrefix/$destinationFile";
$inFile =~ s/\0//g; $outFile =~ s/\0//g;
$result = `$oggCommand -q $quality -o "$outFile" "$inFile"`;


No comments: