py_mpgedit SDK

beta 0.3

Python bindings to the mpgedit audio file editor


Summary

py_mpgedit is a python extension module that wraps the mpgedit sdk. py_mpgedit tries to keep the look and feel of the mpgedit API and be as python friendly as possible. Eventhough py_mpgedit is versioned at beta 0.3, the mpgedit SDK that it wraps is at dev 0.73, has been out for quite a while now and is very stable.

Currently simply_play.py and simple_edit.py are the only example which are included in the SDK.

If you have any questions, suggestions, want to report a bug, need an enhancement or feature, please feel free to email me.

The latest version can be downloaded here.

Classes:

Samples:

Terms and conditions for accessing or otherwise using py_mpgedit is here.


mpgedit.Play

class Play(mp3file)
Constructor for the Play class. mp3file is the name of the mp3 file to play. mp3file may contain a relative or absolute path. To close or free a Play instance, either have the object instance go out of scope, explicitly decrement the reference count with the del command, or call this object's close() method.

play(callback=None)
Play the mp3 file. If a callback is provided, play will call the function callback with two arguments, sec and msec, which is the time offset of the current frame being played. The callback function must return a boolean True value to tell play to continue playing, otherwise, play will stop.

seek_time(sec, msec)
Sets the mp3 file's current position to the frame corresponding to sec and msec.

total_size()
Returns the total size in bytes of the mp3 file.

total_time()
Returns the total time of the mp3 file. The return value is a 2-tuple (sec, msec).

total_info()
Returns the total size and total time of the mp3 file. The return value is a 2-tuple (size, (sec, msec)).

current_time()
Returns the current time of the mp3 file. The return value is a 2-tuple (sec, msec).

get_volume()
Returns the current volume of the system. The return value is a 2-tuple (lvol, rvol) and both value are in the range 0 to 100.

set_volume(lvol, rvol=-1)
Sets the current volume of the system. Both lvol and rvol are in the range 0 to 100. If only lvol is specified, both left and right volumes are set to lvol.

Note: In the current Windows implementation, the right volume is always set to lvol. This will be fixed in a future version of the mpgedit SDK. If this is an issue for anyone at this time, please let us know.

close()
Frees all resources of this object. After this method is called, this object instance cannot be used again. This objects __del__ method calls close(). So having the object go out of scope is usually good enough and an explicit call to close in not required.

mpgedit.Index

class Index(mp3file)
Constructor for the Index class. mp3file is the name of the mp3 file to index. mp3file may contain a relative or absolute path. To close or free a Index instance, either have the object instance go out of scope, explicitly decrement the reference count with the del command, or call this object's close() method.

Indexing is required anytime you want to access an mp3 file by an edit time, as specified by an mpgedit.Spec. Normally, all operations require the index file. Play does not when you are playing from the start of the file. However, when you want to seek to a time, then play, you must have the index file.

index(callback=None)
Creates an index file. If a callback is pass in, index will call the function callback with the arguments (sec, msec, offset). The callback function must return a boolean True value to tell index to continue indexing, otherwise, index will stop.

frames()
Returns the number of the frames indexed at this position.

time()
Returns the time offset for the current indexed position. The return value is a 2-tuple (sec, msec).

offset()
Returns the byte offset for the current indexed position.

info()
Returns the frames, time, and offset indexed at this position. The return value is a 3-tuple (frames, (sec, msec), offset).

mpgedit.Spec

class Spec()
Constructor for the Spec class. To close or free a Spec instance, either have the object instance go out of scope, explicitly decrement the reference count with the del command, or call this object's close() method.

