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
from .models import (Emission, Episode, Diffusion, Schedule, SoundFile,
NewsItem, Absence, PlaylistElement)
+from .utils import get_duration
from .widgets import DateTimeWidget, DateWidget
'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:
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(','):
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)
from ckeditor.fields import RichTextField
from taggit.managers import TaggableManager
-from .utils import maybe_resize
+from .utils import maybe_resize, get_duration
LICENSES = (
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
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()