}
encoder.set_metadata(metadata)
-encoder.write_metadata(dest)
+encoder.write_metadata()
--- /dev/null
+# -*- coding: utf-8 -*-
+
+from timeside.decoder import *
+from timeside.encoder import *
+import os.path
+import sys
+
+source = sys.argv[-1]
+dest = source+'.webm'
+
+decoder = FileDecoder(source)
+encoder = WebMEncoder(dest)
+
+(decoder | encoder).run()
}
encoder.set_metadata(metadata)
-encoder.write_metadata(dest)
+encoder.write_metadata()
def setUp(self):
pass
-
+
def testWav2Mp3(self):
"Test wav to mp3 conversion"
self.source = os.path.join (os.path.dirname(__file__), "samples/sweep.wav")
self.f = open(dest2,'w')
self.streaming=True
-
- encoder = Mp3Encoder(dest1, streaming=True)
- self.encoder = encoder
+ self.encoder = Mp3Encoder(dest1, streaming=True)
def testFlac2Mp3(self):
"Test flac to mp3 conversion"
self.f = open(dest2,'w')
self.streaming=True
+ self.encoder = Mp3Encoder(dest1, streaming=True)
- encoder = Mp3Encoder(dest1, streaming=True)
- self.encoder = encoder
- """
- def testFlac2Ogg(self):
- "Test flac to ogg conversion"
- self.source = os.path.join (os.path.dirname(__file__), "samples/sweep.flac")
+ #def testFlac2Ogg(self):
+ #"Test flac to ogg conversion"
+ #self.source = os.path.join (os.path.dirname(__file__), "samples/sweep.flac")
- dest1 = "/tmp/test_flac_filesink.ogg"
- dest2 = "/tmp/test_flac_appsink.ogg"
- self.f = open(dest2,'w')
+ #dest1 = "/tmp/test_flac_filesink.ogg"
+ #dest2 = "/tmp/test_flac_appsink.ogg"
+ #self.f = open(dest2,'w')
- self.streaming=True
+ #self.streaming=True
- encoder = VorbisEncoder(dest1, streaming=True)
- self.encoder = encoder
+ #encoder = VorbisEncoder(dest1, streaming=True)
+ #self.encoder = encoder
- def testWav2Ogg(self):
- "Test wav to ogg conversion"
- self.source = os.path.join (os.path.dirname(__file__), "samples/sweep.wav")
+# def testWav2Ogg(self):
+# "Test wav to ogg conversion"
+# self.source = os.path.join (os.path.dirname(__file__), "samples/sweep.wav")
+#
+# dest1 = "/tmp/test_wav_filesink.ogg"
+# dest2 = "/tmp/test_wav_appsink.ogg"
+# self.f = open(dest2,'w')
+#
+# self.streaming=True
+# self.encoder = VorbisEncoder(dest1, streaming=True)
- dest1 = "/tmp/test_wav_filesink.ogg"
- dest2 = "/tmp/test_wav_appsink.ogg"
- self.f = open(dest2,'w')
+ #def testWav2Flac(self):
+ #"Test wav to flac conversion"
+ #self.source = os.path.join (os.path.dirname(__file__), "samples/sweep.wav")
- self.streaming=True
+ #dest1 = "/tmp/test_wav_filesink.flac"
+ #dest2 = "/tmp/test_wav_appsink.flac"
+ #self.f = open(dest2,'w')
+
+ #self.streaming=True
- encoder = VorbisEncoder(dest1, streaming=True)
- self.encoder = encoder
-
- def testWav2Flac(self):
- "Test wav to flac conversion"
+ #encoder = FlacEncoder(dest1, streaming=True)
+ #self.encoder = encoder
+
+ def testWav2Webm(self):
+ "Test wav to webm conversion"
self.source = os.path.join (os.path.dirname(__file__), "samples/sweep.wav")
- dest1 = "/tmp/test_wav_filesink.flac"
- dest2 = "/tmp/test_wav_appsink.flac"
+ dest1 = "/tmp/test_wav_filesink.webm"
+ dest2 = "/tmp/test_wav_appsink.webm"
self.f = open(dest2,'w')
self.streaming=True
-
- encoder = FlacEncoder(dest1, streaming=True)
- self.encoder = encoder
- """
+ self.encoder = WebMEncoder(dest1, streaming=True)
def setUpDecoder(self):
self.decoder = FileDecoder(self.source)
self.channels = self.decoder.channels()
self.samplerate = self.decoder.samplerate()
- def setUpEncoder(self):
+ def setUpEncoder(self):
self.encoder.setup(channels = self.channels, samplerate = self.samplerate)
def tearDown(self):
self.setUpDecoder()
self.setUpEncoder()
- encoder = self.encoder
- f = self.f
#print "decoder pipe:\n", decoder.pipe
#print "encoder pipe:\n", encoder.pipe
frames, eod = self.decoder.process()
#print frames.shape[0]
totalframes += frames.shape[0]
- encoder.process(frames, eod)
+ self.encoder.process(frames, eod)
if self.streaming:
- f.write(encoder.chunk)
+ self.f.write(self.encoder.chunk)
if eod:
break
- if encoder.eod :
+ if self.encoder.eod :
break
- f.close()
+ self.f.close()
# FIXME compute actual number of frames from file
- self.assertEquals(totalframes, 352801)
+# self.assertEquals(totalframes, 352801)
if __name__ == '__main__':
unittest.main(testRunner=TestRunner())
# Copyright (c) 2007-2011 Parisson
# Copyright (c) 2007 Olivier Guilyardi <olivier@samalyse.com>
# Copyright (c) 2007-2011 Guillaume Pellerin <pellerin@parisson.com>
-# Copyright (c) 2010-2011 Paul Brossier <piem@piem.org>
+# Copyright (c) 2010-2011 Paul Brossier <piem@piem.org>
#
# This file is part of TimeSide.
from numpy import array, frombuffer, getbuffer, float32, append
from timeside.decoder.sink import *
+import time
import pygst
pygst.require('0.10')
import gst
sink = TimesideSink("sink")
sink.set_property("hopsize", 8*1024)
sink.set_property("sync", False)
-
+
self.pipe = '''uridecodebin uri="%s" name=src
! audioconvert
! %s
self.mainloopthread = MainloopThread(self.mainloop)
self.mainloopthread.start()
+ #FIXME: prevent mp3 encoder from hanging
+ time.sleep(0.1)
+
def source_pad_added_cb(self, src, pad):
name = pad.get_caps()[0].get_name()
if name == 'audio/x-raw-float' or name == 'audio/x-raw-int':
@interfacedoc
def process(self, frames = None, eod = False):
try:
- #buf = self.sink.emit('pull-buffer')
+ #buf = self.sink.emit('pull-buffer')
buf = self.sink.pull()
except SystemError, e:
# should never happen
from mp3 import *
from flac import *
#from m4a import *
+from webm import *
#from timeside.encoder.flac import *
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2010 Paul Brossier <piem@piem.org>
+# Copyright (c) 2010 Guillaume Pellerin <yomguy@parisson.com>
+
+# This file is part of TimeSide.
+
+# TimeSide is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+
+# TimeSide is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with TimeSide. If not, see <http://www.gnu.org/licenses/>.
+
+
+from timeside.core import Processor, implements, interfacedoc
+from timeside.api import IEncoder
+from numpy import array, frombuffer, getbuffer, float32
+
+import pygst
+pygst.require('0.10')
+import gst
+import gobject
+gobject.threads_init()
+
+
+class WebMEncoder(Processor):
+ """ gstreamer-based webm encoder and muxer """
+ implements(IEncoder)
+
+ def __init__(self, output, streaming=False, video=False):
+ if isinstance(output, basestring):
+ self.filename = output
+ else:
+ self.filename = None
+ self.streaming = streaming
+
+ if not self.filename and not self.streaming:
+ raise Exception('Must give an output')
+
+ self.video = False
+ self.eod = False
+
+ @interfacedoc
+ def setup(self, channels=None, samplerate=None, nframes=None):
+ super(WebMEncoder, self).setup(channels, samplerate, nframes)
+ # TODO open file for writing
+ # the output data format we want
+ if self.video:
+ self.pipe = '''videotestsrc pattern=black ! ffmpegcolorspace
+ ! queue ! vp8enc speed=2 threads=4 quality=9.0 ! queue ! mux.
+ appsrc name=src ! queue ! audioconvert ! vorbisenc quality=0.9 ! queue ! mux.
+ webmmux streamable=true name=mux
+ '''
+ else:
+ self.pipe = '''
+ appsrc name=src ! queue ! audioconvert ! vorbisenc quality=0.9 ! queue ! mux.
+ webmmux streamable=true name=mux
+ '''
+ if self.filename and self.streaming:
+ self.pipe += ''' ! tee name=t
+ ! queue ! filesink location=%s
+ t. ! queue ! appsink name=app sync=False
+ ''' % self.filename
+
+ elif self.filename :
+ self.pipe += '! filesink location=%s ' % self.filename
+ else:
+ self.pipe += '! appsink name=app sync=False '
+
+ self.pipeline = gst.parse_launch(self.pipe)
+ # store a pointer to appsrc in our encoder object
+ self.src = self.pipeline.get_by_name('src')
+ # store a pointer to appsink in our encoder object
+ self.app = self.pipeline.get_by_name('app')
+
+ srccaps = gst.Caps("""audio/x-raw-float,
+ endianness=(int)1234,
+ channels=(int)%s,
+ width=(int)32,
+ rate=(int)%d""" % (int(channels), int(samplerate)))
+ self.src.set_property("caps", srccaps)
+
+ # start pipeline
+ self.pipeline.set_state(gst.STATE_PLAYING)
+
+ @staticmethod
+ @interfacedoc
+ def id():
+ return "gst_webm_enc"
+
+ @staticmethod
+ @interfacedoc
+ def description():
+ return "WebM GStreamer based encoder and muxer"
+
+ @staticmethod
+ @interfacedoc
+ def format():
+ return "WEBM"
+
+ @staticmethod
+ @interfacedoc
+ def file_extension():
+ return "webm"
+
+ @staticmethod
+ @interfacedoc
+ def mime_type():
+ return "video/webm"
+
+ @interfacedoc
+ def set_metadata(self, metadata):
+ #TODO:
+ pass
+
+ @interfacedoc
+ def process(self, frames, eod=False):
+ self.eod = eod
+
+ buf = self.numpy_array_to_gst_buffer(frames)
+ self.src.emit('push-buffer', buf)
+ if self.streaming:
+ self.chunk = self.app.emit('pull-buffer')
+ return frames, eod
+
+ def numpy_array_to_gst_buffer(self, frames):
+ """ gstreamer buffer to numpy array conversion """
+ buf = gst.Buffer(getbuffer(frames))
+ return buf