more docs
This commit is contained in:
parent
f67a4dc7dc
commit
87dfe3dbfe
7 changed files with 230 additions and 106 deletions
10
README.md
10
README.md
|
|
@ -8,18 +8,18 @@
|
|||
|
||||
Automate downloading and adding metadata with YoutubeDL.
|
||||
|
||||
This package strives to download media via
|
||||
This package downloads media via
|
||||
[yt-dlp](https://github.com/yt-dlp/yt-dlp)
|
||||
and prepare it for consumption in your favorite media player
|
||||
and prepares it for consumption in your favorite media player
|
||||
([Kodi](https://github.com/xbmc/xbmc),
|
||||
[Jellyfin](https://github.com/jellyfin/jellyfin),
|
||||
[Plex](https://github.com/plexinc/pms-docker),
|
||||
[Emby](https://github.com/plexinc/pms-docker),
|
||||
modern music players)
|
||||
in the most hassle-free way possible. We recognize that everyone stores their
|
||||
modern music players).
|
||||
We recognize that everyone stores their
|
||||
media differently. Our approach for file and metadata formatting is to provide
|
||||
maximum flexibility while maintaining simplicity. Read more about it
|
||||
[here](https://ytdl-sub.readthedocs.io/en/latest/).
|
||||
[here](https://ytdl-sub.readthedocs.io/en/latest/getting_started.html).
|
||||
|
||||
## Supported Features
|
||||
Below lists supported download schemes. You can see our
|
||||
|
|
|
|||
110
docs/config.rst
110
docs/config.rst
|
|
@ -30,112 +30,60 @@ download strategy has its own set of parameters.
|
|||
|
||||
youtube
|
||||
"""""""
|
||||
Download strategies for downloading videos (or audio if you configure `ytdl_options`_ correctly) from Youtube. See
|
||||
Download strategies for downloading music from Soundcloud. See
|
||||
:class:`Youtube Variables <ytdl_sub.entries.variables.youtube_variables>`
|
||||
for available source variables to use.
|
||||
|
||||
channel
|
||||
'''''''
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
youtube:
|
||||
download_strategy: "channel"
|
||||
|
||||
channel_id
|
||||
__________
|
||||
.. autoproperty:: ytdl_sub.downloaders.youtube_downloader.YoutubeChannelDownloaderOptions.channel_id
|
||||
|
||||
channel_avatar_path
|
||||
___________________
|
||||
.. autoproperty:: ytdl_sub.downloaders.youtube_downloader.YoutubeChannelDownloaderOptions.channel_avatar_path
|
||||
|
||||
channel_banner_path
|
||||
___________________
|
||||
.. autoproperty:: ytdl_sub.downloaders.youtube_downloader.YoutubeChannelDownloaderOptions.channel_banner_path
|
||||
|
||||
before
|
||||
______
|
||||
.. autoproperty:: ytdl_sub.downloaders.youtube_downloader.YoutubeChannelDownloaderOptions.before
|
||||
|
||||
after
|
||||
_____
|
||||
.. autoproperty:: ytdl_sub.downloaders.youtube_downloader.YoutubeChannelDownloaderOptions.after
|
||||
.. autoclass:: ytdl_sub.downloaders.youtube_downloader.YoutubeChannelDownloaderOptions()
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:inherited-members:
|
||||
:exclude-members: get_date_range
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
playlist
|
||||
''''''''
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
youtube:
|
||||
download_strategy: "playlist"
|
||||
|
||||
playlist_id
|
||||
___________
|
||||
.. autoproperty:: ytdl_sub.downloaders.youtube_downloader.YoutubePlaylistDownloaderOptions.playlist_id
|
||||
.. autoclass:: ytdl_sub.downloaders.youtube_downloader.YoutubePlaylistDownloaderOptions()
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:inherited-members:
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
video
|
||||
'''''
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
youtube:
|
||||
download_strategy: "video"
|
||||
|
||||
video_id
|
||||
________
|
||||
.. autoproperty:: ytdl_sub.downloaders.youtube_downloader.YoutubeVideoDownloaderOptions.video_id
|
||||
.. autoclass:: ytdl_sub.downloaders.youtube_downloader.YoutubeVideoDownloaderOptions()
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:inherited-members:
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
soundcloud
|
||||
""""""""""
|
||||
Download strategies for downloading music from Soundcloud. See
|
||||
:class:`Soundcloud Variables <ytdl_sub.entries.variables.soundcloud_variables>`
|
||||
for available source variables to use.
|
||||
|
||||
albums_and_singles
|
||||
''''''''''''''''''
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
soundcloud:
|
||||
download_strategy: "albums_and_singles"
|
||||
|
||||
username
|
||||
________
|
||||
.. autoproperty:: ytdl_sub.downloaders.soundcloud_downloader.SoundcloudAlbumsAndSinglesDownloadOptions.username
|
||||
|
||||
skip_premiere_tracks
|
||||
____________________
|
||||
.. autoproperty:: ytdl_sub.downloaders.soundcloud_downloader.SoundcloudAlbumsAndSinglesDownloadOptions.skip_premiere_tracks
|
||||
.. autoclass:: ytdl_sub.downloaders.soundcloud_downloader.SoundcloudAlbumsAndSinglesDownloadOptions()
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:inherited-members:
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
output_options
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
output_directory
|
||||
""""""""""""""""
|
||||
.. autoproperty:: ytdl_sub.config.preset_options.OutputOptions.output_directory
|
||||
|
||||
file_name
|
||||
"""""""""
|
||||
.. autoproperty:: ytdl_sub.config.preset_options.OutputOptions.file_name
|
||||
|
||||
thumbnail_name
|
||||
""""""""""""""
|
||||
.. autoproperty:: ytdl_sub.config.preset_options.OutputOptions.thumbnail_name
|
||||
|
||||
maintain_download_archive
|
||||
"""""""""""""""""""""""""
|
||||
.. autoproperty:: ytdl_sub.config.preset_options.OutputOptions.maintain_download_archive
|
||||
|
||||
keep_files
|
||||
""""""""""
|
||||
.. autoproperty:: ytdl_sub.config.preset_options.OutputOptions.keep_files
|
||||
.. autoclass:: ytdl_sub.config.preset_options.OutputOptions()
|
||||
:members:
|
||||
:member-order: bysource
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -151,14 +99,18 @@ overrides
|
|||
|
||||
Plugins
|
||||
^^^^^^^
|
||||
Plugins are used to perform any type of post-processing to the already downloaded files.
|
||||
|
||||
music_tags
|
||||
""""""""""
|
||||
.. autoclass:: ytdl_sub.plugins.music_tags.MusicTagsOptions()
|
||||
:members:
|
||||
|
||||
nfo
|
||||
"""
|
||||
.. autoclass:: ytdl_sub.plugins.nfo_tags.NfoTagsOptions()
|
||||
:members:
|
||||
:member-order: bysource
|
||||
|
||||
nfo_output_directory
|
||||
""""""""""""""""""""
|
||||
|
|
|
|||
|
|
@ -86,7 +86,26 @@ class Overrides(DictFormatterValidator):
|
|||
|
||||
|
||||
class OutputOptions(StrictDictValidator):
|
||||
"""Where to output the final files and thumbnails"""
|
||||
"""
|
||||
Defines where to output files and thumbnails after all post-processing has completed.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
output_options:
|
||||
# required
|
||||
output_directory: "/path/to/videos_or_music"
|
||||
file_name: "{sanitized_title}.{ext}"
|
||||
# optional
|
||||
thumbnail_name: "{sanitized_title}.{thumbnail_ext}"
|
||||
maintain_download_archive: True
|
||||
keep_files:
|
||||
before: now
|
||||
after: today-2weeks
|
||||
"""
|
||||
|
||||
_required_keys = {"output_directory", "file_name"}
|
||||
_optional_keys = {
|
||||
|
|
@ -168,19 +187,8 @@ class OutputOptions(StrictDictValidator):
|
|||
"""
|
||||
Optional. Requires ``maintain_download_archive`` set to True.
|
||||
|
||||
Only keeps files that are uploaded in the defined range. Should be formatted as:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
output_options:
|
||||
keep_files:
|
||||
before:
|
||||
after:
|
||||
|
||||
where ``before`` and ``after`` are date-times. A common usage of this option is to only
|
||||
fill in the after, such as:
|
||||
Only keeps files that are uploaded in the defined range. ``before`` and ``after`` are
|
||||
date-times. A common usage of this option is to only fill in the after, such as:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
|
|
|
|||
|
|
@ -71,6 +71,25 @@ class SoundcloudDownloader(
|
|||
|
||||
|
||||
class SoundcloudAlbumsAndSinglesDownloadOptions(SoundcloudDownloaderOptions):
|
||||
"""
|
||||
Downloads a soundcloud user's entire discography. Groups together album tracks and considers
|
||||
any track not in an album as a single. Also includes any collaboration tracks.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
soundcloud:
|
||||
# required
|
||||
download_strategy: "albums_and_singles"
|
||||
username: soundcloud_username_from_url
|
||||
# optional
|
||||
skip_premiere_tracks: True
|
||||
|
||||
"""
|
||||
|
||||
_required_keys = {"username"}
|
||||
|
||||
def __init__(self, name, value):
|
||||
|
|
|
|||
|
|
@ -55,6 +55,29 @@ class YoutubeDownloader(
|
|||
|
||||
|
||||
class YoutubeVideoDownloaderOptions(YoutubeDownloaderOptions):
|
||||
"""
|
||||
Downloads a single youtube video. This download strategy is intended for CLI usage performing
|
||||
a one-time download of a video, not a subscription.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
youtube:
|
||||
# required
|
||||
download_strategy: "video"
|
||||
video_id: "VMAPTo7RVDo"
|
||||
|
||||
CLI usage:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
ytdl-sub dl --preset "my_example_preset" --youtube.video_id "VMAPTo7RVDo"
|
||||
|
||||
"""
|
||||
|
||||
_required_keys = {"video_id"}
|
||||
|
||||
def __init__(self, name, value):
|
||||
|
|
@ -64,7 +87,7 @@ class YoutubeVideoDownloaderOptions(YoutubeDownloaderOptions):
|
|||
@property
|
||||
def video_id(self) -> str:
|
||||
"""
|
||||
Required. The ID of the video. Looks like the ``VMAPTo7RVDo`` in
|
||||
Required. The ID of the video. Looks like the ``VMAPTo7RVDo`` from
|
||||
``youtube.com/watch?v=VMAPTo7RVDo``.
|
||||
"""
|
||||
return self._video_id.value
|
||||
|
|
@ -92,6 +115,21 @@ class YoutubeVideoDownloader(YoutubeDownloader[YoutubeVideoDownloaderOptions, Yo
|
|||
|
||||
|
||||
class YoutubePlaylistDownloaderOptions(YoutubeDownloaderOptions):
|
||||
"""
|
||||
Downloads all videos from a youtube playlist.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
youtube:
|
||||
# required
|
||||
download_strategy: "playlist"
|
||||
playlist_id: "UCsvn_Po0SmunchJYtttWpOxMg"
|
||||
"""
|
||||
|
||||
_required_keys = {"playlist_id"}
|
||||
|
||||
def __init__(self, name, value):
|
||||
|
|
@ -101,7 +139,8 @@ class YoutubePlaylistDownloaderOptions(YoutubeDownloaderOptions):
|
|||
@property
|
||||
def playlist_id(self) -> str:
|
||||
"""
|
||||
Required. The playlist's ID.
|
||||
Required. The playlist's ID. Looks like "UCsvn_Po0SmunchJYtttWpOxMg"
|
||||
from ``https://www.youtube.com/playlist?list=UCsvn_Po0SmunchJYtttWpOxMg``.
|
||||
"""
|
||||
return self._playlist_id.value
|
||||
|
||||
|
|
@ -141,6 +180,26 @@ class YoutubePlaylistDownloader(
|
|||
|
||||
|
||||
class YoutubeChannelDownloaderOptions(YoutubeDownloaderOptions, DateRangeValidator):
|
||||
"""
|
||||
Downloads all videos from a youtube channel.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
youtube:
|
||||
# required
|
||||
download_strategy: "channel"
|
||||
channel_id: "UCsvn_Po0SmunchJYtttWpOxMg"
|
||||
# optional
|
||||
channel_avatar_path: "poster.jpg"
|
||||
channel_banner_path: "fanart.jpg"
|
||||
before: "now"
|
||||
after: "today-2weeks"
|
||||
"""
|
||||
|
||||
_required_keys = {"channel_id"}
|
||||
_optional_keys = {"before", "after", "channel_avatar_path", "channel_banner_path"}
|
||||
|
||||
|
|
@ -159,8 +218,10 @@ class YoutubeChannelDownloaderOptions(YoutubeDownloaderOptions, DateRangeValidat
|
|||
def channel_id(self) -> str:
|
||||
"""
|
||||
Required. The channel's ID. Not to be confused with the username. It should look something
|
||||
like `UCsvn_Po0SmunchJYOWpOxMg`. You can get this by opening a video and clicking on the
|
||||
channel's avatar image to take you to their channel, then check the url.
|
||||
like ``UCsvn_Po0SmunchJYOWpOxMg`` from
|
||||
``https://www.youtube.com/channel/UCsvn_Po0SmunchJYOWpOxMg``. You can get this by opening a
|
||||
video and clicking on the channel's avatar image to take you to their channel, then check
|
||||
the url.
|
||||
"""
|
||||
return self._channel_id.value
|
||||
|
||||
|
|
|
|||
|
|
@ -8,18 +8,47 @@ from ytdl_sub.validators.validators import StringValidator
|
|||
|
||||
|
||||
class MusicTagsOptions(PluginOptions):
|
||||
"""
|
||||
Adds tags to every download audio file using
|
||||
`MediaFile <https://mediafile.readthedocs.io/en/latest/>`_,
|
||||
the same audio file tagging package used by
|
||||
`beets <https://beets.readthedocs.io/en/stable/>`_.
|
||||
It supports basic tags like ``title``, ``album``, ``artist`` and ``albumartist``. You can find
|
||||
a full list of tags for various file types in MediaFile's
|
||||
`source code <https://github.com/beetbox/mediafile/blob/v0.9.0/mediafile.py#L1770>`_.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
music_tags:
|
||||
tags:
|
||||
artist: "{artist}"
|
||||
album: "{album}"
|
||||
genre: "ytdl downloaded music"
|
||||
"""
|
||||
|
||||
_required_keys = {"tags"}
|
||||
_optional_keys = {"multi_value_separator"}
|
||||
|
||||
def __init__(self, name, value):
|
||||
super().__init__(name, value)
|
||||
|
||||
self.tags = self._validate_key(key="tags", validator=DictFormatterValidator)
|
||||
self._tags = self._validate_key(key="tags", validator=DictFormatterValidator)
|
||||
|
||||
self.multi_value_separator = self._validate_key_if_present(
|
||||
key="multi_value_separator", validator=StringValidator
|
||||
)
|
||||
|
||||
@property
|
||||
def tags(self) -> DictFormatterValidator:
|
||||
"""
|
||||
Key/values of tag names/tag values. Supports source and override variables.
|
||||
"""
|
||||
return self._tags
|
||||
|
||||
|
||||
class MusicTagsPlugin(Plugin[MusicTagsOptions]):
|
||||
plugin_options_type = MusicTagsOptions
|
||||
|
|
|
|||
|
|
@ -11,14 +11,69 @@ from ytdl_sub.validators.string_formatter_validators import StringFormatterValid
|
|||
|
||||
|
||||
class NfoTagsOptions(PluginOptions):
|
||||
"""
|
||||
Adds an NFO file for every download file. An NFO file is simply an XML file
|
||||
with a ``.nfo`` extension. You can add any values into the NFO.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
nfo:
|
||||
nfo_name: "{sanitized_title}.nfo"
|
||||
nfo_root: "episodedetails"
|
||||
tags:
|
||||
title: "{title}"
|
||||
season: "{upload_year}"
|
||||
episode: "{upload_month}{upload_day_padded}"
|
||||
"""
|
||||
|
||||
_required_keys = {"nfo_name", "nfo_root", "tags"}
|
||||
|
||||
def __init__(self, name, value):
|
||||
super().__init__(name, value)
|
||||
|
||||
self.nfo_name = self._validate_key(key="nfo_name", validator=StringFormatterValidator)
|
||||
self.nfo_root = self._validate_key(key="nfo_root", validator=StringFormatterValidator)
|
||||
self.tags = self._validate_key(key="tags", validator=DictFormatterValidator)
|
||||
self._nfo_name = self._validate_key(key="nfo_name", validator=StringFormatterValidator)
|
||||
self._nfo_root = self._validate_key(key="nfo_root", validator=StringFormatterValidator)
|
||||
self._tags = self._validate_key(key="tags", validator=DictFormatterValidator)
|
||||
|
||||
@property
|
||||
def nfo_name(self) -> StringFormatterValidator:
|
||||
"""
|
||||
The NFO file name.
|
||||
"""
|
||||
return self._nfo_name
|
||||
|
||||
@property
|
||||
def nfo_root(self) -> StringFormatterValidator:
|
||||
"""
|
||||
The root tag of the NFO's XML. In the usage above, it would look like
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<episodedetails>
|
||||
</episodedetails>
|
||||
"""
|
||||
return self._nfo_root
|
||||
|
||||
@property
|
||||
def tags(self) -> DictFormatterValidator:
|
||||
"""
|
||||
Tags within the nfo_root tag. In the usage above, it would look like
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<episodedetails>
|
||||
<title>Awesome Youtube Video</title>
|
||||
<season>2022</season>
|
||||
<episode>502</episode>
|
||||
</episodedetails>
|
||||
"""
|
||||
return self._tags
|
||||
|
||||
|
||||
class NfoTagsPlugin(Plugin[NfoTagsOptions]):
|
||||
|
|
|
|||
Loading…
Reference in a new issue