Permalink
Browse files

set dimensions and allow video resizing

  • Loading branch information...
1 parent f79852b commit deb400efbd4c684911bdb69748669a89610fa82b @pvl pvl committed Oct 26, 2011
Showing with 88 additions and 43 deletions.
  1. +5 −12 filer/admin/videoadmin.py
  2. +9 −5 filer/migrations/0009_auto__add_video.py
  3. +29 −18 filer/models/videomodels.py
  4. +6 −0 filer/settings.py
  5. +39 −8 filer/utils/video.py
View
@@ -6,22 +6,13 @@
from filer.models import Video
-class VideoAdminFrom(forms.ModelForm):
+class VideoAdminForm(forms.ModelForm):
class Meta:
model = Video
- #class Media:
- #css = {
- ##'all': (settings.MEDIA_URL + 'filer/css/focal_point.css',)
- #}
- #js = (
- #filer_settings.FILER_STATICMEDIA_PREFIX + 'js/raphael.js',
- #filer_settings.FILER_STATICMEDIA_PREFIX + 'js/focal_point.js',
- #)
-
class VideoAdmin(FileAdmin):
- form = VideoAdminFrom
+ form = VideoAdminForm
fieldsets = (
FileAdmin.fieldsets[0],
(_('Advanced'), {
@@ -30,7 +21,9 @@ class VideoAdmin(FileAdmin):
'classes': ('collapse',),
}),
(_('Conversion'), {
- 'fields': ('conversion_status', 'conversion_output',),
+ 'fields': ('conversion_status', 'original_height','original_width','height','width',
+ 'conversion_output',),
'classes': ('collapse',),
})
)
+ readonly_fields = ('original_height','original_width')
@@ -11,8 +11,10 @@ def forwards(self, orm):
# Adding model 'Video'
db.create_table('filer_video', (
('file_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['filer.File'], unique=True, primary_key=True)),
- ('_height', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)),
- ('_width', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)),
+ ('original_height', self.gf('django.db.models.fields.IntegerField')(default=0, null=True, blank=True)),
+ ('original_width', self.gf('django.db.models.fields.IntegerField')(default=0, null=True, blank=True)),
+ ('height', self.gf('django.db.models.fields.IntegerField')(default=0, null=True, blank=True)),
+ ('width', self.gf('django.db.models.fields.IntegerField')(default=0, null=True, blank=True)),
('date_taken', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),
('default_alt_text', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
('default_caption', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
@@ -138,17 +140,19 @@ def backwards(self, orm):
},
'filer.video': {
'Meta': {'object_name': 'Video', '_ormbases': ['filer.File']},
- '_height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- '_width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'author': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'conversion_output': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'conversion_status': ('django.db.models.fields.CharField', [], {'default': "'new'", 'max_length': '50'}),
'date_taken': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'default_alt_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'default_caption': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'file_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['filer.File']", 'unique': 'True', 'primary_key': 'True'}),
+ 'height': ('django.db.models.fields.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}),
'must_always_publish_author_credit': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'must_always_publish_copyright': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
+ 'must_always_publish_copyright': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'original_height': ('django.db.models.fields.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}),
+ 'original_width': ('django.db.models.fields.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}),
+ 'width': ('django.db.models.fields.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'})
}
}
@@ -4,7 +4,7 @@
from django.utils.translation import ugettext_lazy as _
from filer import settings as filer_settings
from filer.models.filemodels import File
-from filer.utils.video import convert_video, grab_poster
+from filer.utils.video import convert_video, grab_poster, get_dimensions
VIDEO_STATUS_TYPE = (
('new',_('New')),
@@ -17,8 +17,11 @@ class Video(File):
file_type = 'Video'
_icon = "video"
- _height = models.IntegerField(null=True, blank=True)
- _width = models.IntegerField(null=True, blank=True)
+ original_height = models.IntegerField(null=True, blank=True, default=0)
+ original_width = models.IntegerField(null=True, blank=True, default=0)
+
+ height = models.IntegerField(null=True, blank=True, default=0)
+ width = models.IntegerField(null=True, blank=True, default=0)
date_taken = models.DateTimeField(_('date taken'), null=True, blank=True,
editable=False)
@@ -34,22 +37,28 @@ class Video(File):
conversion_status = models.CharField(max_length=50, choices=VIDEO_STATUS_TYPE, default='new')
conversion_output = models.TextField(blank=True)
+ class Meta:
+ app_label = 'filer'
+ verbose_name = _('video')
+ verbose_name_plural = _('videos')
+
@classmethod
def matches_file_type(cls, iname, ifile, request):
iext = os.path.splitext(iname)[1].lower().lstrip('.')
return iext in filer_settings.FILER_SOURCE_VIDEO_FORMATS
- @property
- def width(self):
- return self._width or 0
-
- @property
- def height(self):
- return self._height or 0
+ def set_initial_dimensions(self):
+ sourcefile = self.file.storage.path(self.file.name)
+ x,y = get_dimensions(sourcefile)
+ self.original_width = x
+ self.original_height = y
+ self.width = x
+ self.height = y
def save(self, *args, **kwargs):
self.has_all_mandatory_data = self._check_validity()
- # TODO try to get metadata like width/height
+ if not self.original_width and not self.original_height:
+ self.set_initial_dimensions()
super(Video, self).save(*args, **kwargs)
def _check_validity(self):
@@ -74,26 +83,28 @@ def poster(self):
except Exception, e:
return ""
-
def convert(self):
original_path = self.file.storage.path(self.file.name)
path = os.path.split(self.file.format_storage.path(self.file.name))[0]
# loop in all
full_res = True
- full_out = ''
+ full_out = ''
for extension in filer_settings.FILER_VIDEO_FORMATS:
- res, out = convert_video(original_path, path, extension)
+ #only set new dimensions if diferent from the original and not zero
+ if self.width and self.height and (
+ self.width != self.original_width or self.height != self.original_height):
+ new_dimensions = "%sx%s" % (self.width, self.height)
+ else:
+ new_dimensions = ""
+ res, out = convert_video(original_path, path, extension, new_dimensions)
res = res or full_res
full_out += out
res, out = grab_poster(original_path, path)
res = res or full_res
full_out += out
return full_res, full_out
- class Meta:
- app_label = 'filer'
- verbose_name = _('video')
- verbose_name_plural = _('videos')
+
#def get_video_flv_url(self):
#return self.file.formats_storage.url(self.flv())
View
@@ -116,3 +116,9 @@
FILER_SOURCE_VIDEO_FORMATS = ('mp4', 'avi', 'wmv', 'mov', 'mpg')
# formats to convert into (no leading dot)
FILER_VIDEO_FORMATS = ('flv', 'mp4')
+# command line for video checking of dimensions
+FFMPEG_CHECK_CMD = "ffmpeg -i %(input_file)s"
+# command line for video conversion
+FFMPEG_CMD = "ffmpeg -i %(input_file)s -y -b 2326k -ar 44100 -ab 224k -ac 2 -f %(format)s -s %(dimensions)s %(target_file)s"
+# command line for grabbing preview image from video
+GRABIMG_CMD = "ffmpeg -y -i %(input_file)s -vframes 1 -ss 00:00:05 -an -vcodec png -f rawvideo -s 100x76 %(target_file)s"
View
@@ -1,10 +1,36 @@
# encoding: utf-8
-"""handles all conversion tasks - originally only video but now also for PDF"""
+"""
+Interface with FFMPEG for operations on video files. The actions performed
+include conversion of video formats, extraction of information and creation
+of poster image file.
+"""
-import os, sys, commands, os.path
-from django.conf import settings
+import os
+import re
+import sys
+import commands
+from filer import settings as filer_settings
-def convert_video(sourcefile, path, extension):
+FFMPEG_DIMENSIONS_RE = re.compile(r'Stream.*Video.*([0-9]{3,})x([0-9]{3,})')
+
+def get_dimensions(sourcefile):
+ """ Returns the video dimensions for a video file """
+ ffmpeg = filer_settings.FFMPEG_CHECK_CMD % {'input_file': commands.mkarg(sourcefile)}
+ try:
+ ffmpegresult = commands.getoutput(ffmpeg)
+ return get_dimensions_from_output(ffmpegresult)
+ except:
+ pass
+
+def get_dimensions_from_output(ffmpeg_output):
+ """ Returns the video dimensions from the output of FFMPEG """
+ dim_match = FFMPEG_DIMENSIONS_RE.search(ffmpeg_output)
+ if dim_match and len(dim_match.groups()) == 2:
+ return int(dim_match.groups()[0]), int(dim_match.groups()[1])
+ else:
+ return 0, 0
+
+def convert_video(sourcefile, path, extension, dimensions):
"""returns True, msg if error or False, msg if ok"""
original_path, filename = os.path.split(sourcefile)
if sourcefile is None:
@@ -13,9 +39,12 @@ def convert_video(sourcefile, path, extension):
convfilename = "%s.%s" % (filebase, extension)
targetfile = os.path.join(path, convfilename)
if not os.path.exists(path):
- os.makedirs(path)
- command_str = settings.FFMPEG_CMD
- ffmpeg = command_str % (commands.mkarg(sourcefile), commands.mkarg(targetfile))
+ os.makedirs(path)
+ cmd_options = {'input_file': commands.mkarg(sourcefile),
+ 'format': commands.mkarg(extension),
+ 'dimensions': commands.mkarg(dimensions),
+ 'target_file': commands.mkarg(targetfile) }
+ ffmpeg = filer_settings.FFMPEG_CMD % cmd_options
#flvtool = "flvtool2 -U %s" % targetfile
try:
ffmpegresult = commands.getoutput(ffmpeg)
@@ -43,7 +72,9 @@ def grab_poster(sourcefile, path):
thumbnailfile = os.path.join(path, thumbnailfilename)
if not os.path.exists(path):
os.makedirs(path)
- grabimage = settings.GRABIMG_CMD % (commands.mkarg(sourcefile), commands.mkarg(thumbnailfile))
+ cmd_options = {'input_file': commands.mkarg(sourcefile),
+ 'target_file': commands.mkarg(thumbnailfile)}
+ grabimage = filer_settings.GRABIMG_CMD % cmd_options
#flvtool = "flvtool2 -U %s" % targetfile
try:
grab = commands.getoutput(grabimage)

0 comments on commit deb400e

Please sign in to comment.