append(mp3file, timespec)
Appends an edit definition for an mp3 file to the spec. mp3file is the name of an mp3 file to edit. mp3file may contain a relative or absolute path. timespec is a string that specifies the start and stop times of the edit to perform on the named mp3 file. The general form of this time specification is 'MM:ss.mmm-MM:ss.mmm' where MM is minutes, ss is seconds and mmm is milliseconds. Any of these fields may be omitted. When the start time specification is omitted, the edit is performed from the start of the mp3 file to the specified end time. When the end time is omitted, the edit is performed from the specified start time to the end of the mp3 file. The entire file may be included in the edit by specifying "-". For example, the timespec string "20-30.500" defines an edit starting 20 seconds from the start of mp3file, and ending at 30 seconds 500 milliseconds. The econds specifier can be greater than 60. For example, "95-1000" is equivalent to "1:35-16:40".

Please refer to the mpgedit sdk documentation for the complete format.

filename(offset)
Returns the file name associated with spec at the location specified by offset. The first entry in Spec is accessed when the value of offset is zero. An empty string is returned when offset is out of bounds.

length()
Returns the number of edit definitions appended to spec.

stime(offset)
Returns the start time associated with the spec at the location specified by offset. The return value is 2-tuple (sec, msec). An IndexError exception is raised if offset is out of bounds.

etime(offset)
Returns the end time associated with the spec at the location specified by offset. The return value is 2-tuple (sec, msec). An IndexError exception is raised if offset is out of bounds.

info(offset)
Returns the filename, length, start time and end time associated with the spec at the location specified by offset. The return value is 3-tuple (filename, (start_sec, start_msec), (end_sec, end_msec)) . An IndexError exception is raised if offset is out of bounds.

info_all()
Retrieves info for all edit definitions contained in Spec. Returns a list containing the filename, length, start time and end time for each edit definition. The return value is a list of 3-tuples (filename, (start_sec, start_msec), (end_sec, end_msec))

close()
Frees all resources of this object. After this method is called, this object instance cannot be used again. This objects __del__ method calls close(). So having the object go out of scope is usually good enough and an explicit call to close in not required.

mpgedit.Edit

class Edit(spec, outfile, flags=0)
Constructor for the Edit class. spec is an instance of Spec. outfile is the name of an output mp3 file that will be generated. outfile may contain a relative or absolute path. flags is optional and defaults to zero. If flags is 0, a outfile will be created and outfile must not exist. If flags is 1, Edit will append to outfile. To close or free an Edit instance, either have the object instance go out of scope, explicitly decrement the reference count with the del command, or call this object's close() method.

edit(callback=None)
Edits an mp3 file. If a callback is specified, edit will call the function callback with the arguments (frame, sec, offset). The callback function must return a boolean True value to tell play to continue editing, otherwise, edit will stop. An MpgeditError will be raised on errors.

frames()
Returns the frame number which is currently being edited.

sec()
Returns the number of seconds which is currently being edited.

offset()
Returns the current byte offset in the file being edited.

sec()
Returns the frame number, number of seconds, and offset which is currently being edited. The return value is a 3-tuple (frame, sec, offset).

