See #195: fix_track_files command can now recompute size, bitrate and duration
This commit is contained in:
parent
af82111ade
commit
4b21128e46
|
@ -2,6 +2,7 @@ import cacheops
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
from django.db.models import Q
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.management.base import BaseCommand, CommandError
|
from django.core.management.base import BaseCommand, CommandError
|
||||||
|
|
||||||
|
@ -24,6 +25,8 @@ class Command(BaseCommand):
|
||||||
if options['dry_run']:
|
if options['dry_run']:
|
||||||
self.stdout.write('Dry-run on, will not commit anything')
|
self.stdout.write('Dry-run on, will not commit anything')
|
||||||
self.fix_mimetypes(**options)
|
self.fix_mimetypes(**options)
|
||||||
|
self.fix_file_data(**options)
|
||||||
|
self.fix_file_size(**options)
|
||||||
cacheops.invalidate_model(models.TrackFile)
|
cacheops.invalidate_model(models.TrackFile)
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
|
@ -43,3 +46,60 @@ class Command(BaseCommand):
|
||||||
if not dry_run:
|
if not dry_run:
|
||||||
self.stdout.write('[mimetypes] commiting...')
|
self.stdout.write('[mimetypes] commiting...')
|
||||||
qs.update(mimetype=mimetype)
|
qs.update(mimetype=mimetype)
|
||||||
|
|
||||||
|
def fix_file_data(self, dry_run, **kwargs):
|
||||||
|
self.stdout.write('Fixing missing bitrate or length...')
|
||||||
|
matching = models.TrackFile.objects.filter(
|
||||||
|
Q(bitrate__isnull=True) | Q(duration__isnull=True))
|
||||||
|
total = matching.count()
|
||||||
|
self.stdout.write(
|
||||||
|
'[bitrate/length] {} entries found with missing values'.format(
|
||||||
|
total))
|
||||||
|
if dry_run:
|
||||||
|
return
|
||||||
|
for i, tf in enumerate(matching.only('audio_file')):
|
||||||
|
self.stdout.write(
|
||||||
|
'[bitrate/length] {}/{} fixing file #{}'.format(
|
||||||
|
i+1, total, tf.pk
|
||||||
|
))
|
||||||
|
|
||||||
|
try:
|
||||||
|
audio_file = tf.get_audio_file()
|
||||||
|
if audio_file:
|
||||||
|
with audio_file as f:
|
||||||
|
data = utils.get_audio_file_data(audio_file)
|
||||||
|
tf.bitrate = data['bitrate']
|
||||||
|
tf.duration = data['length']
|
||||||
|
tf.save(update_fields=['duration', 'bitrate'])
|
||||||
|
else:
|
||||||
|
self.stderr.write('[bitrate/length] no file found')
|
||||||
|
except Exception as e:
|
||||||
|
self.stderr.write(
|
||||||
|
'[bitrate/length] error with file #{}: {}'.format(
|
||||||
|
tf.pk, str(e)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def fix_file_size(self, dry_run, **kwargs):
|
||||||
|
self.stdout.write('Fixing missing size...')
|
||||||
|
matching = models.TrackFile.objects.filter(size__isnull=True)
|
||||||
|
total = matching.count()
|
||||||
|
self.stdout.write(
|
||||||
|
'[size] {} entries found with missing values'.format(total))
|
||||||
|
if dry_run:
|
||||||
|
return
|
||||||
|
for i, tf in enumerate(matching.only('size')):
|
||||||
|
self.stdout.write(
|
||||||
|
'[size] {}/{} fixing file #{}'.format(
|
||||||
|
i+1, total, tf.pk
|
||||||
|
))
|
||||||
|
|
||||||
|
try:
|
||||||
|
tf.size = tf.get_file_size()
|
||||||
|
tf.save(update_fields=['size'])
|
||||||
|
except Exception as e:
|
||||||
|
self.stderr.write(
|
||||||
|
'[size] error with file #{}: {}'.format(
|
||||||
|
tf.pk, str(e)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
from funkwhale_api.music.management.commands import fix_track_files
|
||||||
|
|
||||||
|
|
||||||
|
def test_fix_track_files_bitrate_length(factories, mocker):
|
||||||
|
tf1 = factories['music.TrackFile'](bitrate=1, duration=2)
|
||||||
|
tf2 = factories['music.TrackFile'](bitrate=None, duration=None)
|
||||||
|
c = fix_track_files.Command()
|
||||||
|
|
||||||
|
mocker.patch(
|
||||||
|
'funkwhale_api.music.utils.get_audio_file_data',
|
||||||
|
return_value={'bitrate': 42, 'length': 43})
|
||||||
|
|
||||||
|
c.fix_file_data(dry_run=False)
|
||||||
|
|
||||||
|
tf1.refresh_from_db()
|
||||||
|
tf2.refresh_from_db()
|
||||||
|
|
||||||
|
# not updated
|
||||||
|
assert tf1.bitrate == 1
|
||||||
|
assert tf1.duration == 2
|
||||||
|
|
||||||
|
# updated
|
||||||
|
assert tf2.bitrate == 42
|
||||||
|
assert tf2.duration == 43
|
||||||
|
|
||||||
|
|
||||||
|
def test_fix_track_files_size(factories, mocker):
|
||||||
|
tf1 = factories['music.TrackFile'](size=1)
|
||||||
|
tf2 = factories['music.TrackFile'](size=None)
|
||||||
|
c = fix_track_files.Command()
|
||||||
|
|
||||||
|
mocker.patch(
|
||||||
|
'funkwhale_api.music.models.TrackFile.get_file_size',
|
||||||
|
return_value=2)
|
||||||
|
|
||||||
|
c.fix_file_size(dry_run=False)
|
||||||
|
|
||||||
|
tf1.refresh_from_db()
|
||||||
|
tf2.refresh_from_db()
|
||||||
|
|
||||||
|
# not updated
|
||||||
|
assert tf1.size == 1
|
||||||
|
|
||||||
|
# updated
|
||||||
|
assert tf2.size == 2
|
Loading…
Reference in New Issue