Skip to content
Browse files

video conversion tests and refactor of video.formats and video.poster

  • Loading branch information...
1 parent 73e625a commit c7e22a20a31725667266423fb7df4f5cdbc34d7b @pvl pvl committed Oct 28, 2011
View
18 filer/fields/multistorage_file.py
@@ -35,24 +35,24 @@ def generate_filename_multistorage(instance, filename):
class FormatNameMixin(object):
+
+ def get_format_filepath(self, ext):
+ """ Returns the full file pathname for the given format """
+ return self.format_storage.path(self.get_format_name(ext))
+
def get_format_name(self, ext):
- path, source_filename = os.path.split(self.name)
- filename, extension = os.path.splitext(source_filename)
- newfilename = '%s.%s' % (filename, ext)
- return os.path.join(path, newfilename)
+ """ Returns the local file path in the storage for the given format """
+ file_base, file_ext = os.path.splitext(self.name)
+ return '%s.%s' % (file_base, ext)
def get_format_url(self, ext):
+ """ Returns the url for the given format """
base_name = self.get_format_name(ext)
if self.format_storage.exists(base_name):
return os.path.join(self.format_storage.base_url, base_name)
else:
raise NameError
- def get_poster_url(self):
- original_path, filename = os.path.split(self.name)
- basename = os.path.splitext(filename)[0]
- return self.format_storage.url(os.path.join(original_path, basename + '.png'))
-
class MultiStorageFieldFile(ThumbnailerNameMixin,
easy_thumbnails_files.ThumbnailerFieldFile,
View
25 filer/models/videomodels.py
@@ -72,10 +72,12 @@ def _check_validity(self):
@property
def formats(self):
- _formats = {}
+ _formats = []
for ext in filer_settings.FILER_VIDEO_FORMATS:
try:
- _formats[ext] = self.file.get_format_url(ext)
+ url = self.file.get_format_url(ext)
+ filepath = self.file.get_format_filepath(ext)
+ _formats.append({'url': url, 'format':ext, 'filepath':filepath})
except Exception, e:
pass
return _formats
@@ -91,21 +93,28 @@ def formats_html5(self):
""" Video formats supported by HTML5 browsers """
HTML5_FORMATS = {'mp4':'video/mp4', 'ogv':'video/ogg','webm':'video/webm'}
_formats = []
- for fmt, url in self.formats.items():
- if fmt in HTML5_FORMATS:
- _formats.append({'format': fmt, 'url': url, 'mimetype': HTML5_FORMATS[format]})
+ for entry in self.formats:
+ format = entry['format']
+ if format in HTML5_FORMATS:
+ _formats.append({'format': format, 'url': entry['url'], 'mimetype': HTML5_FORMATS[format]})
return _formats
def format_flash(self):
""" Returns flash video file if available """
- return self.formats.get('flv', None)
+ for entry in self.formats:
+ if entry['format'] == 'flv':
+ return {'format': entry['format'], 'url': entry['url']}
+ return {}
@property
def poster(self):
try:
- return self.file.get_poster_url()
+ ext = 'png'
+ url = self.file.get_format_url(ext)
+ filepath = self.file.get_format_filepath(ext)
+ return {'url': url, 'format':ext, 'filepath':filepath}
except Exception, e:
- return ""
+ return {'url': '', 'format':ext, 'filepath':''}
def convert(self):
original_path = self.file.storage.path(self.file.name)
View
6 filer/templates/filer/video.html
@@ -1,7 +1,7 @@
{% load filermedia %}
<!-- from: http://camendesign.com/code/video_for_everybody -->
<!-- first try HTML5 playback: if serving as XML, expand `controls` to `controls="controls"` and autoplay likewise -->
-<video {% if video.poster %} poster="{{ video.poster }}"{% endif %} width="{{ dimensions.0 }}" height="{{ dimensions.1 }}" controls>
+<video {% if video.poster %} poster="{{ video.poster.url }}"{% endif %} width="{{ dimensions.0 }}" height="{{ dimensions.1 }}" controls>
<!-- MP4 must be first for iPad! -->
{% for fileformat in video.formats_html5 %}
<source src="{{ fileformat.url }}" type='{{ fileformat.mimetype }}' />
@@ -15,9 +15,9 @@
<!-- Firefox uses the `data` attribute above, IE/Safari uses the param below -->
<param name="movie" value="{% filer_staticmedia_prefix %}flash/flowplayer-3.2.7.swf" />
<param name="wmode" value="transparent" />
- <param name="flashVars" value="config={'playlist':['{{ video.poster }}',{'url':'{{ video.format_flash }}','autoPlay':false}]}" />
+ <param name="flashVars" value="config={'playlist':['{{ video.poster.url }}',{'url':'{{ video.format_flash }}','autoPlay':false}]}" />
<!-- fallback image. note the title field below, put the title of the video there -->
- <img src="{{ video.poster }}" alt="{{ video.default_alt_text|default_if_none:'' }}"
+ <img src="{{ video.poster.url }}" alt="{{ video.default_alt_text|default_if_none:'' }}"
title="No video playback capabilities" />
</object>
{% endif %}
View
42 filer/tests/models.py
@@ -11,7 +11,7 @@
from filer.tests.helpers import (create_superuser, create_folder_structure,
create_image, create_clipboard_item)
from filer import settings as filer_settings
-
+from filer.utils.video import check_ffmpeg_available
class FilerApiTests(TestCase):
@@ -143,11 +143,19 @@ def setUp(self):
self.client.login(username='admin', password='secret')
self.video_name = 'video_test.mp4'
self.video_path = os.path.join(os.path.dirname(__file__), 'mediafiles', self.video_name)
-
+ self.is_ffmpeg_available = check_ffmpeg_available()
+
def tearDown(self):
self.client.logout()
for video in Video.objects.all():
- video.delete()
+ self.delete_filer_video(video)
+
+ def delete_filer_video(self, video):
+ for entry in video.formats:
+ os.remove(entry['filepath'])
+ if video.poster.has_key('filepath') and video.poster['filepath']:
+ os.remove(video.poster['filepath'])
+ video.delete()
def create_filer_video(self):
djfile = DjangoFile(open(self.video_path), name=self.video_name)
@@ -163,7 +171,7 @@ def test_create_and_delete_video(self):
self.assertEqual(video.conversion_status, 'new')
self.assertEqual(Video.objects.count(), 1)
video = Video.objects.all()[0]
- video.delete()
+ self.delete_filer_video(video)
self.assertEqual(Video.objects.count(), 0)
def test_upload_video_form(self):
@@ -176,4 +184,28 @@ def test_upload_video_form(self):
if upoad_video_form.is_valid():
video = upoad_video_form.save()
self.assertEqual(Video.objects.count(), 1)
- self.assertEqual(video.conversion_status, 'new')
+ self.assertEqual(video.conversion_status, 'new')
+ self.delete_filer_video(video)
+
+ def test_convert_video(self):
+ if not self.is_ffmpeg_available:
+ return
+ self.assertEqual(Video.objects.count(), 0)
+ video = self.create_filer_video()
+ video.save()
+ self.assertEqual(Video.objects.count(), 1)
+ self.assertEqual(video.width, 320)
+ self.assertEqual(video.height, 240)
+ old_setting = filer_settings.FILER_VIDEO_FORMATS
+ filer_settings.FILER_VIDEO_FORMATS = ('flv', 'mp4', 'webm')
+ video.convert()
+ self.assertEqual(video.original_format()['url'].endswith('video_test.mp4'), True)
+ formats = [ entry['format'] for entry in video.formats ]
+ self.assertEqual('webm' in formats, True)
+ self.assertEqual('flv' in formats, True)
+ self.assertNotEqual(video.format_flash(), None)
+ self.assertEqual(video.poster['url'].endswith('png'), True)
+ video = Video.objects.all()[0]
+ self.delete_filer_video(video)
+ self.assertEqual(Video.objects.count(), 0)
+ filer_settings.FILER_VIDEO_FORMATS = old_setting
View
4 filer/tests/server_backends.py
@@ -30,8 +30,10 @@ def tearDown(self):
for location in (
filer_settings.FILER_PUBLICMEDIA_STORAGE.location,
filer_settings.FILER_PUBLICMEDIA_THUMBNAIL_STORAGE.location,
+ filer_settings.FILER_PUBLICMEDIA_FORMATS_STORAGE.location,
filer_settings.FILER_PRIVATEMEDIA_STORAGE.location,
- filer_settings.FILER_PRIVATEMEDIA_THUMBNAIL_STORAGE.location):
+ filer_settings.FILER_PRIVATEMEDIA_THUMBNAIL_STORAGE.location,
+ filer_settings.FILER_PRIVATEMEDIA_FORMATS_STORAGE.location):
shutil.rmtree(location,ignore_errors=True)
View
4 filer/utils/video.py
@@ -13,6 +13,10 @@
FFMPEG_DIMENSIONS_RE = re.compile(r'Stream.*Video.*([0-9]{3,})x([0-9]{3,})')
+def check_ffmpeg_available():
+ status, output = execute_ffmpeg_command('ffmpeg','')
+ res = re.search('usage: ffmpeg', output)
+ return True if res else False
def get_dimensions(sourcefile):
"""Returns the video dimensions for a video file"""

0 comments on commit c7e22a2

Please sign in to comment.
Something went wrong with that request. Please try again.