Replies: /9o/

18:16 - Wed 2012.02.22

iterable ogg encoder


class AudioStreamIterable(object):
    chunk_size = 8096
    decoders = {
            "ogg": ("/usr/bin/oggdec", "-Q", "-o", "-"),
            "flac": ("/usr/bin/flac", "-d", "-c", "--totally-silent"),
            "mp3": ("/usr/bin/mpg123", "-s", "-q"),
        }
    encoder = "/usr/bin/oggenc"

    def __init__(self, filename, bitrate):
        self.filename = filename
        self.bitrate = bitrate
        name, found, suffix = filename.rpartition(".")
        self.decoder_cmd = list(self.decoders[suffix] + (filename, ))
        self.encoder_cmd = [self.encoder, "-r", "-Q", "-b", str(bitrate), "-"]

    def __iter__(self):
        self.p1 = subprocess.Popen(self.decoder_cmd, stdout=subprocess.PIPE)
        self.read_fd, self.write_fd = os.pipe()
        self.p2 = subprocess.Popen(self.encoder_cmd, stdin=self.p1.stdout, stdout=os.fdopen(self.write_fd, "wb"))
        fcntl.fcntl(self.read_fd, fcntl.F_SETFL, os.O_NONBLOCK)
        self.finished = False
        return self

    def next(self):
        try:
            self.finished = not self.p2.poll() is None
            try:
                data = os.read(self.read_fd, self.chunk_size)
            except OSError:
                data = ""
            if not self.finished or len(data) != 0:
                return data
        except socket.error:
            pass
        try:
            self.p1.terminate()
        except OSError:
            pass
        try:
            self.p2.terminate()
        except OSError:
            pass
        try:
            os.close(self.read_fd)
        except OSError:
            pass

        raise StopIteration
    __next__ = next