Commit 3a520f21 authored by fred's avatar fred

check and set sound file duration at upload time

parent 056d2177
......@@ -6,6 +6,7 @@ import uuid
from django import forms
from django.forms import fields
from django.forms import ValidationError
from django.core.files.storage import DefaultStorage
from django.core.urlresolvers import reverse
......@@ -19,6 +20,7 @@ from taggit.forms import TagWidget
from .models import (Emission, Episode, Diffusion, Schedule, SoundFile,
NewsItem, Absence, PlaylistElement)
from .utils import get_duration
from .widgets import DateTimeWidget, DateWidget
......@@ -240,6 +242,13 @@ class SoundFileForm(forms.ModelForm):
'file': JqueryFileUploadInput(),
}
def clean(self):
super().clean()
if self.cleaned_data.get('file'):
duration = get_duration(self.cleaned_data['file'].file.name)
if not duration:
raise ValidationError(_('Invalid file, could not get duration.'))
class SoundFileEditForm(forms.ModelForm):
class Meta:
......
......@@ -82,12 +82,8 @@ class Command(BaseCommand):
if not soundfile.podcastable:
# get duration using initial file
if not soundfile.duration:
cmd = ['soxi', '-D', soundfile.file.path]
try:
soundfile.duration = int(float(subprocess.check_output(cmd)))
except (ValueError, subprocess.CalledProcessError):
pass
else:
soundfile.compute_duration()
if soundfile.duration:
soundfile.save()
continue
for format in formats.split(','):
......@@ -98,14 +94,9 @@ class Command(BaseCommand):
if created or reset_metadata:
self.set_metadata(soundfile, format)
if (force or not soundfile.duration):
for extension in ('ogg', 'mp3'):
soundfile_name = soundfile.get_format_path(extension)
if os.path.exists(soundfile_name):
cmd = ['soxi', '-D', soundfile_name]
soundfile.duration = int(float(subprocess.check_output(cmd)))
soundfile.save()
break
soundfile.compute_duration()
if soundfile.duration:
soundfile.save()
def create(self, soundfile, format):
file_path = soundfile.get_format_path(format)
......
......@@ -17,7 +17,7 @@ from django.dispatch.dispatcher import receiver
from ckeditor.fields import RichTextField
from taggit.managers import TaggableManager
from .utils import maybe_resize
from .utils import maybe_resize, get_duration
LICENSES = (
......@@ -496,6 +496,12 @@ class SoundFile(models.Model):
creation_timestamp = models.DateTimeField(auto_now_add=True, null=True)
last_update_timestamp = models.DateTimeField(auto_now=True, null=True)
def compute_duration(self):
for path in (self.get_format_path('ogg'), self.get_format_path('mp3'), self.file.path):
self.duration = get_duration(path)
if self.duration:
return
def get_format_filename(self, format):
return '%s_%05d__%s.%s' % (
self.episode.slug,
......
from datetime import datetime, timedelta, time
import os
import subprocess
from PIL import Image
def get_duration(filename):
p = subprocess.Popen(['mediainfo', '--Inform=Audio;%Duration%', filename],
close_fds=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
try:
return int(stdout) / 1000
except ValueError:
pass
# fallback on soxi
p = subprocess.Popen(['soxi', filename], close_fds=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
for line in stdout.splitlines():
line = force_text(line)
if not line.startswith('Duration'):
continue
try:
hours, minutes, seconds = re.findall(r'(\d\d):(\d\d):(\d\d)', line)[0]
except IndexError:
continue
return int(hours) * 3600 + int(minutes) * 60 + int(seconds)
return None
def maybe_resize(image_path):
if not os.path.exists(image_path):
return
......
......@@ -370,6 +370,13 @@ class EpisodeAddSoundFileView(CreateView):
raise PermissionDenied()
return super(EpisodeAddSoundFileView, self).get_form(*args, **kwargs)
def form_valid(self, form):
response = super().form_valid(form)
if not form.instance.duration:
form.instance.compute_duration()
form.instance.save()
return response
def get_success_url(self):
messages.success(self.request, SUCCESS_MESSAGE)
return self.object.episode.get_absolute_url()
......
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