[FEATURE] Simplify `video_tags` (#661)
* [FEATURE] Simplify ``video_tags`` * video tags old * change for episode * deprecation notice
This commit is contained in:
parent
cc38db9c7a
commit
77487aee86
5 changed files with 98 additions and 21 deletions
|
|
@ -248,8 +248,6 @@ subtitles
|
||||||
video_tags
|
video_tags
|
||||||
''''''''''
|
''''''''''
|
||||||
.. autoclass:: ytdl_sub.plugins.video_tags.VideoTagsOptions()
|
.. autoclass:: ytdl_sub.plugins.video_tags.VideoTagsOptions()
|
||||||
:members:
|
|
||||||
:exclude-members: partial_validate
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ July 2023
|
||||||
music_tags
|
music_tags
|
||||||
^^^^^^^^^^
|
^^^^^^^^^^
|
||||||
|
|
||||||
Music tags is getting simplified. ``tags`` will now reside directly under music_tags, and
|
Music tags are getting simplified. ``tags`` will now reside directly under music_tags, and
|
||||||
``embed_thumbnail`` is getting moved to its own plugin (supports video files as well). Convert from:
|
``embed_thumbnail`` is getting moved to its own plugin (supports video files as well). Convert from:
|
||||||
|
|
||||||
.. code-block:: yaml
|
.. code-block:: yaml
|
||||||
|
|
@ -28,3 +28,24 @@ To the following:
|
||||||
artist: "Elvis Presley"
|
artist: "Elvis Presley"
|
||||||
|
|
||||||
The old format will be removed in October 2023.
|
The old format will be removed in October 2023.
|
||||||
|
|
||||||
|
video_tags
|
||||||
|
^^^^^^^^^^
|
||||||
|
|
||||||
|
Video tags are getting simplified as well. ``tags`` will now reside directly under video_tags.
|
||||||
|
Convert from:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
my_example_preset:
|
||||||
|
video_tags:
|
||||||
|
tags:
|
||||||
|
title: "Elvis Presley Documentary"
|
||||||
|
|
||||||
|
To the following:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
my_example_preset:
|
||||||
|
video_tags:
|
||||||
|
title: "Elvis Presley Documentary"
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import copy
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
|
|
@ -6,8 +7,11 @@ from ytdl_sub.entries.entry import Entry
|
||||||
from ytdl_sub.plugins.plugin import Plugin
|
from ytdl_sub.plugins.plugin import Plugin
|
||||||
from ytdl_sub.utils.ffmpeg import add_ffmpeg_metadata_key_values
|
from ytdl_sub.utils.ffmpeg import add_ffmpeg_metadata_key_values
|
||||||
from ytdl_sub.utils.file_handler import FileMetadata
|
from ytdl_sub.utils.file_handler import FileMetadata
|
||||||
|
from ytdl_sub.utils.logger import Logger
|
||||||
from ytdl_sub.validators.string_formatter_validators import DictFormatterValidator
|
from ytdl_sub.validators.string_formatter_validators import DictFormatterValidator
|
||||||
|
|
||||||
|
logger = Logger.get("video_tags")
|
||||||
|
|
||||||
|
|
||||||
class VideoTagsOptions(OptionsDictValidator):
|
class VideoTagsOptions(OptionsDictValidator):
|
||||||
"""
|
"""
|
||||||
|
|
@ -20,13 +24,13 @@ class VideoTagsOptions(OptionsDictValidator):
|
||||||
presets:
|
presets:
|
||||||
my_example_preset:
|
my_example_preset:
|
||||||
video_tags:
|
video_tags:
|
||||||
tags:
|
title: "{title}"
|
||||||
title: "{title}"
|
date: "{upload_date}"
|
||||||
date: "{upload_date}"
|
description: "{description}"
|
||||||
description: "{description}"
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_required_keys = {"tags"}
|
_optional_keys = {"tags"}
|
||||||
|
_allow_extra_keys = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def partial_validate(cls, name: str, value: Any) -> None:
|
def partial_validate(cls, name: str, value: Any) -> None:
|
||||||
|
|
@ -39,7 +43,12 @@ class VideoTagsOptions(OptionsDictValidator):
|
||||||
|
|
||||||
def __init__(self, name, value):
|
def __init__(self, name, value):
|
||||||
super().__init__(name, value)
|
super().__init__(name, value)
|
||||||
self._tags = self._validate_key(key="tags", validator=DictFormatterValidator)
|
|
||||||
|
new_tags_dict: Dict[str, Any] = copy.deepcopy(value)
|
||||||
|
old_tags_dict = new_tags_dict.pop("tags", {})
|
||||||
|
|
||||||
|
self._is_old_format = len(old_tags_dict) > 0
|
||||||
|
self._tags = DictFormatterValidator(name=name, value=dict(old_tags_dict, **new_tags_dict))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tags(self) -> DictFormatterValidator:
|
def tags(self) -> DictFormatterValidator:
|
||||||
|
|
@ -56,6 +65,13 @@ class VideoTagsPlugin(Plugin[VideoTagsOptions]):
|
||||||
"""
|
"""
|
||||||
Tags the entry's audio file using values defined in the metadata options
|
Tags the entry's audio file using values defined in the metadata options
|
||||||
"""
|
"""
|
||||||
|
# pylint: disable=protected-access
|
||||||
|
if self.plugin_options._is_old_format:
|
||||||
|
logger.warning(
|
||||||
|
"video_tags.tags is now deprecated. Place your tags directly under video_tags "
|
||||||
|
"instead. The old format will be removed in October of 2023."
|
||||||
|
)
|
||||||
|
|
||||||
tags_to_write: Dict[str, str] = {}
|
tags_to_write: Dict[str, str] = {}
|
||||||
for tag_name, tag_formatter in self.plugin_options.tags.dict.items():
|
for tag_name, tag_formatter in self.plugin_options.tags.dict.items():
|
||||||
tag_value = self.overrides.apply_formatter(formatter=tag_formatter, entry=entry)
|
tag_value = self.overrides.apply_formatter(formatter=tag_formatter, entry=entry)
|
||||||
|
|
|
||||||
|
|
@ -38,15 +38,14 @@ presets:
|
||||||
|
|
||||||
_episode_video_tags:
|
_episode_video_tags:
|
||||||
video_tags:
|
video_tags:
|
||||||
tags:
|
show: "{tv_show_name}"
|
||||||
show: "{tv_show_name}"
|
genre: "{tv_show_genre}"
|
||||||
genre: "{tv_show_genre}"
|
episode_id: "{episode_number}"
|
||||||
episode_id: "{episode_number}"
|
title: "{episode_title}"
|
||||||
title: "{episode_title}"
|
synopsis: "{episode_plot}"
|
||||||
synopsis: "{episode_plot}"
|
year: "{episode_year}"
|
||||||
year: "{episode_year}"
|
date: "{episode_date_standardized}"
|
||||||
date: "{episode_date_standardized}"
|
contentRating: "{episode_content_rating}"
|
||||||
contentRating: "{episode_content_rating}"
|
|
||||||
|
|
||||||
_episode_nfo_tags:
|
_episode_nfo_tags:
|
||||||
nfo_tags:
|
nfo_tags:
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,32 @@ from expected_transaction_log import assert_transaction_log_matches
|
||||||
from ytdl_sub.subscriptions.subscription import Subscription
|
from ytdl_sub.subscriptions.subscription import Subscription
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def single_video_preset_dict_old_video_tags_format(output_directory):
|
||||||
|
return {
|
||||||
|
"preset": "music_video",
|
||||||
|
"download": {"url": "https://youtube.com/watch?v=HKTNxEqsN3Q"},
|
||||||
|
# override the output directory with our fixture-generated dir
|
||||||
|
"output_options": {
|
||||||
|
"output_directory": output_directory,
|
||||||
|
"maintain_download_archive": False,
|
||||||
|
},
|
||||||
|
# embed thumb into the video
|
||||||
|
"embed_thumbnail": True,
|
||||||
|
# download the worst format so it is fast
|
||||||
|
"ytdl_options": {
|
||||||
|
"format": "worst[ext=mp4]",
|
||||||
|
},
|
||||||
|
# also test video tags
|
||||||
|
"video_tags": {
|
||||||
|
"tags": {
|
||||||
|
"title": "{title}",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": {"artist": "JMC"},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def single_video_preset_dict(output_directory):
|
def single_video_preset_dict(output_directory):
|
||||||
return {
|
return {
|
||||||
|
|
@ -25,9 +51,7 @@ def single_video_preset_dict(output_directory):
|
||||||
},
|
},
|
||||||
# also test video tags
|
# also test video tags
|
||||||
"video_tags": {
|
"video_tags": {
|
||||||
"tags": {
|
"title": "{title}",
|
||||||
"title": "{title}",
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"overrides": {"artist": "JMC"},
|
"overrides": {"artist": "JMC"},
|
||||||
}
|
}
|
||||||
|
|
@ -71,6 +95,25 @@ def single_video_preset_dict_dl_args(single_video_preset_dict):
|
||||||
|
|
||||||
|
|
||||||
class TestYoutubeVideo:
|
class TestYoutubeVideo:
|
||||||
|
def test_single_video_old_video_tags_format_download(
|
||||||
|
self,
|
||||||
|
music_video_config,
|
||||||
|
single_video_preset_dict_old_video_tags_format,
|
||||||
|
output_directory,
|
||||||
|
):
|
||||||
|
single_video_subscription = Subscription.from_dict(
|
||||||
|
config=music_video_config,
|
||||||
|
preset_name="music_video_single_video_test",
|
||||||
|
preset_dict=single_video_preset_dict_old_video_tags_format,
|
||||||
|
)
|
||||||
|
|
||||||
|
transaction_log = single_video_subscription.download(dry_run=True)
|
||||||
|
assert_transaction_log_matches(
|
||||||
|
output_directory=output_directory,
|
||||||
|
transaction_log=transaction_log,
|
||||||
|
transaction_log_summary_file_name="youtube/test_video.txt",
|
||||||
|
)
|
||||||
|
|
||||||
@pytest.mark.parametrize("dry_run", [True, False])
|
@pytest.mark.parametrize("dry_run", [True, False])
|
||||||
def test_single_video_download(
|
def test_single_video_download(
|
||||||
self,
|
self,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue