Wednesday, October 15, 2008

mp3Manager.cfc for updating ID3 tags with coldfusion

I needed to modify MP3 ID3 tags on our server with Coldfusion. To do so I downloaded three different Java mp3 libraries. One did not work at all, the other two would read the ID3 tags but not update the data.

Frustrated, I went on the prowl again for another library and I found MyID3: a Java ID3 Tag Library. You will also need to download the Jakarta Regexp and Nanoxml jars as well.

Thank you Charles M. Chen for a library that's simple, well documented and works!

Also, thanks to Ray Camden for posting "Reading MP3 ID3 tags with ColdFusion" on his Coldfusion Jedi blog. That gave me a great head start.

Here's how you might use the component...

<!--- Read the ID3 comments field --->
<cfset mp3Manager = createObject("component",'components.managers.mp3Manager') />
<cfset mp3Manager.init(mp3FilePath) />
<cfset comment = mp3Manager.getComment() />

<!--- Update the ID3 comments field --->
<cfset mp3Manager = createObject("component",'components.managers.mp3Manager') />
<cfset mp3Manager.init(mp3FilePath) />
<cfset mp3Manager.setComment(strComments) />

And here is a simple version of the CFC. I hope you find it helpful.

<cfcomponent displayname="mp3Manager" output="false">  

   <!--- ============================================== --->
   <cfset variables.fileObj = "">
   <cfset variables.filename = "">
   <cfset variables.metadata = "">
   <cfset variables.metadataset = "">
   <cfset variables.id3 = "">   

   <!--- ============================================== --->
   <cffunction name="init" access="public" returnType="mp3Manager" output="false">
      <cfargument name="filename" type="string" required="false">

      <cfif structKeyExists(arguments, "filename")>
          <cfset variables.id3 = createObject("java", "org.cmc.music.myid3.MyID3") />
          <cfset variables.metadata = createObject("java", "org.cmc.music.metadata.MusicMetadata") />
          <cfset variables.metadataset = createObject("java", "org.cmc.music.metadata.MusicMetadataSet") />
          <cfset read(filename) />
      </cfif>

        <cfreturn this>
   </cffunction>

   <!--- ============================================== --->
   <cffunction name="read" access="public" returnType="void" output="false">
      <cfargument name="filename" type="string" required="true">

      <cfif not fileExists(arguments.fileName)>
         <cfthrow message="#arguments.fileName# does not exist.">
      </cfif>

      <cfset variables.filename = arguments.filename>

      <cftry>
         <cfset variables.fileObj = createObject("java","java.io.File").init(expandPath(variables.filename)) />
         <cfset variables.id3.init() />
         <cfset variables.metadataset = variables.id3.read(variables.fileObj) />
         <cfset variables.metadata = variables.metadataset.getSimplified() />
         <cfcatch>
            <cfthrow message="Invalid MP3 file: #arguments.filename# #cfcatch.message#">
         </cfcatch>
      </cftry>
   </cffunction>

   <!--- ============================================== --->
   <cffunction name="getComment" access="public" returnType="string" output="false">
      <cfreturn trim(variables.metadata.getComment())>
   </cffunction>

   <!--- ============================================== --->
   <cffunction name="setComment" access="public" returnType="void" output="false">
      <cfargument name="argComment" type="string" required="false">
      <cfset variables.metadata.setComment(argComment) />
      <cfset variables.id3.update(variables.fileObj, variables.metadataset, variables.metadata) />
   </cffunction>

   <!--- ============================================== --->
</cfcomponent>

6 comments:

Anonymous said...

Hey, thanks for sharing this code.

I'm trying to get it up and running and I'm getting an error in read()

[cfdump var="#VARIABLES.metadataset#" label="before"]

[cfset VARIABLES.metadataset = VARIABLES.id3.read(VARIABLES.fileObj)]

[cfdump var="#VARIABLES.metadataset#" label="after"]

For some reason, VARIABLES.metadataset isn't set to anything after the call to read.

Could it be that VARIABLES.id3.read() is returning NULL?

Any idea why this might be happening?

Thanks.

Anonymous said...

Just found the problem.

In read() you expand an already expanded path:

createObject("java","java.io.File").init(expandPath(VARIABLES.filename))

Removing that ExpandPath fixes things.

Cheers.

Chris Simeone said...

Glad you found this to be helpful, Adrian!

Anonymous said...

Hey Chris, a quick question for you...

I'm trying to write tags in ISO-8859-1 encoding. I can see various encoding vars in the source of MyID3 but I can't see how I get to set it prior to writing the tags.

Any ideas?

FlexDojo said...

Sorry Adrian, I have no idea.

Did you try asking Charles Chen? He developed MyID3.

His email is: charlesmchen@gmail.com.

Unknown said...

nice work!

reading works great, but when i try to write a comment back to the file i get:
No matching Method/Function for org.cmc.music.metadata.MusicMetadata.setcomments(string) found

your code uses setComment - but the javadocs say the mehtod is called setComments (with an S) it gives the same error either way.

i've been working on this for hours but can't figure out what i'm doing wrong...any ideas?