mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2026-05-07 16:06:16 +00:00
Compare commits
No commits in common. "e399a564fa0ad60d84a3cb1f4b0d3114fe7d0233" and "a8ba5954abdaaacafc44e7478403d7d55e749b4d" have entirely different histories.
e399a564fa
...
a8ba5954ab
@ -690,7 +690,10 @@ def get_postprocessors(opts):
|
|||||||
'add_chapters': opts.addchapters,
|
'add_chapters': opts.addchapters,
|
||||||
'add_metadata': opts.addmetadata,
|
'add_metadata': opts.addmetadata,
|
||||||
'add_infojson': opts.embed_infojson,
|
'add_infojson': opts.embed_infojson,
|
||||||
'prefer_mutagen': opts.prefer_mutagen,
|
}
|
||||||
|
if opts.prefer_mutagen:
|
||||||
|
yield {
|
||||||
|
'key': 'Mutagen',
|
||||||
}
|
}
|
||||||
# Deprecated
|
# Deprecated
|
||||||
# This should be above EmbedThumbnail since sponskrub removes the thumbnail attachment
|
# This should be above EmbedThumbnail since sponskrub removes the thumbnail attachment
|
||||||
|
|||||||
@ -30,6 +30,7 @@ from .metadataparser import (
|
|||||||
)
|
)
|
||||||
from .modify_chapters import ModifyChaptersPP
|
from .modify_chapters import ModifyChaptersPP
|
||||||
from .movefilesafterdownload import MoveFilesAfterDownloadPP
|
from .movefilesafterdownload import MoveFilesAfterDownloadPP
|
||||||
|
from .mutagen import MutagenPP
|
||||||
from .sponskrub import SponSkrubPP
|
from .sponskrub import SponSkrubPP
|
||||||
from .sponsorblock import SponsorBlockPP
|
from .sponsorblock import SponsorBlockPP
|
||||||
from .xattrpp import XAttrMetadataPP
|
from .xattrpp import XAttrMetadataPP
|
||||||
|
|||||||
@ -8,8 +8,6 @@ import re
|
|||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from yt_dlp.utils._utils import date_from_str
|
|
||||||
|
|
||||||
from .common import PostProcessor
|
from .common import PostProcessor
|
||||||
from ..compat import imghdr
|
from ..compat import imghdr
|
||||||
from ..utils import (
|
from ..utils import (
|
||||||
@ -34,26 +32,6 @@ from ..utils import (
|
|||||||
variadic,
|
variadic,
|
||||||
write_json_file,
|
write_json_file,
|
||||||
)
|
)
|
||||||
from ..dependencies import mutagen
|
|
||||||
|
|
||||||
if mutagen:
|
|
||||||
import mutagen
|
|
||||||
from mutagen import (
|
|
||||||
FileType,
|
|
||||||
aiff,
|
|
||||||
dsdiff,
|
|
||||||
dsf,
|
|
||||||
flac,
|
|
||||||
id3,
|
|
||||||
mp3,
|
|
||||||
mp4,
|
|
||||||
oggopus,
|
|
||||||
oggspeex,
|
|
||||||
oggtheora,
|
|
||||||
oggvorbis,
|
|
||||||
trueaudio,
|
|
||||||
wave,
|
|
||||||
)
|
|
||||||
|
|
||||||
EXT_TO_OUT_FORMATS = {
|
EXT_TO_OUT_FORMATS = {
|
||||||
'aac': 'adts',
|
'aac': 'adts',
|
||||||
@ -690,51 +668,11 @@ class FFmpegEmbedSubtitlePP(FFmpegPostProcessor):
|
|||||||
|
|
||||||
class FFmpegMetadataPP(FFmpegPostProcessor):
|
class FFmpegMetadataPP(FFmpegPostProcessor):
|
||||||
|
|
||||||
_MUTAGEN_SUPPORTED_EXTS = ('alac', 'aiff', 'flac', 'mp3', 'm4a', 'ogg', 'opus', 'vorbis', 'wav')
|
def __init__(self, downloader, add_metadata=True, add_chapters=True, add_infojson='if_exists'):
|
||||||
_VORBIS_METADATA = {
|
|
||||||
'title': 'title',
|
|
||||||
'artist': 'artist',
|
|
||||||
'genre': 'genre',
|
|
||||||
'album': 'album',
|
|
||||||
'albumartist': 'album_artist',
|
|
||||||
'comment': 'description',
|
|
||||||
'composer': 'composer',
|
|
||||||
'tracknumber': 'track',
|
|
||||||
'WWWAUDIOFILE': 'purl', # https://getmusicbee.com/forum/index.php?topic=39759.0
|
|
||||||
}
|
|
||||||
_ID3_METADATA = {
|
|
||||||
'TIT2': 'title',
|
|
||||||
'TPE1': 'artist',
|
|
||||||
'COMM': 'description',
|
|
||||||
'TCON': 'genre',
|
|
||||||
'WOAF': 'purl',
|
|
||||||
'TALB': 'album',
|
|
||||||
'TPE2': 'album_artist',
|
|
||||||
'TRCK': 'track',
|
|
||||||
'TCOM': 'composer',
|
|
||||||
'TPOS': 'disc',
|
|
||||||
}
|
|
||||||
_MP4_METADATA = {
|
|
||||||
'\251ART': 'artist',
|
|
||||||
'\251nam': 'title',
|
|
||||||
'\251gen': 'genre',
|
|
||||||
'\251alb': 'album',
|
|
||||||
'aART': 'album_artist',
|
|
||||||
'\251cmt': 'description',
|
|
||||||
'\251wrt': 'composer',
|
|
||||||
'disk': 'disc',
|
|
||||||
'tvsh': 'show',
|
|
||||||
'tvsn': 'season_number',
|
|
||||||
'egid': 'episode_id',
|
|
||||||
'tven': 'episode_sort',
|
|
||||||
}
|
|
||||||
|
|
||||||
def __init__(self, downloader, add_metadata=True, add_chapters=True, add_infojson='if_exists', prefer_mutagen=False):
|
|
||||||
FFmpegPostProcessor.__init__(self, downloader)
|
FFmpegPostProcessor.__init__(self, downloader)
|
||||||
self._add_metadata = add_metadata
|
self._add_metadata = add_metadata
|
||||||
self._add_chapters = add_chapters
|
self._add_chapters = add_chapters
|
||||||
self._add_infojson = add_infojson
|
self._add_infojson = add_infojson
|
||||||
self._prefer_mutagen = prefer_mutagen
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _options(target_ext):
|
def _options(target_ext):
|
||||||
@ -743,106 +681,8 @@ class FFmpegMetadataPP(FFmpegPostProcessor):
|
|||||||
if audio_only:
|
if audio_only:
|
||||||
yield from ('-vn', '-acodec', 'copy')
|
yield from ('-vn', '-acodec', 'copy')
|
||||||
|
|
||||||
def _use_mutagen(self, info):
|
|
||||||
if not self._prefer_mutagen:
|
|
||||||
return False
|
|
||||||
if info['ext'] not in self._MUTAGEN_SUPPORTED_EXTS:
|
|
||||||
return False
|
|
||||||
if self._add_chapters and info.get('chapters'):
|
|
||||||
# mutagen can't handle adding chapters to M4A
|
|
||||||
return False
|
|
||||||
if not mutagen:
|
|
||||||
self.report_warning('module mutagen was not found. Please install using `python3 -m pip install mutagen`')
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
if mutagen:
|
|
||||||
@functools.singledispatchmethod
|
|
||||||
def _assemble_metadata(self, file: FileType, meta: dict) -> None:
|
|
||||||
raise FFmpegPostProcessorError(f'Filetype {file.__class__.__name__} is not currently supported')
|
|
||||||
|
|
||||||
@_assemble_metadata.register(oggvorbis.OggVorbis)
|
|
||||||
@_assemble_metadata.register(oggtheora.OggTheora)
|
|
||||||
@_assemble_metadata.register(oggspeex.OggSpeex)
|
|
||||||
@_assemble_metadata.register(oggopus.OggOpus)
|
|
||||||
@_assemble_metadata.register(flac.FLAC)
|
|
||||||
def _(self, file: oggopus.OggOpus, meta: dict) -> None:
|
|
||||||
for file_key, meta_key in self._VORBIS_METADATA.items():
|
|
||||||
if meta.get(meta_key):
|
|
||||||
file[file_key] = meta[meta_key]
|
|
||||||
|
|
||||||
if meta.get('date'):
|
|
||||||
# Vorbis uses ISO 8601 format YYYY-MM-DD
|
|
||||||
date = date_from_str(meta['date'])
|
|
||||||
file['date'] = date.strftime('%Y-%m-%d')
|
|
||||||
|
|
||||||
@_assemble_metadata.register(trueaudio.TrueAudio)
|
|
||||||
@_assemble_metadata.register(dsf.DSF)
|
|
||||||
@_assemble_metadata.register(dsdiff.DSDIFF)
|
|
||||||
@_assemble_metadata.register(aiff.AIFF)
|
|
||||||
@_assemble_metadata.register(mp3.MP3)
|
|
||||||
@_assemble_metadata.register(wave.WAVE)
|
|
||||||
def _(self, file: wave.WAVE, meta: dict) -> None:
|
|
||||||
for file_key, meta_key in self._ID3_METADATA.items():
|
|
||||||
if meta.get(meta_key):
|
|
||||||
id3_class = getattr(id3, file_key)
|
|
||||||
if issubclass(id3_class, id3.UrlFrame):
|
|
||||||
file[file_key] = id3_class(url=meta[meta_key])
|
|
||||||
else:
|
|
||||||
file[file_key] = id3_class(encoding=id3.Encoding.UTF8, text=meta[meta_key])
|
|
||||||
|
|
||||||
if meta.get('date'):
|
|
||||||
# ID3 uses ISO 8601 format YYYY-MM-DD
|
|
||||||
date = date_from_str(meta['date'])
|
|
||||||
file['TDRC'] = id3.TDRC(encoding=id3.Encoding.UTF8, text=date.strftime('%Y-%m-%d'))
|
|
||||||
|
|
||||||
@_assemble_metadata.register(mp4.MP4)
|
|
||||||
def _(self, file: mp4.MP4, meta: dict) -> None:
|
|
||||||
for file_key, meta_key in self._MP4_METADATA.items():
|
|
||||||
if meta.get(meta_key):
|
|
||||||
file[file_key] = meta[meta_key]
|
|
||||||
|
|
||||||
if meta.get('date'):
|
|
||||||
# no standard but iTunes uses YYYY-MM-DD format
|
|
||||||
date = date_from_str(meta['date'])
|
|
||||||
file['\251day'] = date.strftime('%Y-%m-%d')
|
|
||||||
|
|
||||||
if meta.get('purl'):
|
|
||||||
# https://getmusicbee.com/forum/index.php?topic=39759.0
|
|
||||||
file['----:com.apple.iTunes:WWWAUDIOFILE'] = meta['purl'].encode()
|
|
||||||
file['purl'] = meta['purl']
|
|
||||||
|
|
||||||
if meta.get('track'):
|
|
||||||
file['trkn'] = [(meta['track'], 0)]
|
|
||||||
|
|
||||||
def _run_mutagen(self, info):
|
|
||||||
self.to_screen('Using mutagen to embed metadata')
|
|
||||||
filename = info['filepath']
|
|
||||||
metadata = self._get_metadata_dict(info)['common']
|
|
||||||
if not metadata:
|
|
||||||
self.to_screen('There isn\'t any metadata to add')
|
|
||||||
return [], info
|
|
||||||
|
|
||||||
self.to_screen(f'Adding metadata to "{filename}"')
|
|
||||||
try:
|
|
||||||
f = mutagen.File(filename)
|
|
||||||
self._assemble_metadata(f, metadata)
|
|
||||||
f.save()
|
|
||||||
except Exception as err:
|
|
||||||
raise FFmpegPostProcessorError(f'Unable to embed metadata; {err}')
|
|
||||||
|
|
||||||
return [], info
|
|
||||||
|
|
||||||
@PostProcessor._restrict_to(images=False)
|
@PostProcessor._restrict_to(images=False)
|
||||||
def run(self, info):
|
def run(self, info):
|
||||||
|
|
||||||
if self._use_mutagen(info):
|
|
||||||
try:
|
|
||||||
self._run_mutagen(info)
|
|
||||||
return [], info
|
|
||||||
except Exception as err:
|
|
||||||
self.report_warning(f'Unable to embed metadata using mutagen; {err}')
|
|
||||||
|
|
||||||
self._fixup_chapters(info)
|
self._fixup_chapters(info)
|
||||||
filename, metadata_filename = info['filepath'], None
|
filename, metadata_filename = info['filepath'], None
|
||||||
files_to_delete, options = [], []
|
files_to_delete, options = [], []
|
||||||
@ -892,7 +732,7 @@ class FFmpegMetadataPP(FFmpegPostProcessor):
|
|||||||
f.write(metadata_file_content)
|
f.write(metadata_file_content)
|
||||||
yield ('-map_metadata', '1')
|
yield ('-map_metadata', '1')
|
||||||
|
|
||||||
def _get_metadata_dict(self, info):
|
def _get_metadata_opts(self, info):
|
||||||
meta_prefix = 'meta'
|
meta_prefix = 'meta'
|
||||||
metadata = collections.defaultdict(dict)
|
metadata = collections.defaultdict(dict)
|
||||||
|
|
||||||
@ -934,10 +774,6 @@ class FFmpegMetadataPP(FFmpegPostProcessor):
|
|||||||
mobj = re.fullmatch(meta_regex, key)
|
mobj = re.fullmatch(meta_regex, key)
|
||||||
if value is not None and mobj:
|
if value is not None and mobj:
|
||||||
metadata[mobj.group('i') or 'common'][mobj.group('key')] = value.replace('\0', '')
|
metadata[mobj.group('i') or 'common'][mobj.group('key')] = value.replace('\0', '')
|
||||||
return metadata
|
|
||||||
|
|
||||||
def _get_metadata_opts(self, info):
|
|
||||||
metadata = self._get_metadata_dict(info)
|
|
||||||
|
|
||||||
# Write id3v1 metadata also since Windows Explorer can't handle id3v2 tags
|
# Write id3v1 metadata also since Windows Explorer can't handle id3v2 tags
|
||||||
yield ('-write_id3v1', '1')
|
yield ('-write_id3v1', '1')
|
||||||
|
|||||||
204
yt_dlp/postprocessor/mutagen.py
Normal file
204
yt_dlp/postprocessor/mutagen.py
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
import collections
|
||||||
|
from functools import singledispatchmethod
|
||||||
|
import re
|
||||||
|
from typing import TypedDict
|
||||||
|
|
||||||
|
from yt_dlp.utils._utils import PostProcessingError, variadic
|
||||||
|
from ..dependencies import mutagen
|
||||||
|
|
||||||
|
if mutagen:
|
||||||
|
import mutagen
|
||||||
|
from mutagen import (
|
||||||
|
FileType,
|
||||||
|
aiff,
|
||||||
|
dsdiff,
|
||||||
|
dsf,
|
||||||
|
flac,
|
||||||
|
id3,
|
||||||
|
mp3,
|
||||||
|
mp4,
|
||||||
|
oggopus,
|
||||||
|
oggspeex,
|
||||||
|
oggtheora,
|
||||||
|
oggvorbis,
|
||||||
|
trueaudio,
|
||||||
|
wave,
|
||||||
|
)
|
||||||
|
|
||||||
|
from yt_dlp.postprocessor.common import PostProcessor
|
||||||
|
|
||||||
|
|
||||||
|
class MutagenPPError(PostProcessingError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class MutagenPP(PostProcessor):
|
||||||
|
def __init__(self, downloader=None):
|
||||||
|
PostProcessor.__init__(self, downloader)
|
||||||
|
|
||||||
|
class MetadataInfo(TypedDict):
|
||||||
|
title: str | None
|
||||||
|
date: str | None
|
||||||
|
description: str | None
|
||||||
|
synopsis: str | None
|
||||||
|
purl: str | None
|
||||||
|
comment: str | None
|
||||||
|
track: str | None
|
||||||
|
artist: str | None
|
||||||
|
composer: str | None
|
||||||
|
genre: str | None
|
||||||
|
album: str | None
|
||||||
|
album_artist: str | None
|
||||||
|
disc: str | None
|
||||||
|
show: str | None
|
||||||
|
season_number: str | None
|
||||||
|
episode_id: str | None
|
||||||
|
episode_sort: str | None
|
||||||
|
|
||||||
|
if mutagen:
|
||||||
|
@singledispatchmethod
|
||||||
|
@staticmethod
|
||||||
|
def _assemble_metadata(file: FileType, meta: MetadataInfo) -> None:
|
||||||
|
raise MutagenPPError(f'Filetype {file.__class__.__name__} is not currently supported')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_metadata(file: FileType, meta: MetadataInfo, file_name: str, meta_name: str):
|
||||||
|
if meta[meta_name]:
|
||||||
|
file[file_name] = meta[meta_name]
|
||||||
|
|
||||||
|
@_assemble_metadata.register(oggvorbis.OggVorbis)
|
||||||
|
@_assemble_metadata.register(oggtheora.OggTheora)
|
||||||
|
@_assemble_metadata.register(oggspeex.OggSpeex)
|
||||||
|
@_assemble_metadata.register(oggopus.OggOpus)
|
||||||
|
@_assemble_metadata.register(flac.FLAC)
|
||||||
|
@staticmethod
|
||||||
|
def _(file: oggopus.OggOpus, meta: MetadataInfo) -> None:
|
||||||
|
MutagenPP._set_metadata(file, meta, 'artist', 'artist')
|
||||||
|
MutagenPP._set_metadata(file, meta, 'title', 'title')
|
||||||
|
MutagenPP._set_metadata(file, meta, 'genre', 'genre')
|
||||||
|
MutagenPP._set_metadata(file, meta, 'date', 'date')
|
||||||
|
MutagenPP._set_metadata(file, meta, 'album', 'album')
|
||||||
|
MutagenPP._set_metadata(file, meta, 'albumartist', 'album_artist')
|
||||||
|
MutagenPP._set_metadata(file, meta, 'description', 'description')
|
||||||
|
MutagenPP._set_metadata(file, meta, 'comment', 'comment')
|
||||||
|
MutagenPP._set_metadata(file, meta, 'composer', 'composer')
|
||||||
|
MutagenPP._set_metadata(file, meta, 'tracknumber', 'track')
|
||||||
|
|
||||||
|
# https://getmusicbee.com/forum/index.php?topic=39759.0
|
||||||
|
MutagenPP._set_metadata(file, meta, 'WWWAUDIOFILE', 'purl')
|
||||||
|
|
||||||
|
@_assemble_metadata.register(trueaudio.TrueAudio)
|
||||||
|
@_assemble_metadata.register(dsf.DSF)
|
||||||
|
@_assemble_metadata.register(dsdiff.DSDIFF)
|
||||||
|
@_assemble_metadata.register(aiff.AIFF)
|
||||||
|
@_assemble_metadata.register(mp3.MP3)
|
||||||
|
@_assemble_metadata.register(wave.WAVE)
|
||||||
|
@staticmethod
|
||||||
|
def _(file: wave.WAVE, meta: MetadataInfo) -> None:
|
||||||
|
|
||||||
|
def _set_metadata(file_name: str, meta_name: str):
|
||||||
|
if meta[meta_name]:
|
||||||
|
id3_class = getattr(id3, file_name)
|
||||||
|
file[file_name] = id3_class(encoding=id3.Encoding.UTF8, text=meta[meta_name])
|
||||||
|
|
||||||
|
_set_metadata('TIT2', 'title')
|
||||||
|
_set_metadata('TPE1', 'artist')
|
||||||
|
_set_metadata('COMM', 'description')
|
||||||
|
_set_metadata('TCON', 'genre')
|
||||||
|
_set_metadata('WFED', 'purl')
|
||||||
|
_set_metadata('WOAF', 'purl')
|
||||||
|
_set_metadata('TDAT', 'date')
|
||||||
|
_set_metadata('TALB', 'album')
|
||||||
|
_set_metadata('TPE2', 'album_artist')
|
||||||
|
_set_metadata('TRCK', 'track')
|
||||||
|
_set_metadata('TCOM', 'composer')
|
||||||
|
_set_metadata('TPOS', 'disc')
|
||||||
|
|
||||||
|
@_assemble_metadata.register(mp4.MP4)
|
||||||
|
@staticmethod
|
||||||
|
def _(file: mp4.MP4, meta: MetadataInfo) -> None:
|
||||||
|
MutagenPP._set_metadata(file, meta, '\251ART', 'artist')
|
||||||
|
MutagenPP._set_metadata(file, meta, '\251nam', 'title')
|
||||||
|
MutagenPP._set_metadata(file, meta, '\251gen', 'genre')
|
||||||
|
MutagenPP._set_metadata(file, meta, '\251day', 'date')
|
||||||
|
MutagenPP._set_metadata(file, meta, '\251alb', 'album')
|
||||||
|
MutagenPP._set_metadata(file, meta, 'aART', 'album_artist')
|
||||||
|
MutagenPP._set_metadata(file, meta, '\251cmt', 'description')
|
||||||
|
MutagenPP._set_metadata(file, meta, '\251wrt', 'composer')
|
||||||
|
MutagenPP._set_metadata(file, meta, 'disk', 'disc')
|
||||||
|
MutagenPP._set_metadata(file, meta, 'tvsh', 'show')
|
||||||
|
MutagenPP._set_metadata(file, meta, 'tvsn', 'season_number')
|
||||||
|
MutagenPP._set_metadata(file, meta, 'egid', 'episode_id')
|
||||||
|
MutagenPP._set_metadata(file, meta, 'tven', 'episode_sort')
|
||||||
|
|
||||||
|
if meta['purl']:
|
||||||
|
# https://getmusicbee.com/forum/index.php?topic=39759.0
|
||||||
|
file['----:com.apple.iTunes:WWWAUDIOFILE'] = meta['purl'].encode()
|
||||||
|
file['purl'] = meta['purl'].encode()
|
||||||
|
|
||||||
|
if meta['track']:
|
||||||
|
file['trkn'] = [(meta['track'], 0)]
|
||||||
|
|
||||||
|
def _get_metadata_from_info(self, info) -> MetadataInfo:
|
||||||
|
meta_prefix = 'meta'
|
||||||
|
metadata: dict[str, self.MetadataInfo] = collections.defaultdict(
|
||||||
|
lambda: collections.defaultdict(lambda: None),
|
||||||
|
)
|
||||||
|
|
||||||
|
def add(meta_list, info_list=None):
|
||||||
|
value = next((
|
||||||
|
info[key] for key in [f'{meta_prefix}_', *variadic(info_list or meta_list)]
|
||||||
|
if info.get(key) is not None), None)
|
||||||
|
if value not in ('', None):
|
||||||
|
value = ', '.join(map(str, variadic(value)))
|
||||||
|
value = value.replace('\0', '') # nul character cannot be passed in command line
|
||||||
|
metadata['common'].update({meta_f: value for meta_f in variadic(meta_list)})
|
||||||
|
|
||||||
|
add('title', ('track', 'title'))
|
||||||
|
add('date', 'upload_date')
|
||||||
|
add(('description', 'synopsis'), 'description')
|
||||||
|
add(('purl', 'comment'), 'webpage_url')
|
||||||
|
add('track', 'track_number')
|
||||||
|
add('artist', ('artist', 'artists', 'creator', 'creators', 'uploader', 'uploader_id'))
|
||||||
|
add('composer', ('composer', 'composers'))
|
||||||
|
add('genre', ('genre', 'genres'))
|
||||||
|
add('album')
|
||||||
|
add('album_artist', ('album_artist', 'album_artists'))
|
||||||
|
add('disc', 'disc_number')
|
||||||
|
add('show', 'series')
|
||||||
|
add('season_number')
|
||||||
|
add('episode_id', ('episode', 'episode_id'))
|
||||||
|
add('episode_sort', 'episode_number')
|
||||||
|
if 'embed-metadata' in self.get_param('compat_opts', []):
|
||||||
|
add('comment', 'description')
|
||||||
|
metadata['common'].pop('synopsis', None)
|
||||||
|
|
||||||
|
meta_regex = rf'{re.escape(meta_prefix)}(?P<i>\d+)?_(?P<key>.+)'
|
||||||
|
for key, value in info.items():
|
||||||
|
mobj = re.fullmatch(meta_regex, key)
|
||||||
|
if value is not None and mobj:
|
||||||
|
metadata[mobj.group('i') or 'common'][mobj.group('key')] = value.replace('\0', '')
|
||||||
|
|
||||||
|
return metadata['common']
|
||||||
|
|
||||||
|
@PostProcessor._restrict_to(video=False, images=False)
|
||||||
|
def run(self, info):
|
||||||
|
if not mutagen:
|
||||||
|
raise MutagenPPError('module mutagen was not found. Please install using `python3 -m pip install mutagen`')
|
||||||
|
filename = info['filepath']
|
||||||
|
metadata = self._get_metadata_from_info(info)
|
||||||
|
if not metadata:
|
||||||
|
self.to_screen('There isn\'t any metadata to add')
|
||||||
|
return [], info
|
||||||
|
|
||||||
|
self.to_screen(f'Adding metadata to "{filename}"')
|
||||||
|
try:
|
||||||
|
f = mutagen.File(filename)
|
||||||
|
metadata = self._get_metadata_from_info(info)
|
||||||
|
self._assemble_metadata(f, metadata)
|
||||||
|
f.save()
|
||||||
|
except Exception as err:
|
||||||
|
raise MutagenPPError(f'Unable to embed metadata; {err}')
|
||||||
|
|
||||||
|
return [], info
|
||||||
Loading…
x
Reference in New Issue
Block a user