import subprocess, tempfile, threading, os from config import config decoders = {} encoders = {} class DecoderMeta(type): def __init__(cls, name, bases, dict): if not name in ('Decoder', 'Codec'): decoders[cls.decoder_name] = cls class Decoder(object): __metaclass__ = DecoderMeta class EncoderMeta(type): def __init__(cls, name, bases, dict): if not name in ('Encoder', 'Codec'): encoders[cls.encoder_name] = cls class Encoder(object): __metaclass__ = EncoderMeta class CodecMeta(DecoderMeta, EncoderMeta): def __init__(cls, name, bases, dict): DecoderMeta.__init__(cls, name, bases, dict) EncoderMeta.__init__(cls, name, bases, dict) class Codec(object): __metaclass__ = CodecMeta # end of metastuff class FFmpeg(Decoder): decoder_name = 'ffmpeg' def decode(self, source, dest, *args, **kwargs): cmd = 'ffmpeg -loglevel quiet'.split() if 'start_time' in kwargs and kwargs['start_time']: cmd += ['-ss', str(kwargs['start_time'])] if 'end_time' in kwargs and kwargs['end_time']: cmd += ['-t', str(kwargs['end_time'] - kwargs['start_time'])] cmd += ['-i', source, '-y', dest] p = subprocess.Popen(cmd, stderr = subprocess.PIPE, close_fds = True) p.stderr.close() p.wait() class Ogg(Encoder): encoder_name = 'ogg' def encode(self, source, dest, *args, **kwargs): options = config.get('options', 'encoder/ogg', '') cmd = ['oggenc', '-Q'] + options.split() + [source, '-o', dest] subprocess.call(cmd) class Recoder(object): def __init__(self, decoder, encoder): self.decoder = decoder self.encoder = encoder def recode(self, source, dest, **kwargs): if self.decoder.__class__ == self.encoder.__class__ and hasattr(self.decoder, 'recode'): self.decoder.recode(source, dest) else: with tempfile.NamedTemporaryFile(mode = 'wb', prefix = 'ongaku-', suffix = '.wav', delete = True) as temp: self.decoder.decode(source, temp.name, **kwargs) self.encoder.encode(temp.name, dest, **kwargs) class RecodeThread(threading.Thread): lock = threading.Lock() queue = [] running = False def get_job(self): return self.queue.pop(0) if len(self.queue) else None def run(self): self.lock.acquire() job = self.get_job() while job: self.lock.release() func, decoder, encoder, sessionid = job func(decoder, encoder, sessionid) self.lock.acquire() job = self.get_job() RecodeThread.running = False self.lock.release() @classmethod def add(cls, job): cls.lock.acquire() cls.queue.append(job) if not cls.running: cls.running = True RecodeThread().start() cls.lock.release() if __name__ == '__main__': import sys ffmpeg = FFmpeg() print ffmpeg r = Recoder(ffmpeg, ffmpeg) r.recode(sys.argv[1], sys.argv[2])