src/pyams_media/converter.py
changeset 0 fd39db613f8b
child 5 73e9b218db71
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_media/converter.py	Wed Sep 02 15:31:55 2015 +0200
@@ -0,0 +1,189 @@
+#
+# Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+__docformat__ = 'restructuredtext'
+
+
+# import standard library
+import mimetypes
+
+from io import StringIO
+from tempfile import NamedTemporaryFile
+
+# import interfaces
+from pyams_media.interfaces import IMediaVideoConverter, IMediaAudioConverter, IMediaConversionUtility, IMediaConverter
+
+# import packages
+from pyams_media.ffdocument import FFDocument
+from pyams_utils.list import unique
+from pyams_utils.registry import utility_config, get_utilities_for, query_utility
+from zope.interface import implementer
+from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm, getVocabularyRegistry
+
+from pyams_media import _
+
+
+class BaseMediaConverter(object):
+    """Base media converter"""
+
+    format = None
+    require_temp_file = False
+
+    def require_input_file(self, media):
+        """Check if a physical file is required to handle conversion"""
+        return media.content_type == b'video/quicktime'
+
+    def convert(self, media):
+        """Convert media"""
+        if self.require_input_file(media):
+            input = NamedTemporaryFile(prefix='input_', suffix=mimetypes.guess_extension(media.contentType))
+            if isinstance(media, str):
+                input.write(media)
+            else:
+                input.write(media.data)
+            input.file.flush()
+            document = FFDocument(input.name)
+        else:
+            if isinstance(media, str):
+                media = StringIO(media)
+            document = FFDocument(media)
+        self.add_filters(document)
+        for loop in self.get_conversion_loop(document):
+            if self.require_temp_file:
+                output = NamedTemporaryFile(prefix='media_', suffix='.%s' % self.format)
+                document.get_output(self.format, target=output.name)
+                output.file.seek(0)
+                yield loop, output.file.read()
+            else:
+                yield loop, document.get_output(self.format)
+
+    def add_filters(self, document):
+        pass
+
+    def get_conversion_loop(self, document):
+        yield None
+
+
+#
+# Audio converters
+#
+
+@implementer(IMediaAudioConverter)
+class BaseAudioConverter(BaseMediaConverter):
+    """Base media converter"""
+
+
+@utility_config(name='audio/wav', provides=IMediaConverter)
+class WavAudioConverter(BaseAudioConverter):
+    """Default WAV media converter"""
+
+    label = _("WAV audio converter")
+    format = 'wav'
+
+
+@utility_config(name='audio/mpeg', provides=IMediaConverter)
+class Mp3AudioConverter(BaseAudioConverter):
+    """Default MP3 media converter"""
+
+    label = _("MP3 audio converter")
+    format = 'mp3'
+
+
+@utility_config(name='audio/ogg', provides=IMediaConverter)
+class OggAudioConverter(BaseAudioConverter):
+    """Default OGG audio converter"""
+
+    label = _("OGG audio converter")
+    format = 'ogg'
+
+
+class AudioConvertersVocabulary(SimpleVocabulary):
+    """Audio converters vocabulary"""
+
+    def __init__(self, context=None):
+        terms = [SimpleTerm(name, title=util.label)
+                 for name, util in unique(get_utilities_for(IMediaConverter))
+                 if IMediaAudioConverter.providedBy(util)]
+        super(AudioConvertersVocabulary, self).__init__(terms)
+
+getVocabularyRegistry().register('PyAMS media audio converters', AudioConvertersVocabulary)
+
+
+#
+# Video converters
+#
+
+@implementer(IMediaVideoConverter)
+class BaseVideoConverter(BaseMediaConverter):
+    """Base video converter"""
+
+    def add_filters(self, document):
+        utility = query_utility(IMediaConversionUtility)
+        if utility is not None:
+            if utility.video_audio_sampling:
+                document.audiosampling(utility.video_audio_sampling)
+            if utility.video_audio_bitrate:
+                document.bitrate(utility.video_audio_bitrate)
+            if utility.video_quantisation:
+                document.quantizerscale(utility.video_quantisation)
+
+    def get_conversion_loop(self, document):
+        utility = query_utility(IMediaConversionUtility)
+        if utility is not None:
+            for size in utility.video_frame_size or ():
+                document.size(size)
+                yield size
+
+
+@utility_config(name='video/x-flv', provides=IMediaConverter)
+class FlvVideoConverter(BaseVideoConverter):
+    """Default FLV media converter"""
+
+    label = _("FLV (Flash Video) video converter")
+    format = 'flv'
+
+
+@utility_config(name='video/mp4', provides=IMediaConverter)
+class Mp4VideoConverter(BaseVideoConverter):
+    """Default MP4 media converter"""
+
+    label = _("MP4 (HTML5) video converter")
+    format = 'mp4'
+    require_temp_file = True
+
+
+@utility_config(name='video/ogg', provides=IMediaConverter)
+class OggVideoConverter(BaseVideoConverter):
+    """OGG media converter"""
+
+    label = _("OGG video converter")
+    format = 'ogg'
+
+
+@utility_config(name='video/webm', provides=IMediaConverter)
+class WebmVideoConverter(BaseVideoConverter):
+    """WebM Media converter"""
+
+    label = _("WebM video converter")
+    format = 'webm'
+
+
+class VideoConvertersVocabulary(SimpleVocabulary):
+    """Video converters vocabulary"""
+
+    def __init__(self, context=None):
+        terms = [SimpleTerm(name, title=util.label)
+                 for name, util in unique(get_utilities_for(IMediaConverter))
+                 if IMediaVideoConverter.providedBy(util)]
+        super(VideoConvertersVocabulary, self).__init__(terms)
+
+getVocabularyRegistry().register('PyAMS media video converters', VideoConvertersVocabulary)