Commit 70ece934 authored by Seb's avatar Seb
Browse files

Added duration field to video, retrieved using ffprobe. Also updated the way...

Added duration field to video, retrieved using ffprobe. Also updated the way post-save fields are generated
parent 03b6d693
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-07-08 06:48
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('wagtailvideos', '0006_auto_20160707_1413'),
]
operations = [
migrations.AddField(
model_name='video',
name='duration',
field=models.CharField(blank=True, max_length=255),
),
]
...@@ -2,6 +2,7 @@ from __future__ import unicode_literals ...@@ -2,6 +2,7 @@ from __future__ import unicode_literals
import os import os
import os.path import os.path
import re
import shutil import shutil
import subprocess import subprocess
import tempfile import tempfile
...@@ -12,7 +13,7 @@ from django.conf import settings ...@@ -12,7 +13,7 @@ from django.conf import settings
from django.core.files.base import ContentFile from django.core.files.base import ContentFile
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.db import models from django.db import models
from django.db.models.signals import pre_delete from django.db.models.signals import post_save, pre_delete
from django.dispatch.dispatcher import receiver from django.dispatch.dispatcher import receiver
from django.utils.encoding import python_2_unicode_compatible from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
...@@ -49,6 +50,7 @@ class AbstractVideo(CollectionMember, TagSearchable): ...@@ -49,6 +50,7 @@ class AbstractVideo(CollectionMember, TagSearchable):
verbose_name=_('file'), upload_to=get_upload_to) verbose_name=_('file'), upload_to=get_upload_to)
thumbnail = models.ImageField(upload_to=get_upload_to, null=True, blank=True) thumbnail = models.ImageField(upload_to=get_upload_to, null=True, blank=True)
created_at = models.DateTimeField(verbose_name=_('created at'), auto_now_add=True, db_index=True) created_at = models.DateTimeField(verbose_name=_('created at'), auto_now_add=True, db_index=True)
duration = models.CharField(max_length=255, blank=True)
uploaded_by_user = models.ForeignKey( uploaded_by_user = models.ForeignKey(
settings.AUTH_USER_MODEL, verbose_name=_('uploaded by user'), settings.AUTH_USER_MODEL, verbose_name=_('uploaded by user'),
null=True, blank=True, editable=False, on_delete=models.SET_NULL null=True, blank=True, editable=False, on_delete=models.SET_NULL
...@@ -110,15 +112,27 @@ class AbstractVideo(CollectionMember, TagSearchable): ...@@ -110,15 +112,27 @@ class AbstractVideo(CollectionMember, TagSearchable):
def __str__(self): def __str__(self):
return self.title return self.title
def get_duration(self):
if self.duration:
return self.duration
file_path = self.file.path
try:
show_format = subprocess.check_output(['ffprobe', '-i', file_path, '-show_format'])
show_format = show_format.decode("utf-8")
# show_format comes out in key=value pairs seperated by newlines
duration = re.findall(r'([duration^=]+)=([^=]+)(?:\n|$)', show_format)[0][1]
hours, remainder = divmod(float(duration), 3600)
minutes, seconds = divmod(remainder, 60)
return "%d:%02d:%02d" % (hours, minutes, seconds)
except subprocess.CalledProcessError:
return ''
def get_thumbnail(self): def get_thumbnail(self):
if self.thumbnail: if self.thumbnail:
return self.thumbnail return self.thumbnail
file_path = os.path.join( file_path = self.file.path
self.file.field.storage.base_location,
self.get_upload_to(self.filename()))
try: try:
output_dir = tempfile.mkdtemp() output_dir = tempfile.mkdtemp()
...@@ -263,6 +277,17 @@ def video_delete(sender, instance, **kwargs): ...@@ -263,6 +277,17 @@ def video_delete(sender, instance, **kwargs):
instance.thumbnail.delete(False) instance.thumbnail.delete(False)
instance.file.delete(False) instance.file.delete(False)
# Fields that need the actual video file to create
@receiver(post_save, sender=Video)
def video_saved(sender, instance, **kwargs):
if hasattr(instance, '_from_signal'):
return
instance.thumbnail = instance.get_thumbnail()
instance.duration = instance.get_duration()
instance.file_size = instance.file.size
instance._from_signal = True
instance.save()
del instance._from_signal
class AbstractVideoTranscode(models.Model): class AbstractVideoTranscode(models.Model):
media_format = EnumChoiceField(MediaFormats) media_format = EnumChoiceField(MediaFormats)
......
...@@ -87,6 +87,8 @@ ...@@ -87,6 +87,8 @@
<dd><img src='{{ video.thumbnail.url }}' /></dd> <dd><img src='{{ video.thumbnail.url }}' /></dd>
<dt>{% trans "Filesize" %}</dt> <dt>{% trans "Filesize" %}</dt>
<dd>{% if filesize %}{{ filesize|filesizeformat }}{% else %}{% trans "File not found" %}{% endif %}</dd> <dd>{% if filesize %}{{ filesize|filesizeformat }}{% else %}{% trans "File not found" %}{% endif %}</dd>
<dt>{% trans "Duration" %}</dt>
<dd>{{ video.duration }}</dd>
</dl> </dl>
</div> </div>
</div> </div>
......
...@@ -107,16 +107,11 @@ def chooser_upload(request): ...@@ -107,16 +107,11 @@ def chooser_upload(request):
if form.is_valid(): if form.is_valid():
video.uploaded_by_user = request.user video.uploaded_by_user = request.user
video.file_size = video.file.size
video.save() video.save()
# Double save because the video file needs to *really* exists to generate thumbnail
video.thumbnail = video.get_thumbnail()
video.save(update_fields=['thumbnail'])
# Reindex the video to make sure all tags are indexed # Reindex the video to make sure all tags are indexed
for backend in get_search_backends(): for backend in get_search_backends():
backend.add(video) backend.add(video)
print("RETURN!!!!")
return render_modal_workflow( return render_modal_workflow(
request, None, 'wagtailvideos/chooser/video_chosen.js', request, None, 'wagtailvideos/chooser/video_chosen.js',
{'video_json': get_video_json(video)} {'video_json': get_video_json(video)}
......
...@@ -58,11 +58,7 @@ def add(request): ...@@ -58,11 +58,7 @@ def add(request):
# Save # Save
video = form.save(commit=False) video = form.save(commit=False)
video.uploaded_by_user = request.user video.uploaded_by_user = request.user
video.file_size = video.file.size
video.save() video.save()
# Double save because the video file needs to *really* exists to generate thumbnail
video.thumbnail = video.get_thumbnail()
video.save(update_fields=['thumbnail'])
# Success! Send back an edit form # Success! Send back an edit form
return JsonResponse({ return JsonResponse({
......
...@@ -87,7 +87,6 @@ def edit(request, video_id): ...@@ -87,7 +87,6 @@ def edit(request, video_id):
video.file_size = video.file.size video.file_size = video.file.size
video = form.save() video = form.save()
video.thumbnail = video.get_thumbnail()
video.save() video.save()
# Reindex the image to make sure all tags are indexed # Reindex the image to make sure all tags are indexed
...@@ -160,9 +159,6 @@ def add(request): ...@@ -160,9 +159,6 @@ def add(request):
video = form.save(commit=False) video = form.save(commit=False)
video.file_size = video.file.size video.file_size = video.file.size
video.save() video.save()
# Double save because the video file needs to *really* exists to generate thumbnail
video.thumbnail = video.get_thumbnail()
video.save(update_fields=['thumbnail'])
# Success! Send back an edit form # Success! Send back an edit form
for backend in get_search_backends(): for backend in get_search_backends():
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment