19 |
19 |
20 from tempfile import NamedTemporaryFile |
20 from tempfile import NamedTemporaryFile |
21 |
21 |
22 # import interfaces |
22 # import interfaces |
23 from pyams_file.interfaces import IVideo, IThumbnail |
23 from pyams_file.interfaces import IVideo, IThumbnail |
|
24 from pyams_media.interfaces import IVideoType |
|
25 from pyams_utils.interfaces.tales import ITALESExtension |
24 from zope.annotation.interfaces import IAnnotations |
26 from zope.annotation.interfaces import IAnnotations |
25 from zope.traversing.interfaces import ITraversable |
27 from zope.traversing.interfaces import ITraversable |
26 |
28 |
27 # import packages |
29 # import packages |
28 import transaction |
30 import transaction |
29 |
31 |
30 from pyams_file.file import ImageFile, get_magic_content_type |
32 from pyams_file.file import ImageFile, get_magic_content_type |
31 from pyams_file.image import ThumbnailGeometrry |
33 from pyams_file.image import ThumbnailGeometrry |
32 from pyams_media.ffbase import FFmpeg |
34 from pyams_media.ffbase import FFmpeg |
33 from pyams_utils.adapter import adapter_config, ContextAdapter |
35 from pyams_utils.adapter import adapter_config, ContextAdapter, ContextRequestViewAdapter |
34 from pyramid.threadlocal import get_current_registry |
36 from pyramid.threadlocal import get_current_registry |
|
37 from zope.interface import Interface |
35 from zope.lifecycleevent import ObjectCreatedEvent, ObjectAddedEvent |
38 from zope.lifecycleevent import ObjectCreatedEvent, ObjectAddedEvent |
36 from zope.location import locate |
39 from zope.location import locate |
37 |
40 |
38 |
41 |
39 THUMBNAIL_ANNOTATION_KEY = 'pyams_media.video.thumbnail' |
42 THUMBNAIL_ANNOTATION_KEY = 'pyams_media.video.thumbnail' |
51 def get_image_size(self): |
54 def get_image_size(self): |
52 if self.thumbnail is not None: |
55 if self.thumbnail is not None: |
53 return self.thumbnail.get_image_size() |
56 return self.thumbnail.get_image_size() |
54 else: |
57 else: |
55 mpeg = FFmpeg('ffprobe') |
58 mpeg = FFmpeg('ffprobe') |
56 streams = mpeg.info(self.video) |
59 streams = mpeg.info(self.video).get('streams', ()) |
57 if streams: |
60 for stream in streams: |
58 for stream in streams: |
61 if stream.get('codec_type') != 'video': |
59 if stream.get('codec_type') != 'video': |
62 continue |
60 continue |
63 return stream.get('width'), stream.get('height') |
61 return stream.get('width'), stream.get('height') |
|
62 |
64 |
63 def get_thumbnail_size(self, thumbnail_name, forced=False): |
65 def get_thumbnail_size(self, thumbnail_name, forced=False): |
64 if self.thumbnail is not None: |
66 if self.thumbnail is not None: |
65 return IThumbnail(self.thumbnail).get_thumbnail_size(thumbnail_name, forced) |
67 return IThumbnail(self.thumbnail).get_thumbnail_size(thumbnail_name, forced) |
66 else: |
68 else: |
159 format = None |
161 format = None |
160 thumbnails = IThumbnail(self.context) |
162 thumbnails = IThumbnail(self.context) |
161 result = thumbnails.get_thumbnail(thumbnail_name, format) |
163 result = thumbnails.get_thumbnail(thumbnail_name, format) |
162 transaction.commit() |
164 transaction.commit() |
163 return result |
165 return result |
|
166 |
|
167 |
|
168 # |
|
169 # Custom video types |
|
170 # |
|
171 |
|
172 @adapter_config(context=IVideo, provides=IVideoType) |
|
173 class VideoTypeAdapter(ContextAdapter): |
|
174 """Default video content type adapter""" |
|
175 |
|
176 @property |
|
177 def video_type(self): |
|
178 return self.context.content_type |
|
179 |
|
180 |
|
181 @adapter_config(name='video/x-flv', context=IVideo, provides=IVideoType) |
|
182 class FlashVideoTypeAdapter(ContextAdapter): |
|
183 """Flash video content type adapter""" |
|
184 |
|
185 @property |
|
186 def video_type(self): |
|
187 return b'video/flash' |
|
188 |
|
189 |
|
190 @adapter_config(name='video_type', context=(IVideo, Interface, Interface), provides=ITALESExtension) |
|
191 class VideoTypeExtension(ContextRequestViewAdapter): |
|
192 """extension:video_type(media) TALES extension""" |
|
193 |
|
194 def render(self, context=None): |
|
195 if context is None: |
|
196 context = self.context |
|
197 registry = self.request.registry |
|
198 adapter = registry.queryAdapter(context, IVideoType, name=context.content_type.decode()) |
|
199 if adapter is None: |
|
200 adapter = registry.queryAdapter(context, IVideoType) |
|
201 if adapter is not None: |
|
202 return adapter.video_type.decode() |