]> git.0d.be Git - django-panik-emissions.git/blob - emissions/management/commands/create-sound-files.py
update management commands to argparse
[django-panik-emissions.git] / emissions / management / commands / create-sound-files.py
1 import base64
2 import mutagen
3 import mutagen.mp3
4 import shutil
5 import os
6 import subprocess
7
8 from django.core.management.base import BaseCommand, CommandError
9
10 from ...models import SoundFile
11
12
13 class Command(BaseCommand):
14
15     def add_arguments(self, parser):
16         parser.add_argument(
17             '--force',
18             action='store_true',
19             dest='force',
20             default=False,
21             help='Create files even if they exist')
22         parser.add_argument('--reset-metadata',
23             action='store_true',
24             dest='reset_metadata',
25             default=False,
26             help='Reset metadata on all files')
27         parser.add_argument('--emission',
28             dest='emission',
29             metavar='EMISSION',
30             default=None,
31             help='Process files belonging to emission only')
32         parser.add_argument('--episode',
33             dest='episode',
34             metavar='EPISODE',
35             default=None,
36             help='Process files belonging to episode only')
37         parser.add_argument('--copy',
38             action='store_true',
39             dest='copy',
40             default=False,
41             help='Copy initial file (ogg only)')
42
43     def handle(self, force, reset_metadata, copy, emission, episode, verbosity, **kwargs):
44         self.verbose = (verbosity > 1)
45         self.copy = copy
46
47         for soundfile in SoundFile.objects.select_related().exclude(podcastable=False):
48             if emission and soundfile.episode.emission.slug != emission:
49                 continue
50             if episode and soundfile.episode.slug != episode:
51                 continue
52             try:
53                 if soundfile.file is None or not os.path.exists(soundfile.file.path):
54                     continue
55             except ValueError:  # no file associated with it
56                 continue
57             for format in ('ogg', 'mp3'):
58                 file_path = soundfile.get_format_path(format)
59                 created = False
60                 if not os.path.exists(file_path) or force:
61                     self.create(soundfile, format)
62                     created = True
63                 if created or reset_metadata:
64                     self.set_metadata(soundfile, format)
65             if not soundfile.duration:
66                 cmd = ['soxi', '-D', soundfile.get_format_path('ogg')]
67                 soundfile.duration = int(float(subprocess.check_output(cmd)))
68                 soundfile.save()
69
70
71     def create(self, soundfile, format):
72         file_path = soundfile.get_format_path(format)
73         if not os.path.exists(os.path.dirname(file_path)):
74             os.mkdir(os.path.dirname(file_path))
75
76         cmd = ['ffmpeg', '-y', '-i', soundfile.file.path]
77
78         if format == 'ogg':
79             if self.copy:
80                 shutil.copy(soundfile.file.path, file_path)
81                 return
82             cmd.extend(['-q:a', '5'])
83         elif format == 'mp3':
84             cmd.extend(['-q:a', '4'])
85
86         cmd.append(file_path)
87
88         if self.verbose:
89             print 'creating', file_path
90             print '  ', ' '.join(cmd)
91         else:
92             cmd[1:1] = ['-loglevel', 'quiet']
93
94         subprocess.call(cmd)
95
96     def set_metadata(self, soundfile, format):
97         file_path = soundfile.get_format_path(format)
98
99         audio = mutagen.File(file_path, easy=True)
100
101         if 'comment' in audio:
102             del audio['comment']
103         if soundfile.fragment is True and soundfile.title:
104             audio['title'] = '%s - %s' % (
105                     soundfile.episode.title,
106                     soundfile.title)
107         else:
108             audio['title'] = soundfile.episode.title
109         audio['album'] = soundfile.episode.emission.title
110         audio['artist'] = 'Radio Panik'
111
112         if soundfile.episode.image or soundfile.episode.emission.image:
113             image = (soundfile.episode.image or soundfile.episode.emission.image)
114             image.file.open()
115             if os.path.splitext(image.path)[1].lower() in ('.jpeg', '.jpg'):
116                 mimetype = 'image/jpeg'
117             elif os.path.splitext(image.path)[1].lower() == '.png':
118                 mimetype = 'image/png'
119             else:
120                 mimetype = None
121             if mimetype:
122                 if format == 'ogg':
123                     audio['coverartmime'] = mimetype
124                     audio['coverartdescription'] = 'image'
125                     audio['coverart'] = base64.encodestring(image.read()).replace('\n', '')
126                 elif format == 'mp3':
127                     audio.save()
128                     audio = mutagen.mp3.MP3(file_path)
129                     audio.tags.add(mutagen.id3.APIC(
130                             encoding=3, description='image',
131                             type=3, mime=mimetype, data=image.read()))
132             image.close()
133
134         audio.save()