--- /dev/null
+import datetime
+import os
+
+import mutagen
+import mutagen.aiff
+import mutagen.mp4
+import mutagen.asf
+
+from django.core.management.base import BaseCommand, CommandError
+
+from ...models import NonstopFile, Track
+
+
+def get_duration(filename):
+ klasses = {'.m4a': mutagen.mp4.MP4,
+ '.wma': mutagen.asf.ASF,
+ '.wav': None,
+ '.WAV': None,
+ }
+ klass = klasses.get(os.path.splitext(filename)[-1], mutagen.File)
+ if klass:
+ try:
+ return klass(filename).info.length
+ except (AttributeError, mutagen.aiff.InvalidChunk):
+ # fallback on soxi
+ pass
+
+ 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():
+ if not line.startswith('Duration'):
+ continue
+ try:
+ hours, minutes, seconds = re.findall('(\d\d):(\d\d):(\d\d)', line)[0]
+ except IndexError:
+ continue
+ return int(hours)*3600 + int(minutes)*60 + int(seconds)
+ return None
+
+
+class Command(BaseCommand):
+ def add_arguments(self, parser):
+ parser.add_argument(
+ '--recent', action='store_true', default=False,
+ help='Only do recent files')
+
+ def handle(self, verbosity, **kwargs):
+ qs = Track.objects.filter(duration__isnull=True)
+ if kwargs.get('recent'):
+ qs = qs.filter(creation_timestamp__gt=datetime.date.today() - datetime.timedelta(days=10))
+ for track in qs:
+ try:
+ file_path = track.file_path()
+ except AttributeError:
+ continue
+ if file_path is None or not os.path.exists(file_path):
+ continue
+ duration = get_duration(file_path)
+ if duration:
+ track.duration = datetime.timedelta(seconds=float(duration))
+ track.save()
--- /dev/null
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('nonstop', '0009_track_added_to_nonstop_timestamp'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='track',
+ name='duration',
+ field=models.DurationField(null=True, verbose_name='Duration'),
+ ),
+ ]
creation_timestamp = models.DateTimeField(auto_now_add=True, null=True)
added_to_nonstop_timestamp = models.DateTimeField(null=True)
uploader = models.ForeignKey(settings.AUTH_USER_MODEL, null=True)
+ duration = models.DurationField(_('Duration'), null=True)
class Meta:
ordering = ['creation_timestamp']
self.filename = os.path.basename(filepath)
def get_local_filepath(self):
+ if not self.short:
+ return None
return os.path.join(LOCAL_BASE_PATH, self.short)