fix: derive media content type from container

This commit is contained in:
wimby
2026-09-25 20:34:08 +02:00
parent d30a808fbd
commit 719f0bf46a
2 changed files with 47 additions and 20 deletions

View File

@@ -928,26 +928,35 @@ class Media(models.Model):
@property
def content_type(self):
if not self.downloaded:
return 'video/mp4'
vcodec = self.downloaded_video_codec
if vcodec is None:
acodec = self.downloaded_audio_codec
if acodec is None:
raise TypeError() # nothing here.
acodec = acodec.upper()
if acodec == Val(YouTube_AudioCodec.MP4A):
return "audio/mp4"
elif acodec == Val(YouTube_AudioCodec.OPUS):
return "audio/opus"
else:
# fall-fall-back.
return 'audio/ogg'
vcodec = vcodec.upper()
if vcodec == Val(YouTube_VideoCodec.AVC1):
return 'video/mp4'
else:
return 'video/matroska'
"""Return a MIME type without requiring downloaded codec metadata.
Imported media can be marked downloaded while codec fields are empty.
MIME type is determined primarily by the container/file extension.
"""
container = (self.downloaded_container or '').strip().lower()
if not container and self.media_file:
container = Path(self.media_file.name).suffix.lstrip('.').lower()
if self.source.is_audio:
return {
'm4a': 'audio/mp4',
'mp4': 'audio/mp4',
'ogg': 'audio/ogg',
'oga': 'audio/ogg',
'opus': 'audio/ogg',
'webm': 'audio/webm',
'mp3': 'audio/mpeg',
}.get(container, 'audio/ogg')
return {
'mp4': 'video/mp4',
'm4v': 'video/mp4',
'mov': 'video/quicktime',
'mkv': 'video/x-matroska',
'matroska': 'video/x-matroska',
'webm': 'video/webm',
'avi': 'video/x-msvideo',
}.get(container, 'video/mp4')
@property
def nfoxml(self):

View File

@@ -48,6 +48,24 @@ class MediaTestCase(TestCase):
self.media.created = datetime(year=2020, month=1, day=1, hour=1,
minute=1, second=1)
def test_content_type_uses_video_container_without_codec_metadata(self):
self.media.downloaded = True
self.media.downloaded_container = 'mkv'
self.media.downloaded_video_codec = None
self.media.downloaded_audio_codec = None
self.assertEqual(self.media.content_type, 'video/x-matroska')
def test_content_type_uses_audio_container_without_codec_metadata(self):
self.source.source_resolution = Val(SourceResolution.AUDIO)
self.source.save(update_fields=['source_resolution'])
self.media.downloaded = True
self.media.downloaded_container = 'mp3'
self.media.downloaded_video_codec = None
self.media.downloaded_audio_codec = None
self.assertEqual(self.media.content_type, 'audio/mpeg')
def test_nfo(self):
expected_tree = ElementTree.fromstring(all_test_metadata['expected_nfo'])
nfo_tree = ElementTree.fromstring(self.media.nfoxml)