src/pyams_media/media.py
changeset 130 0ec5e1dc039c
parent 123 6c949ed8d549
equal deleted inserted replaced
129:bb69e502ecc6 130:0ec5e1dc039c
    10 # FOR A PARTICULAR PURPOSE.
    10 # FOR A PARTICULAR PURPOSE.
    11 #
    11 #
    12 
    12 
    13 __docformat__ = 'restructuredtext'
    13 __docformat__ = 'restructuredtext'
    14 
    14 
       
    15 import json
    15 import re
    16 import re
       
    17 from collections import OrderedDict
    16 from mimetypes import guess_extension, guess_type
    18 from mimetypes import guess_extension, guess_type
    17 
    19 
    18 from pyramid.events import subscriber
    20 from pyramid.events import subscriber
    19 from transaction.interfaces import ITransactionManager
    21 from transaction.interfaces import ITransactionManager
    20 from zope.container.folder import Folder
    22 from zope.container.folder import Folder
    25 
    27 
    26 from pyams_file.file import FileFactory
    28 from pyams_file.file import FileFactory
    27 from pyams_file.interfaces import IFile
    29 from pyams_file.interfaces import IFile
    28 from pyams_media.ffbase import FFmpeg
    30 from pyams_media.ffbase import FFmpeg
    29 from pyams_media.ffdocument import FFDocument
    31 from pyams_media.ffdocument import FFDocument
    30 from pyams_media.interfaces import CUSTOM_AUDIO_TYPES, CUSTOM_VIDEO_TYPES, IMediaConversion, IMediaConversionUtility, \
    32 from pyams_media.interfaces import CUSTOM_AUDIO_TYPES, CUSTOM_VIDEO_TYPES, IMediaConversion, \
    31     IMediaConversions, IMediaInfo, MEDIA_CONVERSIONS_KEY, VIDEO_FRAME_SIZE
    33     IMediaConversionUtility, IMediaConversions, IMediaInfo, MEDIA_CONVERSIONS_KEY, \
    32 from pyams_utils.adapter import ContextAdapter, ContextRequestViewAdapter, adapter_config, get_annotation_adapter
    34     VIDEO_FRAME_SIZE
       
    35 from pyams_media.video import get_video_type
       
    36 from pyams_utils.adapter import ContextAdapter, ContextRequestViewAdapter, adapter_config, \
       
    37     get_annotation_adapter
       
    38 from pyams_utils.date import get_timestamp
    33 from pyams_utils.factory import factory_config
    39 from pyams_utils.factory import factory_config
    34 from pyams_utils.interfaces.tales import ITALESExtension
    40 from pyams_utils.interfaces.tales import ITALESExtension
    35 from pyams_utils.registry import get_global_registry, query_utility
    41 from pyams_utils.registry import get_global_registry, query_utility
       
    42 from pyams_utils.url import absolute_url
       
    43 
    36 
    44 
    37 #
    45 #
    38 # Media infos
    46 # Media infos
    39 #
    47 #
    40 
    48 
    78         if extension is None:
    86         if extension is None:
    79             extension = guess_extension(format)
    87             extension = guess_extension(format)
    80         content_type = target.content_type
    88         content_type = target.content_type
    81         if isinstance(content_type, bytes):
    89         if isinstance(content_type, bytes):
    82             content_type = content_type.decode()
    90             content_type = content_type.decode()
    83         target_name = '{name}{width}.{extension}'.format(name=content_type.split('/', 1)[0]
    91         target_name = '{name}{width}.{extension}'.format(
    84                                                              if content_type else 'media',
    92             name=content_type.split('/', 1)[0] if content_type else 'media',
    85                                                          width='-{0}'.format(width) if width else '',
    93             width='-{0}'.format(width) if width else '',
    86                                                          extension=extension)
    94             extension=extension)
    87         if target_name in self:
    95         if target_name in self:
    88             del self[target_name]
    96             del self[target_name]
    89         target.filename = target_name
    97         target.filename = target_name
    90         self[target_name] = target
    98         self[target_name] = target
    91         return target
    99         return target
   111         for conversion in self.get_conversions():
   119         for conversion in self.get_conversions():
   112             if conversion.content_type in formats:
   120             if conversion.content_type in formats:
   113                 return True
   121                 return True
   114         return False
   122         return False
   115 
   123 
       
   124     def get_sources(self, request):
       
   125         sources = []
       
   126         types_order = ('video/mp4','video/webm','video/ogg','video/x-flv')
       
   127         media_width = 0
       
   128         previous_type = None
       
   129         for conversion in self.get_conversions(order=types_order):
       
   130             video_type = get_video_type(conversion, request.registry)
       
   131             min_width = ((media_width or 0) + 1) if (video_type == previous_type) else 0
       
   132             media_width = self.get_conversion_width(conversion.__name__)
       
   133             media_src = '{0}?_={1}'.format(absolute_url(conversion, request),
       
   134                                            get_timestamp(conversion))
       
   135             sources.append({'type': video_type,
       
   136                             'min': min_width,
       
   137                             'max': media_width,
       
   138                             'src': media_src})
       
   139             previous_type = video_type
       
   140         return json.dumps(sources)
       
   141 
   116 
   142 
   117 @adapter_config(context=IFile, provides=IMediaConversions)
   143 @adapter_config(context=IFile, provides=IMediaConversions)
   118 def media_conversions_factory(context):
   144 def media_conversions_factory(context):
   119     """Media conversions factory"""
   145     """Media conversions factory"""
   120     return get_annotation_adapter(context, MEDIA_CONVERSIONS_KEY, IMediaConversions,
   146     return get_annotation_adapter(context, MEDIA_CONVERSIONS_KEY, IMediaConversions,
   127 
   153 
   128     def traverse(self, name, furtherpath=None):
   154     def traverse(self, name, furtherpath=None):
   129         return IMediaConversions(self.context)
   155         return IMediaConversions(self.context)
   130 
   156 
   131 
   157 
   132 @adapter_config(name='conversions', context=(Interface, Interface, Interface), provides=ITALESExtension)
   158 @adapter_config(name='conversions',
       
   159                 context=(Interface, Interface, Interface),
       
   160                 provides=ITALESExtension)
   133 class ConversionsExtension(ContextRequestViewAdapter):
   161 class ConversionsExtension(ContextRequestViewAdapter):
   134     """extension:conversions(media) TALES extension"""
   162     """extension:conversions(media) TALES extension"""
   135 
   163 
   136     def render(self, context=None):
   164     def render(self, context=None):
   137         if context is None:
   165         if context is None: