more docs

This commit is contained in:
jbannon 2022-05-10 19:53:59 +00:00
parent f67a4dc7dc
commit 87dfe3dbfe
7 changed files with 230 additions and 106 deletions

View file

@ -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

View file

@ -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
""""""""""""""""""""

View file

@ -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

View file

@ -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):

View file

@ -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

View file

@ -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

View file

@ -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]):