Create a Graphic EQ using SoundKeys and Maya

You can create this graphic equalizer with Trapcode Soundkeys and Maya. Use my Python script, below, to automatically import keyframe data and create the eq.

Trapcode Soundkeys, an Adobe After Effects plugin, breaks audio into into about 27 frequency blocks, “ranges”, and allows you to drive animation, set keyframes, or export keyframes. To export keys, copy the keyframes from the After Effects timeline, then paste into a text editor to create your data.txt files. Each frequency range should have it’s own text file, named sequentially. Use a code editor like BB Edit or Text Wrangler, as these apps will save your .txt files with UNIX line returns, which are necessary to make my Python script work properly.

Place all the data files in a directory, by themselves, and use the Python script below to automatically build the EQ in Maya.

[py collapse=”true”]
## make a graphic equalizer, based on keyframe data from After Effects and Sound Keys.
import os
import maya.cmds as mc
## add path to keyframe data files – just the source directory that contains them.
theAttribute = ‘data’
count = 0
theCubes = []
for subdir, dirs, files in os.walk(rootdir):
dataFiles = [each for each in files if each.endswith(‘.txt’)]
for thisFile in dataFiles:
## create a cube for each data file, and distibute them across the X axis
cube = = True)
mc.setAttr((cubeName + ‘.translateY’), .5);
mc.makeIdentity(apply=True, t =True, r=True, s=True, n= 0)
mc.move( count -(len(dataFiles)/2), 0, 0)
count +=1
count = 0
for subdir, dirs, files in os.walk(rootdir):
dataFiles = [each for each in files if each.endswith(‘.txt’)]
for thisFile, o in zip(dataFiles, theCubes):
## prepare each cube for animation by ading an attibute to accept the keys, and creating an expression
theName = theCubes[count]
mc.addAttr( theName, shortName=’data’, longName=’data’, defaultValue=1.0)
mc.setAttr ( (theName + ‘.data’), e=True, keyable=True)
mc.expression(o=theName, s = (theName + ‘.scaleY =’ + theName + ‘.data / 4’), ae = True, uc = all)
## make shader for each cube
myBlinn = mc.shadingNode(‘blinn’, asShader=True, name = ("myBlinn" + str(count)))
myShader = mc.sets(renderable=True, noSurfaceShader=True, empty=True, name = (‘myBlinn’ + str(count) + ‘SG’))
mc.connectAttr( (myBlinn + ".outColor"), (myShader + ".surfaceShader"), f=True)
mc.setAttr((myBlinn + ".color"), 0.1, 0.1, 0.1, type =’double3′ )
mySetRange = mc.shadingNode(‘setRange’, asUtility=True)
mySetRange2 = mc.shadingNode(‘setRange’, asUtility=True)
mc.setAttr((mySetRange + ".minX"),230)
mc.setAttr((mySetRange + ".maxX") ,240)
mc.setAttr((mySetRange + ".oldMaxX") ,25)
mc.setAttr((mySetRange2 + ".maxX") ,3)
mc.setAttr((mySetRange2 + ".minX") ,.1)
mc.setAttr((mySetRange2 + ".oldMaxX") ,25)
myRamp = mc.shadingNode(‘ramp’, asTexture=True)
my2dPlace = mc.shadingNode(‘place2dTexture’, asUtility=True)
mc.connectAttr((my2dPlace + ".outUV"), (myRamp + ".uv"))
mc.connectAttr((my2dPlace + ".outUvFilterSize"), (myRamp + ".uvFilterSize"))
mc.setAttr((myRamp + ".colorEntryList[2].color"), 0, 0, 0 , type = ‘double3’)
mc.removeMultiInstance((myRamp + ".colorEntryList[0]"), b=True )
mc.removeMultiInstance(myRamp + ".colorEntryList[1]", b=True )
mc.connectAttr( (theName + ".scaleY"), (mySetRange + ".valueX"), f=True)
mc.connectAttr( (theName+ ".scaleY"), (mySetRange2 + ".valueX"), f=True)
mc.connectAttr( (theName + ".scaleY"), (mySetRange2 + ".valueY"), f=True)
mc.connectAttr( (theName + ".scaleY"), (mySetRange2 + ".valueZ"), f=True)
myhsvToRgb = mc.createNode(‘hsvToRgb’, ss=True)
mc.setAttr((myhsvToRgb+".inHsv"), .75, .75, .75)
mc.connectAttr( (mySetRange + ".outValueX"), (myhsvToRgb + ".inHsvR"), f=True )
mc.connectAttr( (myRamp + ".outColor"), (myBlinn + ".incandescence"), f=True )
mc.connectAttr( (myhsvToRgb + ".outRgb"), (myRamp+ ".colorEntryList[2].color"), f=True )
mc.connectAttr( (mySetRange2 + ".outValue"), (myRamp + ".colorGain"), f=True )
mc.sets( e=True, forceElement= myShader)
count +=1
## read keyframe data and set keyframes
dataFile = open((os.path.join(rootdir, thisFile)), ‘r’)
lines = dataFile.readlines()
mylines = lines[10:-4]
for eachLine in mylines:
data = eachLine.split(‘\t’)
theFrame = data[1]
theValue = data[2]
mc.setKeyframe( o, v=float(theValue), at=theAttribute, t =float(theFrame))
## the code below will set the playback range to equal the amount of the keyframe data in the files
fileData = open(rootdir + ‘/’ + dataFiles[0])
lines= fileData.readlines()
myLines = lines[10:-4]
countLines = len(myLines)
mc.playbackOptions( minTime=’0sec’, maxTime=countLines)

Sample keyframe data, exported from After Effects.


  1. Friso

    This is awesome! Just curious though, did you do anything special for the render? Because I can get the glow if I use Final Gather in Mental Ray with the default lights turned off, but I can’t get it to light up the whole room..

  2. bs219

    wer i put the text file in my system. windows 7 maya 2011.
    pls help me i dont no scripting sorry for the english

  3. Oliver

    It’s an Autodesk Maya script. You need to download the keysframes file here: then run the script from Maya after you have properly modified it to point to those keyframes.

  4. bs219

    ok .i downloaded /scripts/data/
    than where i extract that in my system
    in maya script folder
    or where is this location in my system > rootdir=’/path/to/data/folder’
    i have a little nice idea to work out pls help me

  5. Oscar M

    for windows users
    put the keys in a word remove the text ,leave only the numbers,
    dont leave space at the top.
    rename the file .mov
    select from channel box two attributes
    import in maya move

Post a comment

You may use the following HTML:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>