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