xing_header()
Returns a dictionary containing the xing header infomation. Here is an example returned by this method:
{'h_layer': 3, 'bytes': 596332, 'h_protect': 0, 'vbr_scale': 66, flags': 15, 'frames': 1264, 'h_id': 3, 'samprate': 44100}

close()
Frees all resources of this object. After this method is called, this object instance cannot be used again. This objects __del__ method calls close(). So having the object go out of scope is usually good enough and an explicit call to close in not required.

mpgedit.MpgeditError

exception MpgeditError
This exception is raised when there is a problem reading or appending to a file. The associated value of the exception is a 2-tuple that contains the error number a message string. Possible error values are:
  • (1, 'Unable to append to output file')
  • (2, 'Output file exists')
  • (3, 'Unable to read input file')
  • (4, 'Unable to read index file')
  • (5, 'Unable to open output file')
  • (6, 'Invalid Edit object'}

Playing an mp3 file

>>> import mpgedit
>>>
>>> # Create a spec that a time slice of an mp3 file
>>> spec = mpgedit.Spec()
>>> spec.append('test.mp3', '6-12')
>>>
>>> # Create an index for the mp3 file which will contain frame and time data
>>> mpgedit.Index('test.mp3').index()
>>>
>>> # Create a new mp3 file based on the spec  
>>> mpgedit.Edit(spec, 'new.mp3').edit()
>>>
>>> # Play the new mp3 file
>>> mpgedit.Play('new.mp3').play()

Playing an mp3 file

import sys
import mpgedit

class MyPlay:
    def __init__(self, mp3file):
        self.mp3file = mp3file
        self.count = 0
        
    def status(self, sec, msec):
        self.count += 1
        sys.stdout.write('Frame %5d: %02d.%03d sec\r' % (self.count, sec, msec))
        sys.stdout.flush();            
        return 1        

    def play(self):                           
        print 'Playing', self.mp3file
        mpgedit.Index(self.mp3file).index()
        p = mpgedit.Play(self.mp3file)  
        time = p.total_time()
        print 'Total: size=%d time=%d.%03d' % (p.total_size(), time[0], time[1])
        print 'Previous volume: left=%d right=%d' % p.get_volume()        
        p.set_volume(50, 100)
        print 'New volume: left=%d right=%d' % p.get_volume()        
        p.play(self.status) 
        
if __name__ == '__main__':
    try:
        MyPlay(sys.argv[1]).play()        
    except KeyboardInterrupt: pass


Editing an mp3 file

import sys
import mpgedit

def index_callback(frame, sec, msec, offset):
    print 'frame=%4d  time=%2d:%02d  offset=%6d' % (frame, sec, msec, offset)
    return True
 
def edit_callback(frame, sec, offset):
    print 'frame=%4d  sec=%2d  offset=%6d' % (frame, sec, offset)
    return True

def editif_test(mp3file):
    # This test edits a file by scrambling it, then puts it back together
    
    # Create a spec that contains several time slices of the original file
    spec = mpgedit.Spec()
    spec.append(mp3file, '15.986-19.983')
    spec.append(mp3file, '11.989-15.986')
    spec.append(mp3file, '7.993-11.989')
    spec.append(mp3file, '3.996-7.993')
    spec.append(mp3file, '0.0-3.996')
    spec.append(mp3file, '27.976-31.999')
    spec.append(mp3file, '23.979-27.976')
    spec.append(mp3file, '19.983-23.979')
    spec.append(mp3file, '31.999-34.0')

    # Create an index for the original mp3 file which will contain frame and time data
    print '\nCreating index for %s...' % mp3file
    mpgedit.Index(mp3file).index(index_callback)

    
    print '\nSpec entries' 
    print 'length=%d' % spec.length()    
    for s in spec.info_all(): 
        print 'filename=%s, stime=%s, etime=%s' % s

        
    # Create a new mp3 file based on the spec above      
    edit = mpgedit.Edit(spec, 'editif_test.mp3')
    print '\nCreating editif_test.mp3...'
    edit.edit()
    
    print 'info: frames=%d, sec=%d, offset=%d' % edit.info()
    print 'xing header:', edit.xing_header()

    # Create a new spec that will unscramble the scrambled mp3 file
    spec = mpgedit.Spec()
    tmpfile = 'editif_test.mp3'
    spec.append(tmpfile, "15.986-19.983")
    spec.append(tmpfile, "11.989-15.986")
    spec.append(tmpfile, "7.993-11.989")
    spec.append(tmpfile, "3.996-7.993")
    spec.append(tmpfile, "0.0-3.996")
    spec.append(tmpfile, "28.002-31.999")
    spec.append(tmpfile, "24.006-28.002")
    spec.append(tmpfile, "19.983-24.006")
    spec.append(tmpfile, "31.999-")
    
    # Create an index for scrambled mp3 file
    mpgedit.Index(tmpfile).index()    
    print '\nCreating editif_test2.mp3...'
    
    # Create a new mp3 file which will be exactly the same as the original.
    mpgedit.Edit(spec, 'editif_test2.mp3').edit(edit_callback)
    
                                                                          
if __name__ == '__main__':
    editif_test(sys.argv[1])