diff --git a/setup.py b/setup.py index dad3972..6a4914a 100755 --- a/setup.py +++ b/setup.py @@ -19,7 +19,6 @@ install_requires=[ "wagtail>=5.2", "Django>=3.2", - "django-enumchoicefield>=1.1.0", "bcp47==0.0.4", "wagtail-modeladmin>=2.0.0" ], diff --git a/tests/app/migrations/0001_initial.py b/tests/app/migrations/0001_initial.py index 87924e6..eac8fdd 100644 --- a/tests/app/migrations/0001_initial.py +++ b/tests/app/migrations/0001_initial.py @@ -3,7 +3,6 @@ from django.conf import settings from django.db import migrations, models import django.db.models.deletion -import enumchoicefield.fields import modelcluster.fields import taggit.managers import wagtail.fields @@ -89,8 +88,23 @@ class Migration(migrations.Migration): name='CustomVideoTranscode', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('media_format', enumchoicefield.fields.EnumChoiceField(enum_class=wagtailvideos.models.MediaFormats, max_length=4)), - ('quality', enumchoicefield.fields.EnumChoiceField(default=wagtailvideos.models.VideoQuality(1), enum_class=wagtailvideos.models.VideoQuality, max_length=7)), + ('media_format', models.CharField( + choices=[ + ("webm", "VP8 and Vorbis in WebM"), + ("mp4", "H.264 and AAC in Mp4"), + ("ogg", "Theora and Vorbis in Ogg"), + ], + max_length=4, + )), + ('quality', models.CharField( + choices=[ + ("default", "Default"), + ("lowest", "Low"), + ("highest", "High"), + ], + default="default", + max_length=7, + )), ('processing', models.BooleanField(default=False)), ('file', models.FileField(blank=True, null=True, upload_to=wagtailvideos.models.get_upload_to, verbose_name='file')), ('error_message', models.TextField(blank=True)), diff --git a/wagtailvideos/enums.py b/wagtailvideos/enums.py new file mode 100644 index 0000000..19a89af --- /dev/null +++ b/wagtailvideos/enums.py @@ -0,0 +1,42 @@ +from django.db import models +from django.utils.translation import gettext_lazy as _ + + +class VideoQuality(models.TextChoices): + DEFAULT = "default", _("Default") + LOWEST = "lowest", _("Low") + HIGHEST = "highest", _("High") + + +class MediaFormats(models.TextChoices): + WEBM = "webm", _("VP8 and Vorbis in WebM") + MP4 = "mp4", _("H.264 and AAC in Mp4") + OGG = "ogg", _("Theora and Vorbis in Ogg") + + def get_quality_param(self, quality): + if self is MediaFormats.WEBM: + return { + VideoQuality.LOWEST: '50', + VideoQuality.DEFAULT: '22', + VideoQuality.HIGHEST: '4' + }[quality] + elif self is MediaFormats.MP4: + return { + VideoQuality.LOWEST: '28', + VideoQuality.DEFAULT: '24', + VideoQuality.HIGHEST: '18' + }[quality] + elif self is MediaFormats.OGG: + return { + VideoQuality.LOWEST: '5', + VideoQuality.DEFAULT: '7', + VideoQuality.HIGHEST: '9' + }[quality] + + +class VideoTrackKind(models.TextChoices): + SUBTITLES = 'subtitles', _('Subtitles') + CAPTIONS = 'captions', _('Captions') + DESCRIPTIONS = 'descriptions', _('Descriptions') + CHAPTERS = 'chapters', _('Chapters') + METADATA = 'metadata', _('Metadata') diff --git a/wagtailvideos/fields.py b/wagtailvideos/fields.py index 29e4b1b..bc88e7a 100644 --- a/wagtailvideos/fields.py +++ b/wagtailvideos/fields.py @@ -7,7 +7,7 @@ class WagtailVideoField(FileField): def __init__(self, *args, **kwargs): - super(WagtailVideoField, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # Get max upload size from settings self.max_upload_size = getattr(settings, 'WAGTAILVIDEOS_MAX_UPLOAD_SIZE', 1024 * 1024 * 1024) @@ -50,7 +50,7 @@ def check_video_file_size(self, f): ), code='file_too_large') def to_python(self, data): - f = super(WagtailVideoField, self).to_python(data) + f = super().to_python(data) if f is not None: self.check_video_file_size(f) diff --git a/wagtailvideos/forms.py b/wagtailvideos/forms.py index 16e6652..456a7e8 100644 --- a/wagtailvideos/forms.py +++ b/wagtailvideos/forms.py @@ -1,13 +1,13 @@ from django import forms from django.forms.models import modelform_factory from django.utils.translation import gettext as _ -from enumchoicefield.forms import EnumField from wagtail.admin import widgets from wagtail.admin.forms.collections import ( BaseCollectionMemberForm, collection_member_permission_formset_factory) +from wagtailvideos.enums import MediaFormats, VideoQuality from wagtailvideos.fields import WagtailVideoField -from wagtailvideos.models import MediaFormats, Video, VideoQuality +from wagtailvideos.models import Video from wagtailvideos.permissions import \ permission_policy as video_permission_policy @@ -16,7 +16,7 @@ class BaseVideoForm(BaseCollectionMemberForm): permission_policy = video_permission_policy def __init__(self, *args, **kwargs): - super(BaseVideoForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # A file is only required if there is not already a file, such as when # editing an existing video. The file field is not used on the # multiple-upload forms, so may not be present @@ -59,11 +59,11 @@ def get_video_form(model): class VideoTranscodeAdminForm(forms.Form): - media_format = EnumField(MediaFormats) - quality = EnumField(VideoQuality) + media_format = forms.ChoiceField(choices=MediaFormats.choices) + quality = forms.ChoiceField(choices=VideoQuality.choices) def __init__(self, video, data=None, **kwargs): - super(VideoTranscodeAdminForm, self).__init__(data=data, **kwargs) + super().__init__(data=data, **kwargs) self.video = video def save(self): diff --git a/wagtailvideos/jinja2tags.py b/wagtailvideos/jinja2tags.py index c534a31..091cef0 100644 --- a/wagtailvideos/jinja2tags.py +++ b/wagtailvideos/jinja2tags.py @@ -17,7 +17,7 @@ def video(video, **attrs): class WagtailVideosExtension(Extension): def __init__(self, environment): - super(WagtailVideosExtension, self).__init__(environment) + super().__init__(environment) self.environment.globals.update({ 'video': video, diff --git a/wagtailvideos/migrations/0003_auto_20160705_1646.py b/wagtailvideos/migrations/0003_auto_20160705_1646.py index 4075180..749b960 100644 --- a/wagtailvideos/migrations/0003_auto_20160705_1646.py +++ b/wagtailvideos/migrations/0003_auto_20160705_1646.py @@ -3,7 +3,6 @@ from __future__ import absolute_import, print_function, unicode_literals import django.db.models.deletion -import enumchoicefield.fields from django.db import migrations, models import wagtailvideos.models @@ -20,7 +19,14 @@ class Migration(migrations.Migration): name='VideoTranscode', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('media_format', enumchoicefield.fields.EnumChoiceField(enum_class=wagtailvideos.models.MediaFormats, max_length=4)), + ('media_format', models.CharField( + choices=[ + ("webm", "VP8 and Vorbis in WebM"), + ("mp4", "H.264 and AAC in Mp4"), + ("ogg", "Theora and Vorbis in Ogg"), + ], + max_length=4, + )), ('processing', models.BooleanField(default=False)), ('file', models.FileField(null=True, upload_to=wagtailvideos.models.get_upload_to, verbose_name='file')), ('video', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='transcodes', to='wagtailvideos.Video')), diff --git a/wagtailvideos/migrations/0009_videotranscode_quality.py b/wagtailvideos/migrations/0009_videotranscode_quality.py index 9bacb8c..5c1a24e 100644 --- a/wagtailvideos/migrations/0009_videotranscode_quality.py +++ b/wagtailvideos/migrations/0009_videotranscode_quality.py @@ -2,9 +2,7 @@ # Generated by Django 1.9.7 on 2016-08-01 04:35 from __future__ import unicode_literals -from django.db import migrations -import enumchoicefield.fields -import wagtailvideos.models +from django.db import migrations, models class Migration(migrations.Migration): @@ -17,6 +15,14 @@ class Migration(migrations.Migration): migrations.AddField( model_name='videotranscode', name='quality', - field=enumchoicefield.fields.EnumChoiceField(default=wagtailvideos.models.VideoQuality(1), enum_class=wagtailvideos.models.VideoQuality, max_length=7), + field=models.CharField( + choices=[ + ("default", "Default"), + ("lowest", "Low"), + ("highest", "High"), + ], + default="default", + max_length=7, + ), ), ] diff --git a/wagtailvideos/models.py b/wagtailvideos/models.py index 6d49fe5..3a35fdd 100644 --- a/wagtailvideos/models.py +++ b/wagtailvideos/models.py @@ -16,7 +16,6 @@ from django.urls import reverse from django.utils.safestring import mark_safe from django.utils.translation import gettext_lazy as _ -from enumchoicefield import ChoiceEnum, EnumChoiceField from modelcluster.fields import ParentalKey from modelcluster.models import ClusterableModel from taggit.managers import TaggableManager @@ -25,39 +24,19 @@ from wagtail.search import index from wagtail.search.queryset import SearchableQuerySetMixin +from wagtailvideos.enums import MediaFormats, VideoQuality, VideoTrackKind + logger = logging.getLogger(__name__) -class VideoQuality(ChoiceEnum): - default = 'Default' - lowest = 'Low' - highest = 'High' - - -class MediaFormats(ChoiceEnum): - webm = 'VP8 and Vorbis in WebM' - mp4 = 'H.264 and AAC in Mp4' - ogg = 'Theora and Vorbis in Ogg' - - def get_quality_param(self, quality): - if self is MediaFormats.webm: - return { - VideoQuality.lowest: '50', - VideoQuality.default: '22', - VideoQuality.highest: '4' - }[quality] - elif self is MediaFormats.mp4: - return { - VideoQuality.lowest: '28', - VideoQuality.default: '24', - VideoQuality.highest: '18' - }[quality] - elif self is MediaFormats.ogg: - return { - VideoQuality.lowest: '5', - VideoQuality.default: '7', - VideoQuality.highest: '9' - }[quality] +def _choices(text_choices, max_length=None): + """Return a kwargs dict for adding choices and max_length to a CharField""" + if max_length is None: + max_length = max([len(choice) for choice in text_choices.values]) + return { + "choices": text_choices.choices, + "max_length": max_length, + } class VideoQuerySet(SearchableQuerySetMixin, models.QuerySet): @@ -96,7 +75,7 @@ class AbstractVideo(CollectionMember, index.Indexed, models.Model): ] def __init__(self, *args, **kwargs): - super(AbstractVideo, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self._initial_file = self.file def get_file_size(self): @@ -145,9 +124,6 @@ def formatted_duration(self): def __str__(self): return self.title - def save(self, **kwargs): - super(AbstractVideo, self).save(**kwargs) - @property def url(self): return self.file.url @@ -246,7 +222,7 @@ class Meta: class TranscodingThread(threading.Thread): def __init__(self, transcode, **kwargs): - super(TranscodingThread, self).__init__(**kwargs) + super().__init__(**kwargs) self.transcode = transcode def get_file_url(self, file): @@ -289,7 +265,7 @@ def run(self): quality_param = media_format.get_quality_param(self.transcode.quality) args = ['ffmpeg', '-hide_banner', '-i', input_file] try: - if media_format is MediaFormats.ogg: + if media_format is MediaFormats.OGG: subprocess.check_output(args + [ '-codec:v', 'libtheora', '-qscale:v', quality_param, @@ -297,7 +273,7 @@ def run(self): '-qscale:a', '5', output_file, ], stdin=FNULL, stderr=subprocess.STDOUT) - elif media_format is MediaFormats.mp4: + elif media_format is MediaFormats.MP4: subprocess.check_output(args + [ '-codec:v', 'libx264', '-preset', 'slow', # TODO Checkout other presets @@ -305,7 +281,7 @@ def run(self): '-codec:a', 'aac', output_file, ], stdin=FNULL, stderr=subprocess.STDOUT) - elif media_format is MediaFormats.webm: + elif media_format is MediaFormats.WEBM: subprocess.check_output(args + [ '-codec:v', 'libvpx', '-crf', quality_param, @@ -325,8 +301,8 @@ def run(self): class AbstractVideoTranscode(models.Model): - media_format = EnumChoiceField(MediaFormats) - quality = EnumChoiceField(VideoQuality, default=VideoQuality.default) + media_format = models.CharField(**_choices(MediaFormats)) + quality = models.CharField(**_choices(VideoQuality), default=VideoQuality.DEFAULT) processing = models.BooleanField(default=False) file = models.FileField(null=True, blank=True, verbose_name=_('file'), upload_to=get_upload_to) @@ -371,20 +347,11 @@ class TrackListing(AbstractTrackListing): class AbstractVideoTrack(Orderable): - # TODO move to TextChoices once django < 3 is dropped - track_kinds = [ - ('subtitles', _('Subtitles')), - ('captions', _('Captions')), - ('descriptions', _('Descriptions')), - ('chapters', _('Chapters')), - ('metadata', _('Metadata')), - ] - file = models.FileField( verbose_name=_('File'), upload_to=get_upload_to ) - kind = models.CharField(max_length=50, choices=track_kinds, default=track_kinds[0][0], verbose_name=_('Kind')) + kind = models.CharField(**_choices(VideoTrackKind, max_length=50), default=VideoTrackKind.SUBTITLES, verbose_name=_('Kind')) label = models.CharField( max_length=255, blank=True, help_text=_('A user-readable title of the text track.'),