From 6c8ffee150ee37bf67bf201e7c36fd48f8ad5fbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=84=82=CA=8F=E1=B4=87=E1=B4=85=20=F0=9F=84=B0=CA=99?= =?UTF-8?q?=E1=B4=85=E1=B4=9C=CA=9F=20=F0=9F=84=B0=E1=B4=8D=E1=B4=80?= =?UTF-8?q?=F0=9F=84=9D=20=E2=9C=A7?= Date: Sun, 15 Mar 2026 21:22:08 +0530 Subject: [PATCH 1/9] feat: add AssetType and AssetCodec choices for #1420 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 🄂ʏᴇᴅ 🄰ʙᴅᴜʟ 🄰ᴍᴀ🄝 ✧ --- tubesync/sync/choices.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tubesync/sync/choices.py b/tubesync/sync/choices.py index 80cf62139..94feac916 100644 --- a/tubesync/sync/choices.py +++ b/tubesync/sync/choices.py @@ -257,6 +257,19 @@ class YouTube_VideoCodec(models.TextChoices): AVC1 = 'AVC1', _('AVC1 (H.264)') +class AssetType(models.TextChoices): + THUMBNAIL = 'thumbnail', _('Thumbnail') + AUDIO = 'audio', _('Audio') + VIDEO = 'video', _('Video') + + +class AssetCodec(models.TextChoices): + JPEG = 'jpeg', _('JPEG') + OPUS = 'opus', _('Opus') + VP9 = 'vp9', _('VP9') + AV1 = 'av1', _('AV1') + + SourceResolutionInteger = SourceResolution._integer_mapping() youtube_long_source_types = YouTube_SourceType._long_type_mapping() youtube_validation_urls = YouTube_SourceType._validation_urls() From a70a85b024b9c263ccffe4a3fcee6834419c8f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=84=82=CA=8F=E1=B4=87=E1=B4=85=20=F0=9F=84=B0=CA=99?= =?UTF-8?q?=E1=B4=85=E1=B4=9C=CA=9F=20=F0=9F=84=B0=E1=B4=8D=E1=B4=80?= =?UTF-8?q?=F0=9F=84=9D=20=E2=9C=A7?= Date: Sun, 15 Mar 2026 21:27:40 +0530 Subject: [PATCH 2/9] feat: add Codec model for supported asset codecs for #1421 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 🄂ʏᴇᴅ 🄰ʙᴅᴜʟ 🄰ᴍᴀ🄝 ✧ --- tubesync/sync/models/__init__.py | 6 ++--- tubesync/sync/models/codec.py | 42 ++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 tubesync/sync/models/codec.py diff --git a/tubesync/sync/models/__init__.py b/tubesync/sync/models/__init__.py index a850a4e03..bb13a6ff7 100644 --- a/tubesync/sync/models/__init__.py +++ b/tubesync/sync/models/__init__.py @@ -10,6 +10,7 @@ # The order starts with independent classes # then the classes that depend on them follow. +from .codec import Codec from .media_server import MediaServer from .source import Source @@ -19,7 +20,6 @@ __all__ = [ 'get_media_file_path', 'get_media_thumb_path', - 'media_file_storage', 'MediaServer', 'Source', + 'media_file_storage', 'Codec', 'MediaServer', 'Source', 'Media', 'Metadata', 'MetadataFormat', -] - +] \ No newline at end of file diff --git a/tubesync/sync/models/codec.py b/tubesync/sync/models/codec.py new file mode 100644 index 000000000..72b800c98 --- /dev/null +++ b/tubesync/sync/models/codec.py @@ -0,0 +1,42 @@ +import uuid +from django.db import models +from django.utils.translation import gettext_lazy as _ +from ..choices import AssetType, AssetCodec + + +class Codec(models.Model): + ''' + Codec is a supported codec for a given asset type. + ''' + + uuid = models.UUIDField( + _('uuid'), + primary_key=True, + editable=False, + default=uuid.uuid4, + help_text=_('UUID of the codec'), + ) + asset_type = models.CharField( + _('asset type'), + max_length=16, + db_index=True, + choices=AssetType.choices, + help_text=_('The type of asset this codec is used for'), + ) + codec = models.CharField( + _('codec'), + max_length=16, + db_index=True, + choices=AssetCodec.choices, + help_text=_('The codec name'), + ) + + def __str__(self): + return f'{self.asset_type} / {self.codec}' + + class Meta: + verbose_name = _('Codec') + verbose_name_plural = _('Codecs') + unique_together = ( + ('asset_type', 'codec'), + ) \ No newline at end of file From be466729088721c73e3445e423a9cc35fe154c91 Mon Sep 17 00:00:00 2001 From: tcely Date: Sun, 15 Mar 2026 12:59:15 -0400 Subject: [PATCH 3/9] Update tubesync/sync/choices.py Add `MP4A`, also known as: `M4A` --- tubesync/sync/choices.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tubesync/sync/choices.py b/tubesync/sync/choices.py index 94feac916..4de69389b 100644 --- a/tubesync/sync/choices.py +++ b/tubesync/sync/choices.py @@ -265,7 +265,8 @@ class AssetType(models.TextChoices): class AssetCodec(models.TextChoices): JPEG = 'jpeg', _('JPEG') - OPUS = 'opus', _('Opus') + OPUS = 'OPUS', _('Opus') + MP4A = 'MP4A', _('MP4A') VP9 = 'vp9', _('VP9') AV1 = 'av1', _('AV1') From 3240997867a52d4eaedb2b1a88f05b9061c7e8e2 Mon Sep 17 00:00:00 2001 From: tcely Date: Sun, 15 Mar 2026 13:02:02 -0400 Subject: [PATCH 4/9] Update tubesync/sync/choices.py Add `AVC1` from the `YouTube_VideoCodec` earlier in this file. --- tubesync/sync/choices.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tubesync/sync/choices.py b/tubesync/sync/choices.py index 4de69389b..bcb8b18bf 100644 --- a/tubesync/sync/choices.py +++ b/tubesync/sync/choices.py @@ -268,7 +268,7 @@ class AssetCodec(models.TextChoices): OPUS = 'OPUS', _('Opus') MP4A = 'MP4A', _('MP4A') VP9 = 'vp9', _('VP9') - AV1 = 'av1', _('AV1') + AVC1 = 'AVC1', _('AVC1 (H.264)') SourceResolutionInteger = SourceResolution._integer_mapping() From d837e021da605dd3069cb01208c937d2b861c925 Mon Sep 17 00:00:00 2001 From: tcely Date: Sun, 15 Mar 2026 13:03:24 -0400 Subject: [PATCH 5/9] Update tubesync/sync/choices.py Add `AV1` from the `YouTube_VideoCodec` earlier in this file. --- tubesync/sync/choices.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tubesync/sync/choices.py b/tubesync/sync/choices.py index bcb8b18bf..f540d355f 100644 --- a/tubesync/sync/choices.py +++ b/tubesync/sync/choices.py @@ -267,7 +267,8 @@ class AssetCodec(models.TextChoices): JPEG = 'jpeg', _('JPEG') OPUS = 'OPUS', _('Opus') MP4A = 'MP4A', _('MP4A') - VP9 = 'vp9', _('VP9') + AV1 = 'AV1', _('AV1') + VP9 = 'VP9', _('VP9') AVC1 = 'AVC1', _('AVC1 (H.264)') From 941e355c083032f83dceb43d5923f099fc4df0d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=84=82=CA=8F=E1=B4=87=E1=B4=85=20=F0=9F=84=B0=CA=99?= =?UTF-8?q?=E1=B4=85=E1=B4=9C=CA=9F=20=F0=9F=84=B0=E1=B4=8D=E1=B4=80?= =?UTF-8?q?=F0=9F=84=9D=20=E2=9C=A7?= Date: Sun, 15 Mar 2026 22:43:31 +0530 Subject: [PATCH 6/9] feat: add PNG thumbnail, SUBTITLE type and subtitle codecs to AssetType/AssetCodec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 🄂ʏᴇᴅ 🄰ʙᴅᴜʟ 🄰ᴍᴀ🄝 ✧ --- tubesync/sync/choices.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tubesync/sync/choices.py b/tubesync/sync/choices.py index f540d355f..a504798fa 100644 --- a/tubesync/sync/choices.py +++ b/tubesync/sync/choices.py @@ -261,15 +261,20 @@ class AssetType(models.TextChoices): THUMBNAIL = 'thumbnail', _('Thumbnail') AUDIO = 'audio', _('Audio') VIDEO = 'video', _('Video') + SUBTITLE = 'subtitle', _('Subtitle') class AssetCodec(models.TextChoices): JPEG = 'jpeg', _('JPEG') + PNG = 'png', _('PNG') OPUS = 'OPUS', _('Opus') MP4A = 'MP4A', _('MP4A') AV1 = 'AV1', _('AV1') VP9 = 'VP9', _('VP9') AVC1 = 'AVC1', _('AVC1 (H.264)') + VTT = 'vtt', _('WebVTT') + SRT = 'srt', _('SubRip') + ASS = 'ass', _('Advanced SubStation Alpha') SourceResolutionInteger = SourceResolution._integer_mapping() From b679f559a7c1eea02badf99f364576bc18bd6b4f Mon Sep 17 00:00:00 2001 From: tcely Date: Sun, 15 Mar 2026 13:32:52 -0400 Subject: [PATCH 7/9] Update tubesync/sync/choices.py Switch to `.jpg` and add `.webp` --- tubesync/sync/choices.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tubesync/sync/choices.py b/tubesync/sync/choices.py index a504798fa..1e4b2b834 100644 --- a/tubesync/sync/choices.py +++ b/tubesync/sync/choices.py @@ -265,7 +265,8 @@ class AssetType(models.TextChoices): class AssetCodec(models.TextChoices): - JPEG = 'jpeg', _('JPEG') + JPEG = 'jpg', _('JPEG') + WEBP = 'webp', _('WEBP') PNG = 'png', _('PNG') OPUS = 'OPUS', _('Opus') MP4A = 'MP4A', _('MP4A') From bd8b59353455e3249fee73569aa6dea051ecd00e Mon Sep 17 00:00:00 2001 From: tcely Date: Sun, 15 Mar 2026 13:33:35 -0400 Subject: [PATCH 8/9] Update tubesync/sync/choices.py Add `.ttml` --- tubesync/sync/choices.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tubesync/sync/choices.py b/tubesync/sync/choices.py index 1e4b2b834..279f498af 100644 --- a/tubesync/sync/choices.py +++ b/tubesync/sync/choices.py @@ -274,6 +274,7 @@ class AssetCodec(models.TextChoices): VP9 = 'VP9', _('VP9') AVC1 = 'AVC1', _('AVC1 (H.264)') VTT = 'vtt', _('WebVTT') + TTML = 'ttml', _('TTML') SRT = 'srt', _('SubRip') ASS = 'ass', _('Advanced SubStation Alpha') From 49ef52b0c48abcf3711a406c132568a23a47994b Mon Sep 17 00:00:00 2001 From: tcely Date: Sun, 15 Mar 2026 13:40:19 -0400 Subject: [PATCH 9/9] Update tubesync/sync/choices.py Switch to a text value aligned with the extension. --- tubesync/sync/choices.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tubesync/sync/choices.py b/tubesync/sync/choices.py index 279f498af..38b721010 100644 --- a/tubesync/sync/choices.py +++ b/tubesync/sync/choices.py @@ -269,7 +269,7 @@ class AssetCodec(models.TextChoices): WEBP = 'webp', _('WEBP') PNG = 'png', _('PNG') OPUS = 'OPUS', _('Opus') - MP4A = 'MP4A', _('MP4A') + MP4A = 'M4A', _('MP4A') AV1 = 'AV1', _('AV1') VP9 = 'VP9', _('VP9') AVC1 = 'AVC1', _('AVC1 (H.264)')