--- /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)