systems_glitch

Challenge: Rename mp3 Songs via ID3 Metadata

8 posts in this topic

I recently noticed that a section of my mp3 library had truncated DOS-style 8.3 filenames (example: songna~1.mp3) due to transport on a flash drive that had been formatted in FAT 16 (aside: why do manufacturers send them out like that?). The mp3s still have correct ID3 metadata though, so I can extract the actual name of the song from that. I thought it would make a neat programming challenge, so here it is:

Using ID3 metadata and the programming language of your choice, write an application that renames a file, specified as a command line arg, using the file's ID3 information.

0

Share this post


Link to post
Share on other sites

Here's my solution, in Python:

###############################################################################
# mp3 Filename Fixer
#
# Use the ID3 tag of an mp3 file to rename all of the files in a specified
# directory.
#
# The ID3 library used automatically chooses the appropriate version of ID3.
# You'll need a copy of Ned Batchelder's id3reader:
#
# http://nedbatchelder.com/code/modules/id3reader.html
#
# Syntax: convert.py path/to/files/
#
# @author systems_glitch, systems.glitch@gmail.com
# @version 26.04.2010
###############################################################################

import os, sys, id3reader

path = sys.argv[1]

###############################################################################
# getID3Name()
#
# Return the formatted ID3 filename based on the old file's ID3 metadata.
#
# @param oldName string representation of the path to the old file
# @returns new file name based on the ID3 tag
###############################################################################
def getID3Name(oldName):
newName = ""

id3r = id3reader.Reader(oldName)
newName = str(id3r.getValue('track')).zfill(2) + " - " + id3r.getValue('title') + ".mp3"

return newName

try:
for name in os.listdir(path):
if name.lower().endswith(".mp3"):
print "Renaming " + name
os.rename(path + name, path + getID3Name(path + name))

except OSError, message:
print "Error writing new file name!"

Mine renames all of the files in a supplied directory as I found that more convenient.

Edited by systems_glitch
0

Share this post


Link to post
Share on other sites

Here's my solution, in Python:

###############################################################################
# mp3 Filename Fixer
#
# Use the ID3 tag of an mp3 file to rename all of the files in a specified
# directory.
#
# The ID3 library used automatically chooses the appropriate version of ID3.
# You'll need a copy of Ned Batchelder's id3reader:
#
# http://nedbatchelder.com/code/modules/id3reader.html
#
# Syntax: convert.py path/to/files/
#
# @author systems_glitch, systems.glitch@gmail.com
# @version 26.04.2010
###############################################################################

import os, sys, id3reader

path = sys.argv[1]

###############################################################################
# getID3Name()
#
# Return the formatted ID3 filename based on the old file's ID3 metadata.
#
# @param oldName string representation of the path to the old file
# @returns new file name based on the ID3 tag
###############################################################################
def getID3Name(oldName):
newName = ""

id3r = id3reader.Reader(oldName)
newName = str(id3r.getValue('track')).zfill(2) + " - " + id3r.getValue('title') + ".mp3"

return newName

try:
for name in os.listdir(path):
if name.lower().endswith(".mp3"):
print "Renaming " + name
os.rename(path + name, path + getID3Name(path + name))

except OSError, message:
print "Error writing new file name!"

Mine renames all of the files in a supplied directory as I found that more convenient.

if you don't want to re-invent the wheel take a look to http://www.mp3tag.de

0

Share this post


Link to post
Share on other sites
if you don't want to re-invent the wheel take a look to http://www.mp3tag.de

The project was intended more as a fun exercise than something entirely practical...besides, I run Linux!

0

Share this post


Link to post
Share on other sites
if you don't want to re-invent the wheel take a look to http://www.mp3tag.de

The project was intended more as a fun exercise than something entirely practical...besides, I run Linux!

I think its an excellent exercise. File IO, string extraction, manipulation, and rewrite functions I see off the top of my head. These things I DO need practice with. You'll have to give me a few of weeks though.. I'm in the process of moving and need a computer table. The spirit is willing, but the flesh is unfunded.

0

Share this post


Link to post
Share on other sites
if you don't want to re-invent the wheel take a look to http://www.mp3tag.de

The project was intended more as a fun exercise than something entirely practical...besides, I run Linux!

sorry, i work on windows every day so i totally forgot that many people don't use it. I've never cared about digging in mp3, i'm a curios one so i'll give it a try...

0

Share this post


Link to post
Share on other sites

I'll have a go, but I haven't programmed in Ruby for a while so it might be a bit ugly. Comments and criticisms are welcomed. Haven't been here in a while, but what with the semester rolling to an end in a couple days I hope to be back in the community a lot more.

#!/usr/bin/env ruby
##
# This program takes an mp3 file from the command line. It then parses the
# mp3's ID3 tags to rename the file to the_songs_name.mp3. Incedentally
# I went somewhat overboard on the ID3 class so it can be used for alot
# more than just this application as it should read all ID3v1 tags from
# a file.
#
# Author:: n3xg3n (mailto:me@n3xg3n.org)
# License:: Public Domain
# Date:: 2010.05.07
##

##
# This class accepts 1 argument in its constructor, the filename of an mp3.
# It will read in the file to a byte array. It will then parse the file
# to make sure that the file has ID3v1 tags. Once it has ascertained that
# the file has ID3 tags, it will read the tags in from the end of the file.
# Simple ID3 Spec: http://en.wikipedia.org/wiki/ID3
##
class ID3
attr_reader :title, :artist, :album, :year, :comment, :genre

def initialize(filename)
begin
# Read in the file as a byte stream
file = File.open(filename, "rb")
file.seek(-128, IO::SEEK_END)
bytes = file.read

@tag = bytes[-128,3]

@title = bytes[-125, 30].strip # -128 + 3
@artist = bytes[-95, 30].strip # -128 + 33
@album = bytes[-65, 30].strip # -128 + 63
@year = bytes[-35, 4].strip # -128 + 93
@comment = bytes[-31, 30].strip # -128 + 97
@genre = bytes[-1, 1].strip # -128 + 127
rescue => err
raise err
ensure
file.close
end
end

def has_id3?
@tag == "TAG"
end
end

# Make sure they pass an argument and if not, print usage and exit.
if ARGV.empty?
puts "Usage:"
puts "#{$0} mp3_file_to_rename.mp3"
exit
end

# For convenience, use filename for the passed filename.
filename = ARGV[0]

# Make sure the file exists.
if not File.file?(filename)
puts "Not a File."
exit
end

# Read in the file to read the ID3 tags. Get the name and change the
# spaces to undersocres. add a '.mp3' suffix.
id3 = ID3.new(filename)

if not id3.has_id3?
puts "ID3 Tags Not Found."
exit
end

if id3.title.eql?("")
puts "ID3 Title Tag Empty."
exit
end

new_filename = id3.title.gsub(" ", "_") + ".mp3"

# Rename the file
File.rename(filename, new_filename)

0

Share this post


Link to post
Share on other sites

In Perl


#!perl -w
use MP3::Info;

opendir(DIR, ".");
@files = grep(/\.mp3$/,readdir(DIR));
closedir(DIR);

foreach $file (@files) {
$tag = get_mp3tag($file) or next;
$title = $tag->{TITLE};
system("rename $file \"$title\.mp3\"");
}

0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now