sure, the script in its current form is included below. the code below is very immature, it is not feature complete.
right now i have it working for the following operations: --mp32ogg --ogg2mp3 --m4a2mp3 --m4a2ogg --mp3reencode --oggreencode --cleanup
to execute the script:
Code: Select all
icaff /full/path/to/working/directory --conversiontype
i call it "icaff" for "icaff converts audio file formats". i wanted to call it "glissando" but that name is already taken by some musical notation OCR software on sourceforge.
the point of it is to preserve meta data while doing a batch conversion.
i'd like to put a front end on it eventually, just as a fun project... but im not sure what to write it in... php? python? gtk#?
suggestions encouraged, im no veteran!
Code: Select all
#!/bin/bash
################################################################################
# Project Name: icaff
# License: GPL (http://www.google.com/search?q=GPL)
# Author: Jim Harney
# Version: 0.0.3
# Started: 7/18/2005
# Language: BASH Script
# Platform: GNU/Linux
# Dependencies: id3lib, mpg321, vorbis-tools, lame
# Description of the Problem:
# There are many audio file formats. Some of these support meta data.
# Often a collection of audio files will consist of several different formats
# with such recognizable extensions as .mp3, .ogg, .m4a, .wma.
# Different users favor different formats. Users tend to like meta data.
# This project aims to allow a user to convert a directory of audio files
# from one format to another while preserving meta data wherever possible.
# Technical Problems:
# This project depends on other programs such as id3lib, mpg321, vorbis-tools,
# and lame. One problem is to orchestrate the input and output of these programs.
# Some other problems are: handling input, encoder configuration management,
# handling differnt character encoding.
# Feature List:
# * batch file format conversions: mp3->ogg, ogg->mp3, m4a->mp3, m4a->ogg,
# wma->mp3, wma->ogg, flac->mp3, flac->ogg
# * reencodes mp3 and ogg formats
################################################################################
################################################################################
# Known Issues/Bugs:
# * cannot be executed with a relative path (must be absolute)
# * when converting or reencoding, the comment meta tag is lost
################################################################################
################################################################################
# TODO:
# * allow script to be executed with relative path input
# * improve output for -h/--h and invalid paramaters
# * m4a conversions
# * wma conversions
# * flac conversions
################################################################################
################################################################################
# config
################################################################################
# these will be passed to lame during mp3 encoding
# meta data related args should NOT be used here
#LAME_Args='--preset medium' #The resulting bitrate should be in the 150-180kbps range, according to music complexity.
#LAME_Args='--preset standard' #The resulting bitrate should be in the 170-210kbps range, according to music complexity.
#LAME_Args='--preset extreme' #The resulting bitrate should be in the 200-240kbps range, according to music complexity.
#LAME_Args='--vbr-old -V 4 -b 112 -B 192' #vbr quality=4, min bitrate=112, max bitrate=192
LAME_Args='--vbr-old -V 4 -b 96 -B 192' #vbr quality=4, min bitrate=96, max bitrate=192
#LAME_Args='-a -m m' #voice
# these will be passed to oggenc during ogg encoding
# meta data related args should NOT be used here
OGGENC_Args='-q 5' #vbr quality=5
# files will be temporarily renamed to remove white space
Space_Placeholder='___'
# when re-encoding an mp3, the file is renamed and the newly encoded file
# takes on the original file name. the renamed file is only deleted if the
# encoding is successful.
# you can customize the renaming below, the filename will be prefixed.
Mp3_ReencodingNamingPrefix='Mp3_ReencodingNamingPrefix_'
# this script depends on the following programs
# paths below are from gentoo but seem like logical defaults
ID3INFO=/usr/bin/id3info
MPG321=/usr/bin/mpg321
OGGENC=/usr/bin/oggenc
OGGINFO=/usr/bin/ogginfo
OGGDEC=/usr/bin/oggdec
LAME=/usr/bin/lame
FAAD=/usr/bin/faad
################################################################################
# ensure arg 1
################################################################################
case $1 in
'--help' | '-h')
echo 'Usage: '$0' DIR ACTION'
echo -e '\tDIR must use an absolute path'
echo -e '\tACTION can be:'
echo -e '\t\t--mp32ogg'
echo -e '\t\t--ogg2mp3'
echo -e '\t\t--m4a2mp3'
echo -e '\t\t--m4a2ogg'
echo -e '\t\t--mp3reencode'
echo -e '\t\t--oggreencode'
echo -e '\t\t--cleanup (removes .wav files, renames files to initial name)'
# echo 'Requires:'
# echo -e '\toggenc (http://directory.fsf.org/audio/ogg/OggEnc.html)'
# echo -e '\tlame (http://lame.sourceforge.net/)'
# echo -e '\tfaad (http://www.audiocoding.com/)'
# echo -e '\tid3lib (http://id3lib.sourceforge.net/)'
# echo -e '\tmpg321 (http://sourceforge.net/projects/mpg321/)'
exit 0
;;
*[0-9a-zA-Z/_-]*)
Dir=$1
echo '*** Dir is: '$Dir
;;
* )
echo 'ERROR: bad args!'
exit 0
;;
esac
################################################################################
# ensure arg 2
################################################################################
case $2 in
'--mp32ogg' | '--ogg2mp3' | '--m4a2mp3' | '--m4a2ogg' | '--wma2mp3' | '--wma2ogg' | '--mp3reencode' | '--oggreencode' | '--cleanup')
Action=$2
echo '*** Action is: '$Action
;;
* )
echo 'ERROR: bad args!'
exit 0
;;
esac
################################################################################
# function definitions
################################################################################
function clearMetaVars()
{
Title=''
Artist=''
Album=''
Year=''
Track=''
Genre=''
Comm=''
}
function populateMetaVarsFromMP3()
{
clearMetaVars
echo '*** Reading .mp3 meta data...'
Title=`$ID3INFO $1 | grep --max-count=1 '=== TIT' | grep -Eo '\): .*' | grep -Eo '[^\)].*' | grep -Eo '[^:].*' | grep -Eo '[^ ].*'`; echo 'Title: '$Title
Artist=`$ID3INFO $1 | grep --max-count=1 '=== TPE' | grep -Eo '\): .*' | grep -Eo '[^\)].*' | grep -Eo '[^:].*' | grep -Eo '[^ ].*'`; echo 'Artist: '$Artist
Album=`$ID3INFO $1 | grep --max-count=1 '=== TALB' | grep -Eo '\): .*' | grep -Eo '[^\)].*' | grep -Eo '[^:].*' | grep -Eo '[^ ].*'`; echo 'Album: '$Album
Year=`$ID3INFO $1 | grep --max-count=1 '=== TYER' | grep -Eo '\): .*' | grep -Eo '[^\)].*' | grep -Eo '[^:].*' | grep -Eo '[^ ].*'`; echo 'Year: '$Year
Track=`$ID3INFO $1 | grep --max-count=1 '=== TRCK' | grep -Eo '\): .*' | grep -Eo '[^\)].*' | grep -Eo '[^:].*' | grep -Eo '[^ ].*'`; echo 'Track: '$Track
Genre=`$ID3INFO $1 | grep --max-count=1 '=== TCON' | grep -Eo '\): .*' | grep -Eo '[^\)].*' | grep -Eo '[^:].*' | grep -Eo '[^ ].*' | grep -Eo '[^\(].*[^\)]'`; echo 'Genre: '$Genre
# Comm=`$ID3INFO $1 | grep --max-count=1 '=== COMM' | grep -Eo '\): .*' | grep -Eo '[^\)].*' | grep -Eo '[^:].*' | grep -Eo '[^ ].*'`; echo 'Comment: '$Comm
}
function populateMetaVarsFromOGG()
{
clearMetaVars
echo '*** Reading .ogg meta data...'
Title=`$OGGINFO $1 | grep --max-count=1 'TITLE=' | grep -Eo 'E=.*' | grep -Eo '[^E].*' | grep -Eo '[^=].*'`; echo 'Title: '$Title
Artist=`$OGGINFO $1 | grep --max-count=1 'ARTIST=' | grep -Eo 'T=.*' | grep -Eo '[^T].*' | grep -Eo '[^=].*'`; echo 'Artist: '$Artist
Album=`$OGGINFO $1 | grep --max-count=1 'ALBUM=' | grep -Eo 'M=.*' | grep -Eo '[^M].*' | grep -Eo '[^=].*'`; echo 'Album: '$Album
Year=`$OGGINFO $1 | grep --max-count=1 'DATE=' | grep -Eo 'E=.*' | grep -Eo '[^E].*' | grep -Eo '[^=].*'`; echo 'Year: '$Year
Track=`$OGGINFO $1 | grep --max-count=1 'TRACKNUMBER=' | grep -Eo 'R=.*' | grep -Eo '[^R].*' | grep -Eo '[^=].*'`; echo 'Track: '$Track
Genre=`$OGGINFO $1 | grep --max-count=1 'GENRE=' | grep -Eo 'E=.*' | grep -Eo '[^E].*' | grep -Eo '[^=].*'`; echo 'Genre: '$Genre
# Comm=`$OGGINFO $1 | grep 'COMMENT=' | grep -Eo 'T=.*' | grep -Eo '[^T].*' | grep -Eo '[^=].*'`; echo 'Comment: '$Comm
}
function populateMetaVarsFromM4A()
{
clearMetaVars
echo '*** Reading .m4a meta data...'
Title=`$FAAD -i $1 2>&1 | grep --max-count=1 'title:' | grep -Eo '[:].*' | grep -Eo '[^: ].*'`; echo 'Title: '$Title
Artist=`$FAAD -i $1 2>&1 | grep --max-count=1 'artist:' | grep -Eo '[:].*' | grep -Eo '[^: ].*'`; echo 'Artist: '$Artist
Album=`$FAAD -i $1 2>&1 | grep --max-count=1 'album:' | grep -Eo '[:].*' | grep -Eo '[^: ].*'`; echo 'Album: '$Album
Year=`$FAAD -i $1 2>&1 | grep --max-count=1 'date:' | grep -Eo '[:].*' | grep -Eo '[^: ].*'`; echo 'Year: '$Year
Track=`$FAAD -i $1 2>&1 | grep --max-count=1 'track:' | grep -Eo '[:].*' | grep -Eo '[^: ].*'`; echo 'Track: '$Track
Genre=`$FAAD -i $1 2>&1 | grep --max-count=1 'genre:' | grep -Eo '[:].*' | grep -Eo '[^: ].*'`; echo 'Genre: '$Genre
# Comm=`$OGGINFO $1 | grep 'COMMENT=' | grep -Eo 'T=.*' | grep -Eo '[^T].*' | grep -Eo '[^=].*'`; echo 'Comment: '$Comm
}
function deleteWAV()
{
echo '*** Deleting .wav files...'
rm -Rf *.wav
}
function renameFilesToInitialName()
{
echo '*** Renaming files to initial file name...'
# rename mp3 files, add spaces
echo '*** Renaming mp3...'
for i in *.mp3
do
File=`echo $i | sed -e "s/$Space_Placeholder/\\ /g"`
mv "$i" "$File"
done
# rename ogg files, add spaces
echo '*** Renaming ogg...'
for i in *.ogg
do
File=`echo $i | sed -e "s/$Space_Placeholder/\\ /g"`
mv "$i" "$File"
done
# rename m4a files, add spaces
echo '*** Renaming m4a...'
for i in *.m4a
do
File=`echo $i | sed -e "s/$Space_Placeholder/\\ /g"`
mv "$i" "$File"
done
}
################################################################################
# go to the working directory
################################################################################
cd "$Dir"
################################################################################
# action switch
################################################################################
case $Action in
################################################################################
# mp3 ---> ogg
################################################################################
'--mp32ogg')
echo '*** Converting mp3 to ogg...'
# rename files, remove spaces
for i in *.mp3
do
File_NoSpace=`echo $i | sed -e "s/ /$Space_Placeholder/g"`
mv "$i" "$File_NoSpace"
done
# process each file
for i in *.mp3
do
echo ''
File_NoSpace_NoExt=`echo $i | sed -e 's/.mp3//g'`
echo 'File: '$i
# storing the output of an id3info call would be more efficient
# but i lose my line breaks that way. i need the line breaks
# for parsing so ill have to settle for calling id3info for each field. (for now)
# Info=`id3info $i`
populateMetaVarsFromMP3 $i
# for quiet -q
$MPG321 $i -w $File_NoSpace_NoExt'.wav'
# for quiet -Q
$OGGENC $OGGENC_Args $File_NoSpace_NoExt'.wav' -t "$Title" -a "$Artist" -l "$Album" -d "$Year" -N "$Track" -G "$Genre"
# no one ever wants these around
rm -Rf $File_NoSpace_NoExt'.wav'
done
;;
################################################################################
# ogg ---> mp3
################################################################################
'--ogg2mp3')
echo '*** Converting ogg to mp3...'
# rename files, remove spaces
for i in *.ogg
do
File_NoSpace=`echo $i | sed -e "s/ /$Space_Placeholder/g"`
mv "$i" "$File_NoSpace"
done
# process each file
for i in *.ogg
do
echo ''
File_NoSpace_NoExt=`echo $i | sed -e 's/.ogg//g'`
echo 'File: '$i
populateMetaVarsFromOGG $i
# for quiet -q
$OGGDEC -o $File_NoSpace_NoExt'.wav' $i
# for quiet --quiet
$LAME $LAME_Args --tt "$Title" --ta "$Artist" --tl "$Album" --ty "$Year" --tn "$Track" --tg "$Genre" $File_NoSpace_NoExt'.wav' $File_NoSpace_NoExt'.mp3'
# no one ever wants these around
rm -Rf $File_NoSpace_NoExt'.wav'
done
;;
################################################################################
# m4a ---> mp3
################################################################################
'--m4a2mp3')
echo '*** Converting m4a to mp3...'
# rename files, remove spaces
for i in *.m4a
do
File_NoSpace=`echo $i | sed -e "s/ /$Space_Placeholder/g"`
mv "$i" "$File_NoSpace"
done
# process each file
for i in *.m4a
do
echo ''
File_NoSpace_NoExt=`echo $i | sed -e 's/.m4a//g'`
echo 'File: '$i
# echo 'File (no sp/ext): '$File_NoSpace_NoExt
populateMetaVarsFromM4A $i
# for quiet -q
$FAAD $i
# for quiet --quiet
#$LAME $LAME_Args --tt "$Title" --ta "$Artist" --tl "$Album" --ty "$Year" --tn "$Track" --tg "$Genre" $File_NoSpace_NoExt'.wav' $File_NoSpace_NoExt'.mp3'
# problems when writing the genre tag
$LAME $LAME_Args --tt "$Title" --ta "$Artist" --tl "$Album" --ty "$Year" --tn "$Track" $File_NoSpace_NoExt'.wav' $File_NoSpace_NoExt'.mp3'
# no one ever wants these around
rm -Rf $File_NoSpace_NoExt'.wav'
done
;;
################################################################################
# m4a ---> ogg
################################################################################
'--m4a2ogg')
echo '*** Converting m4a to ogg...'
# rename files, remove spaces
for i in *.m4a
do
File_NoSpace=`echo $i | sed -e "s/ /$Space_Placeholder/g"`
mv "$i" "$File_NoSpace"
done
# process each file
for i in *.m4a
do
echo ''
File_NoSpace_NoExt=`echo $i | sed -e 's/.m4a//g'`
echo 'File: '$i
# echo 'File (no sp/ext): '$File_NoSpace_NoExt
populateMetaVarsFromM4A $i
# for quiet -q
$FAAD $i
# for quiet -Q
$OGGENC $OGGENC_Args $File_NoSpace_NoExt'.wav' -t "$Title" -a "$Artist" -l "$Album" -d "$Year" -N "$Track" -G "$Genre"
# no one ever wants these around
rm -Rf $File_NoSpace_NoExt'.wav'
done
;;
################################################################################
# wma ---> mp3
################################################################################
'--wma2mp3')
echo '*** Converting wma to mp3...'
;;
################################################################################
# wma ---> ogg
################################################################################
'--wma2ogg')
echo '*** Converting wma to ogg...'
;;
################################################################################
# mp3 reencode
################################################################################
'--mp3reencode')
echo '*** Re-encoding mp3...'
# rename files, remove spaces
for i in *.mp3
do
File_NoSpace=`echo $i | sed -e "s/ /$Space_Placeholder/g"`
mv "$i" "$File_NoSpace"
done
# process each file
for i in *.mp3
do
populateMetaVarsFromMP3 $i
mv $i $Mp3_ReencodingNamingPrefix$i
$LAME $LAME_Args --tt "$Title" --ta "$Artist" --tl "$Album" --ty "$Year" --tn "$Track" --tg "$Genre" $Mp3_ReencodingNamingPrefix$i $i && rm $Mp3_ReencodingNamingPrefix$i
done
;;
################################################################################
# ogg reencode
################################################################################
'--oggreencode')
echo '*** Re-encoding ogg...'
# rename files, remove spaces
for i in *.ogg
do
File_NoSpace=`echo $i | sed -e "s/ /$Space_Placeholder/g"`
mv "$i" "$File_NoSpace"
done
# process each file
for i in *.ogg
do
echo ''
File_NoSpace_NoExt=`echo $i | sed -e 's/.ogg//g'`
echo 'File: '$i
# echo 'File (no sp/ext): '$File_NoSpace_NoExt
populateMetaVarsFromOGG $i
# for quiet -q
# -o $File_NoSpace_NoExt'.wav'
$OGGDEC -o $File_NoSpace_NoExt'.wav' $i
# for quiet -Q
$OGGENC $OGGENC_Args $File_NoSpace_NoExt'.wav' -t "$Title" -a "$Artist" -l "$Album" -d "$Year" -N "$Track" -G "$Genre"
# no one ever wants these around
rm -Rf $File_NoSpace_NoExt'.wav'
done
;;
################################################################################
# cleanup
################################################################################
'--cleanup')
echo '*** Cleaning up...'
deleteWAV
;;
esac
renameFilesToInitialName
echo ''
echo '*** All done!'
echo ''
# EOF