From: Thomas Fillon Date: Mon, 3 Mar 2014 10:22:16 +0000 (+0100) Subject: Encoder : add Opus encoder X-Git-Tag: 0.5.5~3^2~5 X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=2ba1a39680ab8da915cf76d89335023ba1cfcff1;p=timeside.git Encoder : add Opus encoder --- diff --git a/tests/test_encoding.py b/tests/test_encoding.py index 5fe617f..8df16b6 100755 --- a/tests/test_encoding.py +++ b/tests/test_encoding.py @@ -88,6 +88,13 @@ class TestEncoding(unittest.TestCase): overwrite=self.overwrite, video=True) + def testOpus(self): + "Test opus encoding" + from timeside.encoder.opus import OpusEncoder + self.encoder_function = OpusEncoder + self.delta = 0.1 + self.samplerate = 48000 # 44100 is not supported by opusenc + def tearDown(self): # Source through ArrayDecoder diff --git a/tests/test_transcoding_streaming.py b/tests/test_transcoding_streaming.py index 457f6eb..2ff0f4a 100644 --- a/tests/test_transcoding_streaming.py +++ b/tests/test_transcoding_streaming.py @@ -22,6 +22,7 @@ class TestTranscodingStreaming(unittest.TestCase): self.test_duration = True self.test_channels = True self.filesize_delta = None + self.expected_sample_rate = None def testMp3(self): "Test conversion to mp3" @@ -32,6 +33,11 @@ class TestTranscodingStreaming(unittest.TestCase): "Test conversion to ogg" self.encoder_function = VorbisEncoder + def testOpus(self): + "Test conversion to opus" + self.encoder_function = OpusEncoder + self.expected_sample_rate = 48000 + def testWebM(self): "Test conversion to webm" self.encoder_function = WebMEncoder @@ -75,7 +81,9 @@ class TestTranscodingStreaming(unittest.TestCase): else: self.assertEqual(2, decoder_encoded.channels()) # voaacenc bug ? - self.assertEqual(decoder.samplerate(), + if not self.expected_sample_rate: + self.expected_sample_rate = decoder.samplerate() + self.assertEqual(self.expected_sample_rate, decoder_encoded.samplerate()) if self.test_duration: diff --git a/timeside/encoder/__init__.py b/timeside/encoder/__init__.py index 37cd6b6..0d341a2 100644 --- a/timeside/encoder/__init__.py +++ b/timeside/encoder/__init__.py @@ -6,4 +6,5 @@ from mp3 import Mp3Encoder from flac import FlacEncoder from m4a import AacEncoder from webm import WebMEncoder -from audiosink import AudioSink \ No newline at end of file +from audiosink import AudioSink +from opus import OpusEncoder \ No newline at end of file diff --git a/timeside/encoder/opus.py b/timeside/encoder/opus.py new file mode 100644 index 0000000..c2e379d --- /dev/null +++ b/timeside/encoder/opus.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2007-2014 Parisson SARL +# Copyright (c) 2006-2014 Guillaume Pellerin +# Copyright (c) 2010-2014 Paul Brossier +# Copyright (c) 2009-2010 Olivier Guilyardi +# Copyright (c) 2013-2014 Thomas Fillon + +# 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 . + +# Authors: Guillaume Pellerin +# Paul Brossier +# Thomas Fillon + +from timeside.core import implements, interfacedoc +from timeside.encoder.core import GstEncoder +from timeside.api import IEncoder + + +class OpusEncoder(GstEncoder): + """ gstreamer-based mp3 encoder """ + implements(IEncoder) + + @interfacedoc + def setup(self, channels=None, samplerate=None, blocksize=None, + totalframes=None): + super(OpusEncoder, self).setup(channels, samplerate, blocksize, + totalframes) + + self.pipe = '''appsrc name=src + ! audioconvert ! audioresample + ! opusenc audio=true + ! oggmux + ''' + + 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 async=False sync=False ' % self.filename + else: + self.pipe += '! queue ! appsink name=app sync=False' + + self.start_pipeline(channels, samplerate) + + @staticmethod + @interfacedoc + def id(): + return "gst_opus_enc" + + @staticmethod + @interfacedoc + def description(): + return "Opus GStreamer based encoder" + + @staticmethod + @interfacedoc + def format(): + return "Opus" + + @staticmethod + @interfacedoc + def file_extension(): + return "opus" + + @staticmethod + @interfacedoc + def mime_type(): + return "audio/mpeg" + + @interfacedoc + def set_metadata(self, metadata): + self.metadata = metadata