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
import os
import os.path
import re
import shutil
import subprocess
import tempfile
......@@ -12,7 +13,7 @@ from django.conf import settings
from django.core.files.base import ContentFile
from django.core.urlresolvers import reverse
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.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _
......@@ -49,6 +50,7 @@ class AbstractVideo(CollectionMember, TagSearchable):
verbose_name=_('file'), upload_to=get_upload_to)
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)
duration = models.CharField(max_length=255, blank=True)
uploaded_by_user = models.ForeignKey(
settings.AUTH_USER_MODEL, verbose_name=_('uploaded by user'),
null=True, blank=True, editable=False, on_delete=models.SET_NULL
......@@ -110,15 +112,27 @@ class AbstractVideo(CollectionMember, TagSearchable):
def __str__(self):
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):
if self.thumbnail:
return self.thumbnail
file_path = os.path.join(
self.file.field.storage.base_location,
self.get_upload_to(self.filename()))
file_path = self.file.path
try:
output_dir = tempfile.mkdtemp()
......@@ -263,6 +277,17 @@ def video_delete(sender, instance, **kwargs):
instance.thumbnail.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):
media_format = EnumChoiceField(MediaFormats)
......
......@@ -87,6 +87,8 @@
<dd><img src='{{ video.thumbnail.url }}' /></dd>
<dt>{% trans "Filesize" %}</dt>
<dd>{% if filesize %}{{ filesize|filesizeformat }}{% else %}{% trans "File not found" %}{% endif %}</dd>
<dt>{% trans "Duration" %}</dt>
<dd>{{ video.duration }}</dd>
</dl>
</div>
</div>
......
......@@ -107,16 +107,11 @@ def chooser_upload(request):
if form.is_valid():
video.uploaded_by_user = request.user
video.file_size = video.file.size
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
for backend in get_search_backends():
backend.add(video)
print("RETURN!!!!")
return render_modal_workflow(
request, None, 'wagtailvideos/chooser/video_chosen.js',
{'video_json': get_video_json(video)}
......
......@@ -58,11 +58,7 @@ def add(request):
# Save
video = form.save(commit=False)
video.uploaded_by_user = request.user
video.file_size = video.file.size
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
return JsonResponse({
......
......@@ -87,7 +87,6 @@ def edit(request, video_id):
video.file_size = video.file.size
video = form.save()
video.thumbnail = video.get_thumbnail()
video.save()
# Reindex the image to make sure all tags are indexed
......@@ -160,9 +159,6 @@ def add(request):
video = form.save(commit=False)
video.file_size = video.file.size
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
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