windows - Arbejde med Ogg filer ved hjælp af Python

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg har et 'oggscissors.py' script, der kan klippe og deltage ogg filer. Det har brug for pyogg og pyvorbis bindinger. Når jeg forsøger at udføre dette script krasjer Python tolk. Kildekode for dette script er:


import getopt
import ogg.vorbis
import sys

def usage():
    print 'usage:'
    print '  oggscissors.py --analyze file.ogg'
    print "  oggscissors.py --from=startpos --upto=endpos in.ogg out.ogg"
    sys.exit("  oggscissors.py --join in1.ogg in2.ogg out.ogg")

def analyze\_packets(fin, filenamein):

    count = None
    copied = 0
    written = 0
    pageno = 0

    instream = None

    insync = ogg.OggSyncState()

    while count == None or copied < count:
        b = fin.read(65536)
        if not b:
            break
        insync.bytesin(b)

        skipped = 1
        while skipped != 0:
            skipped, page = insync.pageseek()
            print 'read', skipped, 'bytes:', page
            if skipped > 0:
                if instream and page.serialno() != serialno:
                    print 'we hit a chain boundary, leaving'
                    break
                if not instream:
                    serialno = page.serialno()
                    instream = ogg.OggStreamState(serialno)
                page.pageno = pageno
                pageno = pageno + 1
                instream.pagein(page)
                while 1:
                    p = instream.packetout()
                    if not p:
                        break
                    print '  read', p
                    copied = copied + 1
            elif skipped < 0:
                print 'skipped', -skipped, 'bytes'


def count\_packets(fin):
    print 'Counting packets',

    fin.seek(0)
    count = 0
    instream = None
    insync = ogg.OggSyncState()

    while 1:
        b = fin.read(65536)
        if not b:
            break
        insync.bytesin(b)

        skipped = 1
        while skipped != 0:
            skipped, page = insync.pageseek()
            if skipped > 0:
                if instream and page.serialno() != serialno:
                    print 'we hit a chain boundary, leaving'
                    break
                if not instream:
                    serialno = page.serialno()
                    instream = ogg.OggStreamState(serialno)
                instream.pagein(page)
                while 1:
                    p = instream.packetout()
                    if not p:
                        break
                    #print '  read', p
                    count = count + 1
            elif skipped < 0:
                print 'skipped', -skipped, 'bytes'

    fin.seek(0)
    print count
    return count


def copy\_packets(fin, fout, outstream=None, skip\_packets=0, count=0, written\_pages=0, written\_packets=0, granule\_delta=0, last\_chunk=0):

    fin.seek(0)

    copied = 0
    written = 0
    orig\_packetno = 0
    granule\_skip = 0

    if last\_chunk and count == 0:
        total\_packets = count\_packets(fin) - skip\_packets

    instream = None

    insync = ogg.OggSyncState()

    if skip\_packets: print 'Skipping packets', skip\_packets,

    while count == 0 or copied < count:
        b = fin.read(65536)
        if not b:
            break
        insync.bytesin(b)

        skipped = 1
        while skipped != 0:
            skipped, page = insync.pageseek()
            if skipped > 0:
                if instream and page.serialno() != serialno:
                    print 'we hit a chain boundary'
                    # we hit a chain boundary
                    break
                if not instream:
                    serialno = page.serialno()
                    instream = ogg.OggStreamState(serialno)
                    if not outstream:
                        outstream = ogg.OggStreamState(serialno)
                #print 'reading', page
                instream.pagein(page)
                while count == 0 or copied < count:
                    p = instream.packetout()
                    if not p:
                        break
                    if (skip\_packets > 0):
                        #print '  skipping', p, 'yet to skip:', skip\_packets
                        skip\_packets = skip\_packets - 1
                        orig\_packetno = orig\_packetno + 1
                        if p.granulepos != -1:
                            granule\_skip = p.granulepos
                        if skip\_packets \% 1000 == 0: print skip\_packets,
                        if skip\_packets == 1: print
                        continue
                    #print '  reading', p
                    if p.eos:
                        p.eos = 0
                    if last\_chunk:
                        if count > 0:
                            if copied + 1 == count:
                                p.eos = 512
                        else:
                            if copied + 1 == total\_packets:
                                p.eos = 512
                    if written\_packets >= 3:
                        if samples.has\_key(orig\_packetno):
                            granule\_delta = granule\_delta + samples[orig\_packetno]
                        else:
                            granule\_delta = granule\_delta + 1024
                            print 'Unknown size of packet', orig\_packetno
                        p.granulepos = granule\_delta
                    #print '  writing', p
                    outstream.packetin(p)
                    copied = copied + 1
                    written\_packets = written\_packets + 1
                    orig\_packetno = orig\_packetno + 1
                    if copied \% 1000 == 0: print copied,
                    if copied \% 25000 == 0:
                        print
                        written\_pages, written, outstream = dump\_pages(outstream, written\_pages, written)
            elif skipped < 0:
                print 'skipped', -skipped, 'bytes'

    print copied
    written\_pages, written, outstream = dump\_pages(outstream, written\_pages, written)

    return (written, written\_pages, written\_packets, outstream, granule\_delta)


def dump\_pages(outstream, written\_pages, written):

    print 'Dumping pages',

    while 1:
        pg = outstream.flush()
        if not pg:
            break
        pg.pageno = written\_pages
        #print 'writing', pg
        written = written + pg.writeout(fout)
        #print 'written', written, 'bytes so far'
        written\_pages = written\_pages + 1
        if written\_pages \% 100 == 0: print written\_pages,

    print written\_pages
    return written\_pages, written, outstream


def get\_packetno(seconds, rate):
    needed\_samples = seconds * rate
    for z in samples:
        needed\_samples = needed\_samples - samples[z]
        if needed\_samples <= 0:
            break
    return z


def get\_samples(filenamein):
    print 'Scanning packets'
    vf = ogg.vorbis.VorbisFile(filenamein)
    pcm\_prev = 0
    packetno = 3
    samples = {}
    while 1:
        (buff, bytes, bit) = vf.read(4096)
        if bytes == 0:
            break
        pcm\_now = vf.pcm\_tell()
        samples[packetno] = pcm\_now - pcm\_prev
        if samples[packetno] > 1024:
            print "Clipping bogus packet", packetno, "sample size", samples[packetno], "to 1024"
            samples[packetno] = 1024
        pcm\_prev = pcm\_now
        packetno = packetno + 1
        if packetno \% 1000 == 0: print packetno,
    (buff, bytes,bit) = vf.read(4096)
    vinfo = vf.info()
    return samples, vinfo.rate

def renumber\_pages(filenamein):
    filenameout = filenamein+".fixed.ogg"
    print
    print "Hole detected! Fixing ogg file and writing it to", filenameout
    fin = open(filenamein, 'rb')
    fout = open(filenameout, 'wb')
    insync = ogg.OggSyncState()
    instream = None
    outstream = None
    pageno = 0

    while 1:
        b = fin.read(65536)
        if not b:
            break
        insync.bytesin(b)
        skipped = 1
        while skipped != 0:
            skipped, page = insync.pageseek()
            if skipped > 0:
                if instream and page.serialno() != serialno:
                    print "we hit a chain boundary, leaving"
                    break
                if not instream:
                    serialno = page.serialno()
                    instream = ogg.OggStreamState(serialno)
                if not outstream:
                    outstream = ogg.OggStreamState(serialno)
                instream.pagein(page)
                #print "in -- ", page
                while 1:
                    try:
                        p = instream.packetout()
                    except ogg.OggError:
                        instream.reset()
                        instream.pagein(page)
                        p = instream.packetout()
                    if not p:
                        break
                    outstream.packetin(p)
                while 1:
                    pg = outstream.flush()
                    if not pg:
                        break
                    pg.writeout(fout)
                    #print "out - ", pg

    fin.close()
    fout.close()
    return filenameout

opts, pargs = getopt.getopt(sys.argv[1:], '', ['analyze', 'join', 'from=', 'upto='])
opt\_analyze = opt\_join = 0
startpos = -1
endpos = -1

for option, argument in opts:
    if option == '--from':
        try:
            startpos = float(argument)
        except ValueError:
            usage()
    elif option == '--upto':
        try:
            endpos = float(argument)
        except ValueError:
            usage()
    elif option == '--analyze':
        opt\_analyze = 1
    elif option == '--join':
        opt\_join = 1
    else:
        usage()

if opt\_analyze:
    if len(pargs) != 1:
        usage()

    filenamein = pargs[0]
    fin = open(filenamein, 'rb')
    analyze\_packets(fin, filenamein)

elif opt\_join:
    if len(pargs) != 3:
        usage()

    filenamein = pargs[0]
    try:
        samples, rate = get\_samples(filenamein)
    except ogg.vorbis.VorbisError, errorString:
        filenamein = renumber\_pages(filenamein)
        samples, rate = get\_samples(filenamein)
    fin = open(filenamein, 'rb')

    filenameout = pargs[2]
    fout = open(filenameout, 'wb')

    n, pages, packets, os, grskip = copy\_packets(fin, fout, None, 0, 3)
    n, pages, packets, os, grskip = copy\_packets(fin, fout, os, 3, 0, pages, packets, grskip)

    filenamein = pargs[1]
    try:
        samples, rate = get\_samples(filenamein)
    except ogg.vorbis.VorbisError, errorString:
        filenamein = renumber\_pages(filenamein)
        samples, rate = get\_samples(filenamein)
    fin = open(filenamein, 'rb')

    n, pages, packets, os, grskip = copy\_packets(fin, fout, os, 3, 0, pages, packets, grskip, 1)

else:
    if len(pargs) != 2:
        usage()

    filenamein = pargs[0]
    try:
        samples, rate = get\_samples(filenamein)
    except ogg.vorbis.VorbisError, errorString:
        filenamein = renumber\_pages(filenamein)
        samples, rate = get\_samples(filenamein)
    fin = open(filenamein, 'rb')

    filenameout = pargs[1]
    fout = open(filenameout, 'wb')

    n, pages, packets, os, grskip = copy\_packets(fin, fout, None, 0, 3)

    if startpos > -1:
        startpacket = get\_packetno(startpos, rate)
    else:
        startpacket = 3

    if startpacket > 5:
        startpacket = startpacket - 2

    if endpos > -1:
        endpacket = get\_packetno(endpos, rate)
        count = endpacket - startpacket
    else:
        count = 0

    n, pages, packets, os, grskip = copy\_packets(fin, fout, os, startpacket, count, pages, packets, grskip, 1)


Det styrter i 'get\_samples' -metoden 'vf=ogg.vorbis.VorbisFile (filenamein)'. Kan nogen hjælpe mig med at løse dette problem? Måske compilerede jeg vorbis modulet forkert?

Bedste reference