[DOCS] Begin complete overhaul of readthedocs (#847)
Readthedocs for ytdl-sub is getting a massive overhaul to both look and read like a modernized app. It is still very-much work-in-progress, stay tuned for more! Huge thanks to @Svagtlys (aka Momo) for driving this
This commit is contained in:
parent
02d51d6aec
commit
008bcf1b2d
49 changed files with 3211 additions and 1059 deletions
|
|
@ -1,16 +1,17 @@
|
|||
version: 2
|
||||
|
||||
build:
|
||||
os: ubuntu-20.04
|
||||
os: "ubuntu-22.04"
|
||||
tools:
|
||||
python: "3.10"
|
||||
|
||||
sphinx:
|
||||
configuration: docs/conf.py
|
||||
configuration: docs/source/conf.py
|
||||
|
||||
python:
|
||||
install:
|
||||
- requirements: docs/source/requirements.txt
|
||||
- method: pip
|
||||
path: .
|
||||
extra_requirements:
|
||||
- docs
|
||||
- docs
|
||||
4
Makefile
4
Makefile
|
|
@ -39,14 +39,14 @@ executable: clean
|
|||
pyinstaller ytdl-sub.spec
|
||||
mv dist/ytdl-sub dist/ytdl-sub${EXEC_SUFFIX}
|
||||
docs:
|
||||
sphinx-build -a -b html docs docs/_html
|
||||
sphinx-build -M html docs/source/ docs/build/
|
||||
clean:
|
||||
rm -rf \
|
||||
.pytest_cache/ \
|
||||
build/ \
|
||||
dist/ \
|
||||
src/ytdl_sub.egg-info/ \
|
||||
docs/_html/ \
|
||||
docs/build/ \
|
||||
.coverage \
|
||||
docker/root/*.whl \
|
||||
docker/root/defaults/examples \
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
# from the environment for the first two.
|
||||
SPHINXOPTS ?=
|
||||
SPHINXBUILD ?= sphinx-build
|
||||
SOURCEDIR = .
|
||||
BUILDDIR = _build
|
||||
SOURCEDIR = source
|
||||
BUILDDIR = build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
|
|
|
|||
67
docs/conf.py
67
docs/conf.py
|
|
@ -1,67 +0,0 @@
|
|||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file only contains a selection of the most common options. For a full
|
||||
# list see the documentation:
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.abspath("../src"))
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = "ytdl-sub"
|
||||
copyright = "2022, Jesse Bannon"
|
||||
author = "Jesse Bannon"
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
"sphinx.ext.autodoc",
|
||||
"sphinx.ext.napoleon",
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ["_templates"]
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
|
||||
html_theme_options = {"navigation_depth": 10}
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
# html_static_path = ["_static"]
|
||||
|
||||
# Do not show full module path in api docs
|
||||
add_module_names = False
|
||||
python_use_unqualified_type_names = False
|
||||
napoleon_numpy_docstrings = True
|
||||
napoleon_use_rtype = False
|
||||
|
||||
# -- Options for autodocs -------------------------------------------------
|
||||
|
||||
autodoc_default_options = {"autodoc_typehints_format": "short"}
|
||||
454
docs/config.rst
454
docs/config.rst
|
|
@ -1,454 +0,0 @@
|
|||
Config
|
||||
======
|
||||
ytdl-sub is configured using a ``config.yaml`` file.
|
||||
|
||||
.. _config:
|
||||
|
||||
config.yaml
|
||||
-----------
|
||||
|
||||
The ``config.yaml`` is made up of two sections:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
configuration:
|
||||
presets:
|
||||
|
||||
You can jump to any section and subsection of the config using the navigation
|
||||
section to the left.
|
||||
|
||||
Note for Windows users, paths can be represented with ``C:/forward/slashes/like/linux``.
|
||||
If you wish to represent paths like Windows, you will need to ``C:\\double\\bashslash\\paths``
|
||||
in order to escape the backslash character.
|
||||
|
||||
configuration
|
||||
^^^^^^^^^^^^^
|
||||
The ``configuration`` section contains app-wide configs applied to all presets
|
||||
and subscriptions.
|
||||
|
||||
.. autoclass:: ytdl_sub.config.config_validator.ConfigOptions()
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:exclude-members: subscription_value, persist_logs, experimental
|
||||
|
||||
persist_logs
|
||||
""""""""""""
|
||||
Within ``configuration``, define whether logs from subscription downloads
|
||||
should be persisted.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
configuration:
|
||||
persist_logs:
|
||||
logs_directory: "/path/to/log/directory"
|
||||
|
||||
Log files are stored as
|
||||
``YYYY-mm-dd-HHMMSS.subscription_name.(success|error).log``.
|
||||
|
||||
.. autoclass:: ytdl_sub.config.config_validator.PersistLogsValidator()
|
||||
:members:
|
||||
:member-order: bysource
|
||||
|
||||
presets
|
||||
^^^^^^^
|
||||
``presets`` define a `formula` for how to format downloaded media and metadata.
|
||||
|
||||
download_strategy
|
||||
"""""""""""""""""
|
||||
Download strategies dictate what is getting downloaded from a source. Each
|
||||
download strategy has its own set of parameters.
|
||||
|
||||
.. _url:
|
||||
|
||||
url
|
||||
'''
|
||||
.. autoclass:: ytdl_sub.downloaders.url.url.UrlDownloadOptions()
|
||||
:members: url, playlist_thumbnails, source_thumbnails, download_reverse
|
||||
:member-order: bysource
|
||||
|
||||
multi_url
|
||||
'''''''''
|
||||
.. autoclass:: ytdl_sub.downloaders.url.multi_url.MultiUrlDownloadOptions()
|
||||
:members: urls, variables
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
output_options
|
||||
""""""""""""""
|
||||
|
||||
.. autoclass:: ytdl_sub.config.preset_options.OutputOptions()
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:exclude-members: get_upload_date_range_to_keep, partial_validate
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
.. _ytdl_options:
|
||||
|
||||
ytdl_options
|
||||
""""""""""""
|
||||
.. autoclass:: ytdl_sub.config.preset_options.YTDLOptions()
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
.. _overrides:
|
||||
|
||||
overrides
|
||||
"""""""""
|
||||
.. autoclass:: ytdl_sub.config.overrides.Overrides()
|
||||
|
||||
.. _parent preset:
|
||||
|
||||
preset
|
||||
""""""
|
||||
Presets support inheritance by defining a parent preset:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
custom_preset:
|
||||
...
|
||||
parent_preset:
|
||||
...
|
||||
child_preset:
|
||||
preset: "parent_preset"
|
||||
|
||||
In the example above, ``child_preset`` inherits all fields defined in ``parent_preset``.
|
||||
It is advantageous to use parent presets where possible to reduce duplicate yaml
|
||||
definitions.
|
||||
|
||||
Presets also support inheritance from multiple presets:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
child_preset:
|
||||
preset:
|
||||
- "custom_preset"
|
||||
- "parent_preset"
|
||||
|
||||
In this example, ``child_preset`` will inherit all fields from ``custom_preset``
|
||||
and ``parent_preset`` in that order. The bottom-most preset has the highest
|
||||
priority.
|
||||
|
||||
If you are only inheriting from one preset, the syntax ``preset: "parent_preset"`` is
|
||||
valid YAML. Inheriting from multiple presets require use of a list.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
Plugins
|
||||
"""""""
|
||||
Plugins are used to perform any type of post-processing to the already downloaded files.
|
||||
|
||||
audio_extract
|
||||
'''''''''''''
|
||||
.. autoclass:: ytdl_sub.plugins.audio_extract.AudioExtractOptions()
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:exclude-members: partial_validate
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
chapters
|
||||
''''''''
|
||||
.. autoclass:: ytdl_sub.plugins.chapters.ChaptersOptions()
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:exclude-members: partial_validate
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
date_range
|
||||
''''''''''
|
||||
.. autoclass:: ytdl_sub.plugins.date_range.DateRangeOptions()
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:exclude-members: partial_validate
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
embed_thumbnail
|
||||
''''''''''''''''
|
||||
|
||||
.. autoclass:: ytdl_sub.plugins.embed_thumbnail.EmbedThumbnailOptions()
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
file_convert
|
||||
''''''''''''
|
||||
.. autoclass:: ytdl_sub.plugins.file_convert.FileConvertOptions()
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:exclude-members: partial_validate
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
format
|
||||
''''''
|
||||
.. autoclass:: ytdl_sub.plugins.format.FormatOptions()
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
match_filters
|
||||
'''''''''''''
|
||||
.. autoclass:: ytdl_sub.plugins.match_filters.MatchFiltersOptions()
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:exclude-members: partial_validate
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
music_tags
|
||||
''''''''''
|
||||
.. autoclass:: ytdl_sub.plugins.music_tags.MusicTagsOptions()
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
nfo_tags
|
||||
''''''''
|
||||
.. autoclass:: ytdl_sub.plugins.nfo_tags.NfoTagsOptions()
|
||||
:members: nfo_name, nfo_root, tags, kodi_safe
|
||||
:member-order: bysource
|
||||
:exclude-members: partial_validate
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
output_directory_nfo_tags
|
||||
'''''''''''''''''''''''''
|
||||
.. autoclass:: ytdl_sub.plugins.output_directory_nfo_tags.OutputDirectoryNfoTagsOptions()
|
||||
:members: nfo_name, nfo_root, tags, kodi_safe
|
||||
:member-order: bysource
|
||||
:exclude-members: partial_validate
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
regex
|
||||
'''''
|
||||
.. autoclass:: ytdl_sub.plugins.regex.RegexOptions()
|
||||
:members: skip_if_match_fails
|
||||
|
||||
.. autoclass:: ytdl_sub.plugins.regex.VariableRegex()
|
||||
:members: match, capture_group_names, capture_group_defaults, exclude
|
||||
:member-order: bysource
|
||||
:exclude-members: partial_validate
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
split_by_chapters
|
||||
'''''''''''''''''
|
||||
.. autoclass:: ytdl_sub.plugins.split_by_chapters.SplitByChaptersOptions()
|
||||
:members: when_no_chapters
|
||||
:member-order: bysource
|
||||
:exclude-members: partial_validate
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
subtitles
|
||||
'''''''''
|
||||
.. autoclass:: ytdl_sub.plugins.subtitles.SubtitleOptions()
|
||||
:members: subtitles_name, subtitles_type, embed_subtitles, languages, allow_auto_generated_subtitles
|
||||
:member-order: bysource
|
||||
:exclude-members: partial_validate
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
throttle_protection
|
||||
'''''''''''''''''''
|
||||
.. autoclass:: ytdl_sub.plugins.throttle_protection.ThrottleProtectionOptions()
|
||||
:members:
|
||||
:member-order: bysource
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
video_tags
|
||||
''''''''''
|
||||
.. autoclass:: ytdl_sub.plugins.video_tags.VideoTagsOptions()
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
.. _subscription_yaml:
|
||||
|
||||
subscription.yaml
|
||||
-----------------
|
||||
The ``subscription.yaml`` file is where we use our `presets`_ in the `config.yaml`_
|
||||
to define a `subscription`: something we want to recurrently download such as a specific
|
||||
channel or playlist.
|
||||
|
||||
The only difference between a ``subscription`` and ``preset`` is that the subscription
|
||||
must have all required fields and ``{variables}`` defined so it can perform a download.
|
||||
|
||||
Below is an example that downloads a YouTube playlist:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: config.yaml
|
||||
|
||||
presets:
|
||||
playlist_preset_ex:
|
||||
download:
|
||||
download_strategy: "url"
|
||||
url: "{url}"
|
||||
output_options:
|
||||
output_directory: "{output_directory}/{playlist_name}"
|
||||
file_name: "{playlist_name}.{title}.{ext}"
|
||||
overrides:
|
||||
output_directory: "/path/to/ytdl-sub-videos"
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: subscription.yaml
|
||||
|
||||
my_subscription_name:
|
||||
preset: "playlist_preset_ex"
|
||||
overrides:
|
||||
playlist_name: "diy-playlist"
|
||||
url: "https://youtube.com/playlist?list=UCsvn_Po0SmunchJYtttWpOxMg"
|
||||
|
||||
Our preset ``playlist_preset_ex`` defines three
|
||||
custom variables: ``{output_directory}``, ``{playlist_name}``, and ``{url}``. The subscription sets
|
||||
the `parent preset`_ to ``playlist_preset_ex``, and must define the variables ``{playlist_name}``
|
||||
and ``{url}`` since the preset did not.
|
||||
|
||||
.. _beautifying subscriptions:
|
||||
|
||||
Beautifying Subscriptions
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Subscriptions support using presets as keys, and using keys to set override variables as values.
|
||||
For example:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: subscription.yaml
|
||||
|
||||
TV Show Full Archive:
|
||||
= News:
|
||||
"Breaking News": "https://www.youtube.com/@SomeBreakingNews"
|
||||
|
||||
TV Show Only Recent:
|
||||
= Tech | TV-Y:
|
||||
"Two Minute Papers": "https://www.youtube.com/@TwoMinutePapers"
|
||||
|
||||
Will create two subscriptions named "Breaking News" and "Two Minute Papers", equivalent to:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
"Breaking News":
|
||||
preset:
|
||||
- "TV Show Full Archive"
|
||||
|
||||
overrides:
|
||||
subscription_indent_1: "News"
|
||||
subscription_name: "Breaking News"
|
||||
subscription_value: "https://www.youtube.com/@SomeBreakingNews"
|
||||
|
||||
"Two Minute Papers":
|
||||
preset:
|
||||
- "TV Show Only Recent"
|
||||
|
||||
overrides:
|
||||
subscription_indent_1: "Tech"
|
||||
subscription_indent_2: "TV-Y"
|
||||
subscription_name: "Two Minute Papers"
|
||||
subscription_value: "https://www.youtube.com/@TwoMinutePapers"
|
||||
|
||||
You can provide as many parent presets in the form of keys, and subscription indents as ``=keys``.
|
||||
This can drastically simplify subscription definitions by setting things like so in your
|
||||
parent preset:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
"TV Show Preset":
|
||||
overrides:
|
||||
subscription_indent_1: "default-genre"
|
||||
subscription_indent_2: "default-content-rating"
|
||||
|
||||
tv_show_name: "{subscription_name}"
|
||||
url: "{subscription_value}"
|
||||
genre: "{subscription_indent_1}"
|
||||
content_rating: "{subscription_indent_2}"
|
||||
|
||||
.. _subscription value:
|
||||
|
||||
File Preset
|
||||
^^^^^^^^^^^
|
||||
NOTE: This is deprecated in favor of using the method in :ref:`beautifying subscriptions`.
|
||||
|
||||
You can apply a preset to all subscriptions in the ``subscription.yaml`` file
|
||||
by using the file-wide ``__preset__``:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: subscription.yaml
|
||||
|
||||
__preset__:
|
||||
preset: "playlist_preset_ex"
|
||||
|
||||
my_subscription_name:
|
||||
overrides:
|
||||
url: "https://youtube.com/playlist?list=UCsvn_Po0SmunchJYtttWpOxMg"
|
||||
playlist_name: "diy-playlist"
|
||||
|
||||
This ``subscription.yaml`` is equivalent to the one above it because all
|
||||
subscriptions automatically set ``__preset__`` as a `parent preset`_.
|
||||
|
||||
|
||||
Subscription Value
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
NOTE: This is deprecated in favor of using the method in :ref:`beautifying subscriptions`.
|
||||
|
||||
With a clever config and use of ``__preset__``, your subscriptions can typically boil
|
||||
down to a name and url. You can set ``__value__`` to the name of an override variable,
|
||||
and use the override variable ``subscription_name`` to achieve one-liner subscriptions.
|
||||
Using the example above, we can do:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: subscription.yaml
|
||||
|
||||
__preset__:
|
||||
preset:
|
||||
- "tv_show"
|
||||
overrides:
|
||||
tv_show_name: "{subscription_name}"
|
||||
|
||||
__value__: "url"
|
||||
|
||||
# single-line subscription, sets "Brandon Acker" and the subscription value
|
||||
# to the override variables tv_show_name and url
|
||||
"Brandon Acker": "https://www.youtube.com/@brandonacker"
|
||||
|
||||
Traditional subscriptions that can override presets will still work when using ``__value__``.
|
||||
``__value__`` can also be set within a :ref:`config`.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
.. _source-variables:
|
||||
|
||||
Source Variables
|
||||
----------------
|
||||
|
||||
.. autoclass:: ytdl_sub.entries.script.variable_definitions.VariableDefinitions()
|
||||
:members:
|
||||
:inherited-members:
|
||||
:undoc-members:
|
||||
|
||||
Override Variables
|
||||
------------------
|
||||
|
||||
.. autoclass:: ytdl_sub.entries.variables.override_variables.OverrideVariables()
|
||||
:members:
|
||||
:member-order: bysource
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Config Types
|
||||
------------
|
||||
The `config.yaml`_ uses various types for its configurable fields. Below is a definition for each type.
|
||||
|
||||
.. autoclass:: ytdl_sub.validators.string_formatter_validators.StringFormatterValidator()
|
||||
|
||||
.. autoclass:: ytdl_sub.validators.string_formatter_validators.OverridesStringFormatterValidator()
|
||||
|
||||
.. autoclass:: ytdl_sub.validators.file_path_validators.StringFormatterFileNameValidator()
|
||||
|
||||
.. autoclass:: ytdl_sub.validators.string_datetime.StringDatetimeValidator()
|
||||
|
||||
.. autoclass:: ytdl_sub.validators.string_formatter_validators.DictFormatterValidator()
|
||||
|
||||
.. autoclass:: ytdl_sub.validators.string_formatter_validators.OverridesDictFormatterValidator()
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
Getting Started
|
||||
===============
|
||||
|
||||
Walk-through Guide
|
||||
-------------------
|
||||
If you haven't read it yet, it's highly recommended to go through our
|
||||
`walk-through guide <https://github.com/jmbannon/ytdl-sub/wiki/1.-Introduction>`_
|
||||
to get familiar with how ``ytdl-sub`` works.
|
||||
|
||||
Example Configs
|
||||
---------------
|
||||
If you are ready to start downloading, see our
|
||||
`examples directory <https://github.com/jmbannon/ytdl-sub/tree/master/examples>`_
|
||||
for ready-to-use configs and subscriptions. Read through them carefully before use.
|
||||
|
||||
Using Example Configs
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
Copy and paste the examples into local yaml files, modify the
|
||||
``working_directory`` and ``output_directory`` with your desired paths,
|
||||
and perform a dry-run using
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
ytdl-sub \
|
||||
--dry-run \
|
||||
--config path/to/config.yaml \
|
||||
sub path/to/subscriptions.yaml
|
||||
|
||||
This will simulate what a download will look like.
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
ytdl-sub readthedocs
|
||||
====================
|
||||
|
||||
Our readthedocs page is dedicated towards ytdl-sub config documentation.
|
||||
|
||||
If you are new to ytdl-sub, head over to the
|
||||
`GitHub Wiki <https://github.com/jmbannon/ytdl-sub/wiki>`_
|
||||
to see our
|
||||
`walkthrough <https://github.com/jmbannon/ytdl-sub/wiki/1.-Introduction>`_ and
|
||||
`FAQ <https://github.com/jmbannon/ytdl-sub/wiki/FAQ>`_. For full examples of
|
||||
ytdl-sub configs, check out the
|
||||
`examples directory <https://github.com/jmbannon/ytdl-sub/tree/master/examples>`_.
|
||||
|
||||
|
||||
For navigating config docs, use the left-side bar on the
|
||||
:ref:`config` page to find every available ytdl-sub field.
|
||||
|
||||
Contents
|
||||
========
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
install
|
||||
usage
|
||||
getting_started
|
||||
presets
|
||||
config
|
||||
deprecation_notices
|
||||
256
docs/install.rst
256
docs/install.rst
|
|
@ -1,256 +0,0 @@
|
|||
Install
|
||||
=======
|
||||
``ytdl-sub`` can be installed on the following platforms.
|
||||
|
||||
.. contents::
|
||||
:depth: 3
|
||||
|
||||
All installations require a 64-bit CPU. 32-bit is not supported.
|
||||
|
||||
Docker Compose
|
||||
--------------
|
||||
The ytdl-sub Docker images use
|
||||
`LSIO-based images <https://www.linuxserver.io/>`_
|
||||
and installs ytdl-sub on top. There are a few flavors to choose from.
|
||||
|
||||
For automating ``subscriptions.yaml`` downloads to pull new media, see
|
||||
`this guide <https://github.com/jmbannon/ytdl-sub/wiki/7.-Automate-Downloading-New-Content-Using-Your-Configs/>`_
|
||||
on how set up a cron job in any of the docker containers.
|
||||
|
||||
GUI
|
||||
^^^^
|
||||
|
||||
The GUI image uses LSIO's
|
||||
`code-server <https://hub.docker.com/r/linuxserver/code-server>`_
|
||||
for its base image. More info on other code-server environment variables
|
||||
can be found within its documentation. This is the recommended way to use ``ytdl-sub``.
|
||||
|
||||
After starting, code-server will be running at http://localhost:8443/
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
services:
|
||||
ytdl-sub:
|
||||
image: ghcr.io/jmbannon/ytdl-sub-gui:latest
|
||||
container_name: ytdl-sub
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/Los_Angeles
|
||||
volumes:
|
||||
- <path/to/ytdl-sub/config>:/config
|
||||
- <path/to/tv_shows>:/tv_shows # optional
|
||||
- <path/to/movies>:/movies # optional
|
||||
- <path/to/music_videos>:/music_videos # optional
|
||||
- <path/to/music>:/music # optional
|
||||
ports:
|
||||
- 8443:8443
|
||||
restart: unless-stopped
|
||||
|
||||
Headless
|
||||
^^^^^^^^^^
|
||||
|
||||
The headless image uses LSIO's
|
||||
`baseimage-alpine <https://github.com/linuxserver/docker-baseimage-alpine>`_
|
||||
for its base image. With this image, ``ytdl-sub`` is meant to be ran from console
|
||||
via exec'ing into the image using the command:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
docker exec -u abc -it ytdl-sub /bin/bash
|
||||
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
services:
|
||||
ytdl-sub:
|
||||
image: ghcr.io/jmbannon/ytdl-sub:latest
|
||||
container_name: ytdl-sub
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/Los_Angeles
|
||||
- DOCKER_MODS=linuxserver/mods:universal-cron
|
||||
volumes:
|
||||
- <path/to/ytdl-sub/config>:/config
|
||||
- <path/to/tv_shows>:/tv_shows # optional
|
||||
- <path/to/movies>:/movies # optional
|
||||
- <path/to/music_videos>:/music_videos # optional
|
||||
- <path/to/music>:/music # optional
|
||||
restart: unless-stopped
|
||||
|
||||
Passthrough
|
||||
^^^^^^^^^^^
|
||||
For CPU or GPU passthrough, you must use either the GUI image or the headless Ubuntu image
|
||||
``ghcr.io/jmbannon/ytdl-sub:ubuntu-latest``.
|
||||
|
||||
The docker-compose examples use the GUI image.
|
||||
|
||||
CPU
|
||||
____
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
services:
|
||||
ytdl-sub:
|
||||
image: ghcr.io/jmbannon/ytdl-sub-gui:latest
|
||||
container_name: ytdl-sub
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/Los_Angeles
|
||||
volumes:
|
||||
- <path/to/ytdl-sub/config>:/config
|
||||
- <path/to/tv_shows>:/tv_shows # optional
|
||||
- <path/to/movies>:/movies # optional
|
||||
- <path/to/music_videos>:/music_videos # optional
|
||||
- <path/to/music>:/music # optional
|
||||
ports:
|
||||
- 8443:8443
|
||||
devices:
|
||||
- /dev/dri:/dev/dri # CPU passthrough
|
||||
restart: unless-stopped
|
||||
|
||||
GPU
|
||||
____
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
services:
|
||||
ytdl-sub:
|
||||
image: ghcr.io/jmbannon/ytdl-sub-gui:latest
|
||||
container_name: ytdl-sub
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/Los_Angeles
|
||||
- NVIDIA_DRIVER_CAPABILITIES=all # Nvidia ENV args
|
||||
- NVIDIA_VISIBLE_DEVICES=all
|
||||
volumes:
|
||||
- <path/to/ytdl-sub/config>:/config
|
||||
- <path/to/tv_shows>:/tv_shows # optional
|
||||
- <path/to/movies>:/movies # optional
|
||||
- <path/to/music_videos>:/music_videos # optional
|
||||
- <path/to/music>:/music # optional
|
||||
ports:
|
||||
- 8443:8443
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices:
|
||||
- capabilities: [gpu] # GPU passthrough
|
||||
restart: unless-stopped
|
||||
|
||||
Docker
|
||||
--------------
|
||||
.. code-block:: bash
|
||||
|
||||
docker run -d \
|
||||
--name=ytdl-sub \
|
||||
-e PUID=1000 \
|
||||
-e PGID=1000 \
|
||||
-e TZ=America/Los_Angeles \
|
||||
-p 8443:8443 \
|
||||
-v <path/to/ytdl-sub/config>:/config \
|
||||
-v <OPTIONAL/path/to/tv_shows>:/tv_shows \
|
||||
-v <OPTIONAL/path/to/movies>:/movies \
|
||||
-v <OPTIONAL/path/to/music_videos>:/music_videos \
|
||||
-v <OPTIONAL/path/to/music>:/music \
|
||||
--restart unless-stopped \
|
||||
ghcr.io/jmbannon/ytdl-sub-gui:latest
|
||||
|
||||
Windows
|
||||
--------------
|
||||
From powershell, run:
|
||||
|
||||
.. code-block:: powershell
|
||||
|
||||
# Download ffmpeg/ffprobe dependencies from yt-dlp
|
||||
curl.exe -L -o ffmpeg.zip https://github.com/yt-dlp/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-win64-gpl.zip
|
||||
tar -xf ffmpeg.zip
|
||||
move "ffmpeg-master-latest-win64-gpl\bin\ffmpeg.exe" "ffmpeg.exe"
|
||||
move "ffmpeg-master-latest-win64-gpl\bin\ffprobe.exe" "ffprobe.exe"
|
||||
|
||||
# Download ytdl-sub
|
||||
curl.exe -L -o ytdl-sub.exe https://github.com/jmbannon/ytdl-sub/releases/latest/download/ytdl-sub.exe
|
||||
ytdl-sub.exe -h
|
||||
|
||||
Unraid
|
||||
--------------
|
||||
See the
|
||||
`community app <https://unraid.net/community/apps?q=ytdl-sub#r>`_
|
||||
``ytdl-sub``. Uses Docker under the hood.
|
||||
|
||||
Linux
|
||||
--------------
|
||||
Requires ffmpeg as a dependency. Can typically be installed with any Linux package manager.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
curl -L -o ytdl-sub https://github.com/jmbannon/ytdl-sub/releases/latest/download/ytdl-sub
|
||||
chmod +x ytdl-sub
|
||||
ytdl-sub -h
|
||||
|
||||
You can also install using yt-dlp's ffmpeg builds. This ensures your ffmpeg is up to date:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
curl -L -o ffmpeg.tar.gz https://github.com/yt-dlp/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-linux64-gpl.tar.xz
|
||||
tar -xf ffmpeg.tar.gz
|
||||
chmod +x ffmpeg-master-latest-linux64-gpl/bin/ffmpeg
|
||||
chmod +x ffmpeg-master-latest-linux64-gpl/bin/ffprobe
|
||||
|
||||
# May need sudo / root permissions to perform
|
||||
mv ffmpeg-master-latest-linux64-gpl/bin/ffmpeg /usr/bin/ffmpeg
|
||||
mv ffmpeg-master-latest-linux64-gpl/bin/ffprobe /usr/bin/ffprobe
|
||||
|
||||
Linux ARM
|
||||
--------------
|
||||
Requires ffmpeg as a dependency. Can typically be installed with any Linux package manager.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
curl -L -o ytdl-sub https://github.com/jmbannon/ytdl-sub/releases/latest/download/ytdl-sub_aarch64
|
||||
chmod +x ytdl-sub
|
||||
ytdl-sub -h
|
||||
|
||||
You can also install using yt-dlp's ffmpeg builds. This ensures your ffmpeg is up to date:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
curl -L -o ffmpeg.tar.gz https://github.com/yt-dlp/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-linuxarm64-gpl.tar.xz
|
||||
tar -xf ffmpeg.tar.gz
|
||||
chmod +x ffmpeg-master-latest-linuxarm64-gpl/bin/ffmpeg
|
||||
chmod +x ffmpeg-master-latest-linuxarm64-gpl/bin/ffprobe
|
||||
|
||||
# May need sudo / root permissions to perform
|
||||
mv ffmpeg-master-latest-linuxarm64-gpl/bin/ffmpeg /usr/bin/ffmpeg
|
||||
mv ffmpeg-master-latest-linuxarm64-gpl/bin/ffprobe /usr/bin/ffprobe
|
||||
|
||||
|
||||
PIP
|
||||
--------------
|
||||
You can install our
|
||||
`PyPI package <https://pypi.org/project/ytdl-sub/>`_.
|
||||
Both ffmpeg and Python 3.10 or greater are required.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
python3 -m pip install -U ytdl-sub
|
||||
|
||||
Local Install
|
||||
--------------
|
||||
With a Python 3.10 virtual environment, you can clone and install the repo using
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git clone https://github.com/jmbannon/ytdl-sub.git
|
||||
cd ytdl-sub
|
||||
|
||||
pip install -e .
|
||||
|
||||
Local Docker Build
|
||||
-------------------
|
||||
Run ``make docker`` in the root directory of this repo to build the image. This
|
||||
will build the python wheel and install it in the Dockerfile.
|
||||
|
||||
|
|
@ -7,8 +7,8 @@ REM Command file for Sphinx documentation
|
|||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set SOURCEDIR=.
|
||||
set BUILDDIR=_build
|
||||
set SOURCEDIR=source
|
||||
set BUILDDIR=build
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
|
|
|
|||
183
docs/presets.rst
183
docs/presets.rst
|
|
@ -1,183 +0,0 @@
|
|||
Presets
|
||||
=======
|
||||
``ytdl-sub`` offers a number of built-in presets using best practices for formatting
|
||||
media in various players. For advanced users, you can find the prebuilt preset
|
||||
definitions
|
||||
`here <https://github.com/jmbannon/ytdl-sub/tree/master/src/ytdl_sub/prebuilt_presets>`_.
|
||||
|
||||
TV Shows
|
||||
--------
|
||||
|
||||
There are two main methods for downloading and formatting videos as a TV show.
|
||||
|
||||
TV Show by Date
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
TV Show by Date will organize something like a YouTube channel or playlist
|
||||
into a tv show, where seasons and episodes are organized using upload date.
|
||||
|
||||
Player Presets
|
||||
""""""""""""""
|
||||
|
||||
* ``kodi_tv_show_by_date``
|
||||
* ``jellyfin_tv_show_by_date``
|
||||
* ``plex_tv_show_by_date``
|
||||
|
||||
Episode Formatting Presets
|
||||
""""""""""""""""""""""""""
|
||||
|
||||
* ``season_by_year__episode_by_month_day``
|
||||
* ``season_by_year_month__episode_by_day``
|
||||
* ``season_by_year__episode_by_month_day_reversed``
|
||||
* Episode numbers are reversed, meaning more recent episodes appear at the
|
||||
top of a season by having a lower value.
|
||||
* ``season_by_year__episode_by_download_index``
|
||||
* Episodes are numbered by the download order. NOTE that this fetched using
|
||||
the length of the download archive. Do not use if you intend to remove
|
||||
old videos.
|
||||
|
||||
Usage
|
||||
"""""
|
||||
|
||||
A preset/subscription requires specifying a player and episode formatting preset
|
||||
and overriding the following variables:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
rick_a_tv_show_by_date:
|
||||
preset:
|
||||
- "jellyfin_tv_show_by_date"
|
||||
- "season_by_year__episode_by_month_day"
|
||||
overrides:
|
||||
# required
|
||||
tv_show_name: "Rick A"
|
||||
tv_show_directory: "/path/to/youtube_shows"
|
||||
url: "https://www.youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw"
|
||||
# can be modified from their default value
|
||||
# tv_show_genre: "ytdl-sub"
|
||||
# tv_show_content_rating: "TV-14"
|
||||
# episode_title: "{upload_date_standardized} - {title}"
|
||||
# episode_description: "{webpage_url}"
|
||||
|
||||
In addition, you can add additional URLs to create a single TV by using the override variables
|
||||
``url2``, ``url3``, ..., ``url20``:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
overrides:
|
||||
tv_show_name: "Rick A"
|
||||
tv_show_directory: "/path/to/youtube_shows"
|
||||
url: "https://www.youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw"
|
||||
url2: "https://www.youtube.com/@just.rick_6"
|
||||
|
||||
|
||||
TV Show Collection
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
TV Show Collections are made up from multiple URLs, where each URL is a season.
|
||||
If a video belongs to multiple URLs (i.e. a channel and a channel's playlist),
|
||||
it will resolve to the bottom-most season.
|
||||
|
||||
Two main use cases of a collection are:
|
||||
1. Organize a YouTube channel TV show where Season 1 contains any video
|
||||
not in a 'season playlist', Season 2 for 'Playlist A', Season 3 for
|
||||
'Playlist B', etc.
|
||||
2. Organize one or more YouTube channels/playlists, where each season
|
||||
represents a separate channel/playlist.
|
||||
|
||||
Player Presets
|
||||
""""""""""""""
|
||||
|
||||
* ``kodi_tv_show_collection``
|
||||
* ``jellyfin_tv_show_collection``
|
||||
* ``plex_tv_show_collection``
|
||||
|
||||
Episode Formatting Presets
|
||||
""""""""""""""""""""""""""
|
||||
|
||||
* ``season_by_collection__episode_by_year_month_day``
|
||||
* ``season_by_collection__episode_by_year_month_day_reversed``
|
||||
* ``season_by_collection__episode_by_playlist_index``
|
||||
* Only use playlist_index episode formatting for playlists that
|
||||
will be fully downloaded once and never again. Otherwise,
|
||||
indices can change.
|
||||
* ``season_by_collection__episode_by_playlist_index_reversed``
|
||||
|
||||
Season Presets
|
||||
""""""""""""""
|
||||
|
||||
* ``collection_season_1``
|
||||
* ``collection_season_2``
|
||||
* ``collection_season_3``
|
||||
* ``collection_season_4``
|
||||
* ``...``
|
||||
* ``collection_season_40``
|
||||
|
||||
Example
|
||||
"""""""
|
||||
|
||||
A preset/subscription requires specifying a player, episode formatting, and
|
||||
one or more season presets, with the following override variables:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
rick_a_tv_show_collection:
|
||||
preset:
|
||||
- "jellyfin_tv_show_collection"
|
||||
- "season_by_collection__episode_by_year_month_day_reversed"
|
||||
- "collection_season_1"
|
||||
- "collection_season_2"
|
||||
overrides:
|
||||
# required
|
||||
tv_show_name: "Rick A"
|
||||
tv_show_directory: "/path/to/youtube_shows"
|
||||
collection_season_1_url: "https://www.youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw"
|
||||
collection_season_1_name: "All Videos"
|
||||
collection_season_2_url: "https://www.youtube.com/playlist?list=PLlaN88a7y2_plecYoJxvRFTLHVbIVAOoc"
|
||||
collection_season_2_name: "Official Music Videos"
|
||||
# can be modified from their default value
|
||||
# tv_show_genre: "ytdl-sub"
|
||||
# episode_title: "{upload_date_standardized} - {title}"
|
||||
# episode_description: "{webpage_url}"
|
||||
|
||||
Common
|
||||
------
|
||||
|
||||
Common presets are applicable to any config.
|
||||
|
||||
Best Video Quality
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Add the following preset to download the best available video and audio quality, and remux
|
||||
it into an MP4 container:
|
||||
|
||||
* ``best_video_quality``
|
||||
|
||||
|
||||
Max 1080p
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Add the following preset to download the best available audio and video quality, with the video not greater than 1080p, and remux it into an MP4 container:
|
||||
|
||||
* ``max_1080p``
|
||||
|
||||
Chunk Initial Download
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If you are archiving a large channel, ``ytdl-sub`` will try pulling each video's metadata from
|
||||
newest to oldest before starting any downloads. It is a long process and not ideal. A better method
|
||||
is to chunk the process by using the following preset:
|
||||
|
||||
* ``chunk_initial_download``
|
||||
|
||||
It will download videos starting from the oldest one, and only download 20 at a time. You can
|
||||
change this number by setting:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
ytdl_options:
|
||||
max_downloads: 30 # Desired number to download per invocation
|
||||
|
||||
Once the entire channel is downloaded, remove this preset. Then it will pull metadata from newest to
|
||||
oldest again, and stop pulling additional metadata once it reaches a video that has already been
|
||||
downloaded.
|
||||
87
docs/source/conf.py
Normal file
87
docs/source/conf.py
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
# Configuration file for the Sphinx documentation builder.
|
||||
|
||||
# For the full list of built-in configuration values, see the documentation:
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
||||
|
||||
project = "ytdl-sub"
|
||||
copyright = "2023, Jesse Bannon"
|
||||
author = "Jesse Bannon"
|
||||
release = "2023.12.15"
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
||||
|
||||
extensions = [
|
||||
"sphinx.ext.autodoc",
|
||||
"sphinx.ext.autosectionlabel",
|
||||
"sphinx.ext.extlinks",
|
||||
"sphinx.ext.napoleon",
|
||||
"sphinx_copybutton",
|
||||
"sphinx_design",
|
||||
]
|
||||
|
||||
templates_path = ["_templates"]
|
||||
exclude_patterns = []
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
||||
|
||||
html_theme = "sphinx_book_theme"
|
||||
|
||||
html_theme_options = {
|
||||
"icon_links": [
|
||||
{
|
||||
"name": "GitHub",
|
||||
"url": "https://github.com/jmbannon/ytdl-sub",
|
||||
"icon": "fa-brands fa-square-github",
|
||||
"type": "fontawesome",
|
||||
},
|
||||
{
|
||||
"name": "Discord",
|
||||
"url": "https://discord.gg/v8j9RAHb4k",
|
||||
"icon": "https://img.shields.io/discord/994270357957648404?logo=Discord",
|
||||
"type": "url",
|
||||
},
|
||||
],
|
||||
"announcement": ("Please excuse our mess as we update these documents"),
|
||||
"navigation_depth": 10,
|
||||
"show_toc_level": 10,
|
||||
}
|
||||
|
||||
html_static_path = ["_static"]
|
||||
|
||||
|
||||
# Make sure the all autosectionlabel targets are unique
|
||||
autosectionlabel_prefix_document = True
|
||||
|
||||
suppress_warnings = [
|
||||
"autosectionlabel.*",
|
||||
]
|
||||
|
||||
extlinks = {
|
||||
"yt-dlp": ("https://github.com/yt-dlp/yt-dlp/%s", "yt-dlp%s"),
|
||||
"unraid": ("https://unraid.net/%s", "unraid%s"),
|
||||
"lsio": ("https://www.linuxserver.io/%s", "lsio%s"),
|
||||
"lsio-gh": ("https://github.com/linuxserver/%s", "%s image"),
|
||||
"ytdl-sub-gh": ("https://github.com/jmbannon/ytdl-sub/%s", "src %s"),
|
||||
}
|
||||
|
||||
# -- Options for autodoc ----------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#configuration
|
||||
|
||||
# Automatically extract typehints when specified and place them in
|
||||
# descriptions of the relevant function/method.
|
||||
autodoc_default_options = {
|
||||
"autodoc_typehints_format": "short",
|
||||
"autodoc_class_signature": "separated",
|
||||
"add_module_names": False,
|
||||
# "add_class_names": False,
|
||||
}
|
||||
|
||||
python_use_unqualified_type_names = True
|
||||
napoleon_numpy_docstring = True
|
||||
napoleon_use_rtype = False
|
||||
134
docs/source/config_reference/config_yaml.rst
Normal file
134
docs/source/config_reference/config_yaml.rst
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
==================
|
||||
Configuration File
|
||||
==================
|
||||
-----------
|
||||
config.yaml
|
||||
-----------
|
||||
|
||||
ytdl-sub is configured using a ``config.yaml`` file.
|
||||
|
||||
The ``config.yaml`` is made up of two sections:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
configuration:
|
||||
presets:
|
||||
|
||||
You can jump to any section and subsection of the config using the navigation
|
||||
section to the left.
|
||||
|
||||
Note for Windows users, paths can be represented with ``C:/forward/slashes/like/linux``.
|
||||
If you wish to represent paths like Windows, you will need to ``C:\\double\\bashslash\\paths``
|
||||
in order to escape the backslash character.
|
||||
|
||||
configuration
|
||||
~~~~~~~~~~~~~
|
||||
The ``configuration`` section contains app-wide configs applied to all presets
|
||||
and subscriptions.
|
||||
|
||||
.. autoclass:: ytdl_sub.config.config_validator.ConfigOptions()
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:exclude-members: subscription_value, persist_logs, experimental
|
||||
|
||||
persist_logs
|
||||
""""""""""""
|
||||
Within ``configuration``, define whether logs from subscription downloads
|
||||
should be persisted.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
configuration:
|
||||
persist_logs:
|
||||
logs_directory: "/path/to/log/directory"
|
||||
|
||||
Log files are stored as
|
||||
``YYYY-mm-dd-HHMMSS.subscription_name.(success|error).log``.
|
||||
|
||||
.. autoclass:: ytdl_sub.config.config_validator.PersistLogsValidator()
|
||||
:members:
|
||||
:member-order: bysource
|
||||
|
||||
presets
|
||||
~~~~~~~
|
||||
``presets`` define a `formula` for how to format downloaded media and metadata.
|
||||
|
||||
download_strategy
|
||||
"""""""""""""""""
|
||||
Download strategies dictate what is getting downloaded from a source. Each
|
||||
download strategy has its own set of parameters.
|
||||
|
||||
.. _url:
|
||||
|
||||
url
|
||||
'''
|
||||
.. autoclass:: ytdl_sub.downloaders.url.url.UrlDownloadOptions()
|
||||
:members: url, playlist_thumbnails, source_thumbnails, download_reverse
|
||||
:member-order: bysource
|
||||
|
||||
multi_url
|
||||
'''''''''
|
||||
.. autoclass:: ytdl_sub.downloaders.url.multi_url.MultiUrlDownloadOptions()
|
||||
:members: urls, variables
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
output_options
|
||||
""""""""""""""
|
||||
|
||||
.. autoclass:: ytdl_sub.config.preset_options.OutputOptions()
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:exclude-members: get_upload_date_range_to_keep, partial_validate
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
.. _ytdl_options:
|
||||
|
||||
ytdl_options
|
||||
""""""""""""
|
||||
.. autoclass:: ytdl_sub.config.preset_options.YTDLOptions()
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
.. _overrides:
|
||||
|
||||
overrides
|
||||
"""""""""
|
||||
.. autoclass:: ytdl_sub.config.overrides.Overrides()
|
||||
|
||||
.. _parent preset:
|
||||
|
||||
preset
|
||||
""""""
|
||||
Presets support inheritance by defining a parent preset:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
custom_preset:
|
||||
...
|
||||
parent_preset:
|
||||
...
|
||||
child_preset:
|
||||
preset: "parent_preset"
|
||||
|
||||
In the example above, ``child_preset`` inherits all fields defined in ``parent_preset``.
|
||||
It is advantageous to use parent presets where possible to reduce duplicate yaml
|
||||
definitions.
|
||||
|
||||
Presets also support inheritance from multiple presets:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
child_preset:
|
||||
preset:
|
||||
- "custom_preset"
|
||||
- "parent_preset"
|
||||
|
||||
In this example, ``child_preset`` will inherit all fields from ``custom_preset``
|
||||
and ``parent_preset`` in that order. The bottom-most preset has the highest
|
||||
priority.
|
||||
|
||||
If you are only inheriting from one preset, the syntax ``preset: "parent_preset"`` is
|
||||
valid YAML. Inheriting from multiple presets require use of a list.
|
||||
12
docs/source/config_reference/index.rst
Normal file
12
docs/source/config_reference/index.rst
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
=========
|
||||
Reference
|
||||
=========
|
||||
|
||||
This section contains direct references to the code of ``ytdl-sub`` and information on how it functions.
|
||||
|
||||
.. toctree::
|
||||
config_yaml
|
||||
subscriptions_yaml
|
||||
plugins
|
||||
scripting/index
|
||||
prebuilt_presets/index
|
||||
767
docs/source/config_reference/plugins.rst
Normal file
767
docs/source/config_reference/plugins.rst
Normal file
|
|
@ -0,0 +1,767 @@
|
|||
Plugins
|
||||
=======
|
||||
|
||||
audio_extract
|
||||
-------------
|
||||
Extracts audio from a video file.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
audio_extract:
|
||||
codec: "mp3"
|
||||
quality: 128
|
||||
|
||||
codec
|
||||
~~~~~
|
||||
The codec to output after extracting the audio. Supported codecs are aac, flac, mp3, m4a,
|
||||
opus, vorbis, wav, and best to grab the best possible format at runtime.
|
||||
|
||||
quality
|
||||
~~~~~~~
|
||||
Optional. Specify ffmpeg audio quality. Insert a value between ``0`` (better) and ``9``
|
||||
(worse) for variable bitrate, or a specific bitrate like ``128`` for 128k.
|
||||
|
||||
chapters
|
||||
--------
|
||||
Embeds chapters to video files if they are present. Additional options to add SponsorBlock
|
||||
chapters and remove specific ones. Can also remove chapters using regex.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
chapters:
|
||||
# Embedded Chapter Fields
|
||||
embed_chapters: True
|
||||
allow_chapters_from_comments: False
|
||||
remove_chapters_regex:
|
||||
- "Intro"
|
||||
- "Outro"
|
||||
|
||||
# Sponsorblock Fields
|
||||
sponsorblock_categories:
|
||||
- "outro"
|
||||
- "selfpromo"
|
||||
- "preview"
|
||||
- "interaction"
|
||||
- "sponsor"
|
||||
- "music_offtopic"
|
||||
- "intro"
|
||||
remove_sponsorblock_categories: "all"
|
||||
force_key_frames: False
|
||||
|
||||
allow_chapters_from_comments
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Optional. If chapters do not exist in the video/description itself, attempt to scrape
|
||||
comments to find the chapters. Defaults to False.
|
||||
|
||||
embed_chapters
|
||||
~~~~~~~~~~~~~~
|
||||
Optional. Embed chapters into the file. Defaults to True.
|
||||
|
||||
force_key_frames
|
||||
~~~~~~~~~~~~~~~~
|
||||
Optional. Force keyframes at cuts when removing sections. This is slow due to needing a
|
||||
re-encode, but the resulting video may have fewer artifacts around the cuts. Defaults to
|
||||
False.
|
||||
|
||||
remove_chapters_regex
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
Optional. List of regex patterns to match chapter titles against and remove them from the
|
||||
entry.
|
||||
|
||||
remove_sponsorblock_categories
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Optional. List of SponsorBlock categories to remove from the output file. Can only remove
|
||||
categories that are specified in ``sponsorblock_categories`` or "all", which removes
|
||||
everything specified in ``sponsorblock_categories``.
|
||||
|
||||
sponsorblock_categories
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Optional. List of SponsorBlock categories to embed as chapters. Supports "sponsor",
|
||||
"intro", "outro", "selfpromo", "preview", "filler", "interaction", "music_offtopic",
|
||||
"poi_highlight", or "all" to include all categories.
|
||||
|
||||
date_range
|
||||
----------
|
||||
Only download files uploaded within the specified date range.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
date_range:
|
||||
before: "now"
|
||||
after: "today-2weeks"
|
||||
|
||||
after
|
||||
~~~~~
|
||||
Optional. Only download videos after this datetime.
|
||||
|
||||
before
|
||||
~~~~~~
|
||||
Optional. Only download videos before this datetime.
|
||||
|
||||
embed_thumbnail
|
||||
---------------
|
||||
Whether to embed thumbnails to the audio/video file or not.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
embed_thumbnail: True
|
||||
|
||||
file_convert
|
||||
------------
|
||||
Converts video files from one extension to another.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
file_convert:
|
||||
convert_to: "mp4"
|
||||
|
||||
Supports custom ffmpeg conversions:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
file_convert:
|
||||
convert_to: "mkv"
|
||||
convert_with: "ffmpeg"
|
||||
ffmpeg_post_process_args: >
|
||||
-bitexact
|
||||
-vcodec copy
|
||||
-acodec copy
|
||||
-scodec mov_text
|
||||
|
||||
convert_to
|
||||
~~~~~~~~~~
|
||||
Convert to a desired file type. Supports:
|
||||
|
||||
* Video: avi, flv, mkv, mov, mp4, webm
|
||||
* Audio: aac, flac, mp3, m4a, opus, vorbis, wav
|
||||
|
||||
convert_with
|
||||
~~~~~~~~~~~~
|
||||
Optional. Supports ``yt-dlp`` and ``ffmpeg``. ``yt-dlp`` will convert files within
|
||||
yt-dlp whereas ``ffmpeg`` specifies it will be converted using a custom command specified
|
||||
with ``ffmpeg_post_process_args``. Defaults to ``yt-dlp``.
|
||||
|
||||
ffmpeg_post_process_args
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Optional. ffmpeg args to post-process an entry file with. The args will be inserted in the
|
||||
form of:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
ffmpeg -i input_file.ext {ffmpeg_post_process_args) output_file.output_ext
|
||||
|
||||
The output file will use the extension specified in ``convert_to``. Post-processing args
|
||||
can still be set with ``convert_with`` set to ``yt-dlp``.
|
||||
|
||||
format
|
||||
------
|
||||
Set ``--format`` to pass into yt-dlp to download a specific format quality.
|
||||
Uses the same syntax as yt-dlp.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
format: "(bv*[height<=1080]+bestaudio/best[height<=1080])"
|
||||
|
||||
format
|
||||
~~~~~~
|
||||
yt-dlp format, uses same syntax as yt-dlp.
|
||||
|
||||
match_filters
|
||||
-------------
|
||||
Set ``--match-filters``` to pass into yt-dlp to filter entries from being downloaded.
|
||||
Uses the same syntax as yt-dlp.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
match_filters:
|
||||
filters: "original_url!*=/shorts/"
|
||||
|
||||
Supports one or multiple filters:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
match_filters:
|
||||
filters:
|
||||
- "age_limit<?18"
|
||||
- "like_count>?100"
|
||||
# Other common match-filters
|
||||
# - "original_url!*=/shorts/ & !is_live"
|
||||
# - "age_limit<?18"
|
||||
# - "availability=?public"
|
||||
|
||||
filters
|
||||
~~~~~~~
|
||||
The filters themselves. If used multiple times, the filter matches if at least one of the
|
||||
conditions are met. For logical AND's between match filters, use the ``&`` operator in
|
||||
a single match filter. These are applied when gathering metadata.
|
||||
|
||||
music_tags
|
||||
----------
|
||||
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}"
|
||||
# Supports id3v2.4 multi-tags
|
||||
genres:
|
||||
- "{genre}"
|
||||
- "ytdl-sub"
|
||||
albumartists:
|
||||
- "{artist}"
|
||||
- "ytdl-sub"
|
||||
|
||||
embed_thumbnail
|
||||
~~~~~~~~~~~~~~~
|
||||
Optional. Whether to embed the thumbnail into the audio file.
|
||||
|
||||
tags
|
||||
~~~~
|
||||
Key, values of tag names, tag values. Supports source and override variables.
|
||||
Supports lists which will get written to MP3s as id3v2.4 multi-tags.
|
||||
|
||||
nfo_tags
|
||||
--------
|
||||
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_tags:
|
||||
# required
|
||||
nfo_name: "{title_sanitized}.nfo"
|
||||
nfo_root: "episodedetails"
|
||||
tags:
|
||||
title: "{title}"
|
||||
season: "{upload_year}"
|
||||
episode: "{upload_month}{upload_day_padded}"
|
||||
# optional
|
||||
kodi_safe: False
|
||||
|
||||
kodi_safe
|
||||
~~~~~~~~~
|
||||
Optional. Kodi does not support > 3-byte unicode characters, which include emojis and some
|
||||
foreign language characters. Setting this to True will replace those characters with '□'.
|
||||
Defaults to False.
|
||||
|
||||
nfo_name
|
||||
~~~~~~~~
|
||||
The NFO file name.
|
||||
|
||||
nfo_root
|
||||
~~~~~~~~
|
||||
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>
|
||||
|
||||
tags
|
||||
~~~~
|
||||
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>
|
||||
|
||||
Also supports xml attributes and duplicate keys:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
tags:
|
||||
season:
|
||||
attributes:
|
||||
name: "Best Year"
|
||||
tag: "{upload_year}"
|
||||
genre:
|
||||
- "Comedy"
|
||||
- "Drama"
|
||||
|
||||
Which translates to
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<season name="Best Year">2022</season>
|
||||
<genre>Comedy</genre>
|
||||
<genre>Drama</genre>
|
||||
|
||||
output_directory_nfo_tags
|
||||
-------------------------
|
||||
Adds a single NFO file in the output directory. An NFO file is simply an XML file with a
|
||||
``.nfo`` extension. It uses the last entry's source variables which can change per download
|
||||
invocation. Be cautious of which variables you use.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
output_directory_nfo_tags:
|
||||
# required
|
||||
nfo_name: "tvshow.nfo"
|
||||
nfo_root: "tvshow"
|
||||
tags:
|
||||
title: "Sweet youtube TV show"
|
||||
# optional
|
||||
kodi_safe: False
|
||||
|
||||
kodi_safe
|
||||
~~~~~~~~~
|
||||
Optional. Kodi does not support > 3-byte unicode characters, which include emojis and some
|
||||
foreign language characters. Setting this to True will replace those characters with '□'.
|
||||
Defaults to False.
|
||||
|
||||
nfo_name
|
||||
~~~~~~~~
|
||||
The NFO file name.
|
||||
|
||||
nfo_root
|
||||
~~~~~~~~
|
||||
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"?>
|
||||
<tvshow>
|
||||
</tvshow>
|
||||
|
||||
tags
|
||||
~~~~
|
||||
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"?>
|
||||
<tvshow>
|
||||
<title>Sweet youtube TV show</title>
|
||||
</tvshow>
|
||||
|
||||
Also supports xml attributes and duplicate keys:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
tags:
|
||||
named_season:
|
||||
- tag: "{source_title}"
|
||||
attributes:
|
||||
number: "{collection_index}"
|
||||
genre:
|
||||
- "Comedy"
|
||||
- "Drama"
|
||||
|
||||
Which translates to
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<title year="2022">Sweet youtube TV show</season>
|
||||
<genre>Comedy</genre>
|
||||
<genre>Drama</genre>
|
||||
|
||||
output_options
|
||||
--------------
|
||||
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: "{title_sanitized}.{ext}"
|
||||
# optional
|
||||
thumbnail_name: "{title_sanitized}.{thumbnail_ext}"
|
||||
info_json_name: "{title_sanitized}.{info_json_ext}"
|
||||
download_archive_name: ".ytdl-sub-{subscription_name}-download-archive.json"
|
||||
migrated_download_archive_name: ".ytdl-sub-{subscription_name_sanitized}-download-archive.json"
|
||||
maintain_download_archive: True
|
||||
keep_files_before: now
|
||||
keep_files_after: 19000101
|
||||
|
||||
download_archive_name
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
Optional. The file name to store a subscriptions download archive placed relative to
|
||||
the output directory. Defaults to ``.ytdl-sub-{subscription_name}-download-archive.json``
|
||||
|
||||
file_name
|
||||
~~~~~~~~~
|
||||
Required. The file name for the media file. This can include directories such as
|
||||
``"Season {upload_year}/{title}.{ext}"``, and will be placed in the output directory.
|
||||
|
||||
info_json_name
|
||||
~~~~~~~~~~~~~~
|
||||
Optional. The file name for the media's info json file. This can include directories such
|
||||
as ``"Season {upload_year}/{title}.{info_json_ext}"``, and will be placed in the output
|
||||
directory. Can be set to empty string or `null` to disable info json writes.
|
||||
|
||||
keep_files_after
|
||||
~~~~~~~~~~~~~~~~
|
||||
Optional. Requires ``maintain_download_archive`` set to True.
|
||||
|
||||
Only keeps files that are uploaded after this datetime. By default, ytdl-sub will keep
|
||||
files after ``19000101``, which implies all files. Can be used in conjunction with
|
||||
``keep_max_files``.
|
||||
|
||||
keep_files_before
|
||||
~~~~~~~~~~~~~~~~~
|
||||
Optional. Requires ``maintain_download_archive`` set to True.
|
||||
|
||||
Only keeps files that are uploaded before this datetime. By default, ytdl-sub will keep
|
||||
files before ``now``, which implies all files. Can be used in conjunction with
|
||||
``keep_max_files``.
|
||||
|
||||
keep_max_files
|
||||
~~~~~~~~~~~~~~
|
||||
Optional. Requires ``maintain_download_archive`` set to True.
|
||||
|
||||
Only keeps N most recently uploaded videos. If set to <= 0, ``keep_max_files`` will not be
|
||||
applied. Can be used in conjunction with ``keep_files_before`` and ``keep_files_after``.
|
||||
|
||||
maintain_download_archive
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Optional. Maintains a download archive file in the output directory for a subscription.
|
||||
It is named ``.ytdl-sub-{subscription_name}-download-archive.json``, stored in the
|
||||
output directory.
|
||||
|
||||
The download archive contains a mapping of ytdl IDs to downloaded files. This is used to
|
||||
create a ytdl download-archive file when invoking a download on a subscription. This will
|
||||
prevent ytdl from redownloading media already downloaded.
|
||||
|
||||
Defaults to False.
|
||||
|
||||
migrated_download_archive_name
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Optional. Intended to be used if you are migrating a subscription with either a new
|
||||
subscription name or output directory. It will try to load the archive file using this name
|
||||
first, and fallback to ``download_archive_name``. It will always save to this file
|
||||
and remove the original ``download_archive_name``.
|
||||
|
||||
output_directory
|
||||
~~~~~~~~~~~~~~~~
|
||||
Required. The output directory to store all media files downloaded.
|
||||
|
||||
thumbnail_name
|
||||
~~~~~~~~~~~~~~
|
||||
Optional. The file name for the media's thumbnail image. This can include directories such
|
||||
as ``"Season {upload_year}/{title}.{thumbnail_ext}"``, and will be placed in the output
|
||||
directory. Can be set to empty string or `null` to disable thumbnail writes.
|
||||
|
||||
overrides
|
||||
---------
|
||||
Optional. This section allows you to define variables that can be used in any string formatter.
|
||||
For example, if you want your file and thumbnail files to match without copy-pasting a large
|
||||
format string, you can define something like:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
overrides:
|
||||
output_directory: "/path/to/media"
|
||||
custom_file_name: "{upload_date_standardized}.{title_sanitized}"
|
||||
|
||||
# Then use the override variables in the output options
|
||||
output_options:
|
||||
output_directory: "{output_directory}"
|
||||
file_name: "{custom_file_name}.{ext}"
|
||||
thumbnail_name: "{custom_file_name}.{thumbnail_ext}"
|
||||
|
||||
Override variables can contain explicit values and other variables, including both override
|
||||
and source variables.
|
||||
|
||||
In addition, any override variable defined will automatically create a ``sanitized`` variable
|
||||
for use. In the example above, ``output_directory_sanitized`` will exist and perform
|
||||
sanitization on the value when used.
|
||||
|
||||
regex
|
||||
-----
|
||||
Performs regex matching on an entry's source or override variables. Regex can be used to filter
|
||||
entries from proceeding with download or capture groups to create new source variables.
|
||||
|
||||
NOTE that YAML differentiates between single-quote (``'``) and double-quote (``"``), which can
|
||||
affect regex. Double-quote implies string literals, i.e. ``"\n"`` is the literal chars ``\n``,
|
||||
whereas single-quote, ``'\n'`` gets evaluated to a new line. To escape ``\`` when using
|
||||
single-quote, use ``\\``. This is necessary if you want your regex to be something like
|
||||
``\d\n`` to match a number and adjacent new-line. It must be written as ``\\d\n``.
|
||||
|
||||
If you want to regex-search multiple source variables to create a logical OR effect, you can
|
||||
create an override variable that contains the concatenation of them, and search that with regex.
|
||||
For example, creating the override variable ``"title_and_description": "{title} {description}"``
|
||||
and using ``title_and_description`` can regex match/exclude from either ``title`` or
|
||||
``description``.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
regex:
|
||||
# By default, if any match fails and has no defaults, the entry will
|
||||
# be skipped. If False, ytdl-sub will error and stop all downloads
|
||||
# from proceeding.
|
||||
skip_if_match_fails: True
|
||||
|
||||
from:
|
||||
# For each entry's `title` value...
|
||||
title:
|
||||
# Perform this regex match on it to act as a filter.
|
||||
# This will only download videos with "[Official Video]" in it. Note that we
|
||||
# double backslash to make YAML happy
|
||||
match:
|
||||
- '\\[Official Video\\]'
|
||||
|
||||
# For each entry's `description` value...
|
||||
description:
|
||||
# Match with capture groups and defaults.
|
||||
# This tries to scrape a date from the description and produce new
|
||||
# source variables
|
||||
match:
|
||||
- '([0-9]{4})-([0-9]{2})-([0-9]{2})'
|
||||
# Exclude any entry where the description contains #short
|
||||
exclude:
|
||||
- '#short'
|
||||
|
||||
# Each capture group creates these new source variables, respectively,
|
||||
# as well a sanitized version, i.e. `captured_upload_year_sanitized`
|
||||
capture_group_names:
|
||||
- "captured_upload_year"
|
||||
- "captured_upload_month"
|
||||
- "captured_upload_day"
|
||||
|
||||
# And if the string does not match, use these as respective default
|
||||
# values for the new source variables.
|
||||
capture_group_defaults:
|
||||
- "{upload_year}"
|
||||
- "{upload_month}"
|
||||
- "{upload_day}"
|
||||
|
||||
skip_if_match_fails
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
Defaults to True. If True, when any match fails and has no defaults, the entry will be
|
||||
skipped. If False, ytdl-sub will error and all downloads will not proceed.
|
||||
|
||||
split_by_chapters
|
||||
-----------------
|
||||
Splits a file by chapters into multiple files. Each file becomes its own entry with the
|
||||
new source variables ``chapter_title``, ``chapter_title_sanitized``, ``chapter_index``,
|
||||
``chapter_index_padded``, ``chapter_count``.
|
||||
|
||||
If a file has no chapters, and ``when_no_chapters`` is set to "pass", then ``chapter_title`` is
|
||||
set to the entry's title and ``chapter_index``, ``chapter_count`` are both set to 1.
|
||||
|
||||
Note that when using this plugin and performing dry-run, it assumes embedded chapters are being
|
||||
used with no modifications.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
split_by_chapters:
|
||||
when_no_chapters: "pass"
|
||||
|
||||
when_no_chapters
|
||||
~~~~~~~~~~~~~~~~
|
||||
Behavior to perform when no chapters are present. Supports "pass" (continue processing),
|
||||
"drop" (exclude it from output), and "error" (stop processing for everything).
|
||||
|
||||
subtitles
|
||||
---------
|
||||
Defines how to download and store subtitles. Using this plugin creates two new variables:
|
||||
``lang`` and ``subtitles_ext``. ``lang`` is dynamic since you can download multiple subtitles.
|
||||
It will set the respective language to the correct subtitle file.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
subtitles:
|
||||
subtitles_name: "{title_sanitized}.{lang}.{subtitles_ext}"
|
||||
subtitles_type: "srt"
|
||||
embed_subtitles: False
|
||||
languages: "en" # supports list of multiple languages
|
||||
allow_auto_generated_subtitles: False
|
||||
|
||||
allow_auto_generated_subtitles
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Optional. Whether to allow auto generated subtitles. Defaults to False.
|
||||
|
||||
embed_subtitles
|
||||
~~~~~~~~~~~~~~~
|
||||
Optional. Whether to embed the subtitles into the video file. Defaults to False.
|
||||
NOTE: webm files can only embed "vtt" subtitle types.
|
||||
|
||||
languages
|
||||
~~~~~~~~~
|
||||
Optional. Language code(s) to download for subtitles. Supports a single or list of multiple
|
||||
language codes. Defaults to "en".
|
||||
|
||||
subtitles_name
|
||||
~~~~~~~~~~~~~~
|
||||
Optional. The file name for the media's subtitles if they are present. This can include
|
||||
directories such as ``"Season {upload_year}/{title_sanitized}.{lang}.{subtitles_ext}"``, and
|
||||
will be placed in the output directory. ``lang`` is dynamic since you can download multiple
|
||||
subtitles. It will set the respective language to the correct subtitle file.
|
||||
|
||||
subtitles_type
|
||||
~~~~~~~~~~~~~~
|
||||
Optional. One of the subtitle file types "srt", "vtt", "ass", "lrc". Defaults to "srt"
|
||||
|
||||
throttle_protection
|
||||
-------------------
|
||||
Provides options to make ytdl-sub look more 'human-like' to protect from throttling. For
|
||||
range-based values, a random number will be chosen within the range to avoid sleeps looking
|
||||
scripted.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
throttle_protection:
|
||||
sleep_per_download_s:
|
||||
min: 2.2
|
||||
max: 10.8
|
||||
sleep_per_subscription_s:
|
||||
min: 9.0
|
||||
max: 14.1
|
||||
max_downloads_per_subscription:
|
||||
min: 10
|
||||
max: 36
|
||||
subscription_download_probability: 1.0
|
||||
|
||||
max_downloads_per_subscription
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Number of downloads to perform per subscription.
|
||||
|
||||
sleep_per_download_s
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
Number in seconds to sleep between each download. Does not include time it takes for
|
||||
ytdl-sub to perform post-processing.
|
||||
|
||||
sleep_per_subscription_s
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Number in seconds to sleep between each subscription.
|
||||
|
||||
subscription_download_probability
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Probability to perform any downloads, recomputed for each subscription. This is only
|
||||
recommended to set if you run ytdl-sub in a cron-job, that way you are statistically
|
||||
guaranteed over time to eventually download the subscription.
|
||||
|
||||
video_tags
|
||||
----------
|
||||
Adds tags to every downloaded video file using ffmpeg ``-metadata key=value`` args.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
video_tags:
|
||||
title: "{title}"
|
||||
date: "{upload_date}"
|
||||
description: "{description}"
|
||||
|
||||
tags
|
||||
~~~~
|
||||
Key/values of tag names/values. Supports source and override variables.
|
||||
|
||||
ytdl_options
|
||||
------------
|
||||
Optional. This section allows you to add any ytdl argument to ytdl-sub's downloader.
|
||||
The argument names can differ slightly from the command-line argument names. See
|
||||
`this docstring <https://github.com/yt-dlp/yt-dlp/blob/2022.04.08/yt_dlp/YoutubeDL.py#L197>`_
|
||||
for more details.
|
||||
|
||||
ytdl_options should be formatted like:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
my_example_preset:
|
||||
ytdl_options:
|
||||
# Ignore any download related errors and continue
|
||||
ignoreerrors: True
|
||||
# Stop downloading additional metadata/videos if it
|
||||
# exists in your download archive
|
||||
break_on_existing: True
|
||||
# Stop downloading additional metadata/videos if it
|
||||
# is out of your date range
|
||||
break_on_reject: True
|
||||
# Path to your YouTube cookies file to download 18+ restricted content
|
||||
cookiefile: "/path/to/cookies/file.txt"
|
||||
# Only download this number of videos/audio
|
||||
max_downloads: 10
|
||||
# Download and use English title/description/etc YouTube metadata
|
||||
extractor_args:
|
||||
youtube:
|
||||
lang:
|
||||
- "en"
|
||||
|
||||
|
||||
where each key is a ytdl argument. Include in the example are some popular ytdl_options.
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
=======================
|
||||
Common Preset Reference
|
||||
=======================
|
||||
|
||||
.. highlight:: yaml
|
||||
|
||||
.. literalinclude:: /../../src/ytdl_sub/prebuilt_presets/helpers/common.yaml
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
========================
|
||||
Players Preset Reference
|
||||
========================
|
||||
|
||||
.. highlight:: yaml
|
||||
|
||||
.. literalinclude:: /../../src/ytdl_sub/prebuilt_presets/helpers/players.yaml
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
====================
|
||||
URL Preset Reference
|
||||
====================
|
||||
|
||||
.. highlight:: yaml
|
||||
|
||||
.. literalinclude:: /../../src/ytdl_sub/prebuilt_presets/helpers/url.yaml
|
||||
12
docs/source/config_reference/prebuilt_presets/index.rst
Normal file
12
docs/source/config_reference/prebuilt_presets/index.rst
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
=========================
|
||||
Prebuilt Preset Reference
|
||||
=========================
|
||||
|
||||
This section contains the code for the prebuilt presets. If you just want to understand how to use the presets, check :doc:`this section instead</prebuilt_presets/index>`.
|
||||
|
||||
|
||||
|
||||
.. toctree::
|
||||
helpers_common
|
||||
helpers_players
|
||||
helpers_url
|
||||
17
docs/source/config_reference/scripting/config_types.rst
Normal file
17
docs/source/config_reference/scripting/config_types.rst
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
==================
|
||||
Config Field Types
|
||||
==================
|
||||
|
||||
The ``config.yaml`` uses various types for its configurable fields. Below is a definition for each type.
|
||||
|
||||
.. autoclass:: ytdl_sub.validators.string_formatter_validators.StringFormatterValidator()
|
||||
|
||||
.. autoclass:: ytdl_sub.validators.string_formatter_validators.OverridesStringFormatterValidator()
|
||||
|
||||
.. autoclass:: ytdl_sub.validators.file_path_validators.StringFormatterFileNameValidator()
|
||||
|
||||
.. autoclass:: ytdl_sub.validators.string_datetime.StringDatetimeValidator()
|
||||
|
||||
.. autoclass:: ytdl_sub.validators.string_formatter_validators.DictFormatterValidator()
|
||||
|
||||
.. autoclass:: ytdl_sub.validators.string_formatter_validators.OverridesDictFormatterValidator()
|
||||
439
docs/source/config_reference/scripting/entry_variables.rst
Normal file
439
docs/source/config_reference/scripting/entry_variables.rst
Normal file
|
|
@ -0,0 +1,439 @@
|
|||
Entry Variables
|
||||
===============
|
||||
|
||||
Entry Variables
|
||||
---------------
|
||||
|
||||
channel
|
||||
~~~~~~~
|
||||
The channel name if it exists, otherwise returns the uploader.
|
||||
|
||||
channel_id
|
||||
~~~~~~~~~~
|
||||
The channel id if it exists, otherwise returns the entry uploader ID.
|
||||
|
||||
chapters
|
||||
~~~~~~~~
|
||||
Chapters if they exist
|
||||
|
||||
comments
|
||||
~~~~~~~~
|
||||
Comments if they are requested
|
||||
|
||||
creator
|
||||
~~~~~~~
|
||||
The creator name if it exists, otherwise returns the channel.
|
||||
|
||||
description
|
||||
~~~~~~~~~~~
|
||||
The description if it exists. Otherwise, returns an emtpy string.
|
||||
|
||||
duration
|
||||
~~~~~~~~
|
||||
The duration of the entry in seconds
|
||||
|
||||
epoch
|
||||
~~~~~
|
||||
The unix epoch of when the metadata was scraped by yt-dlp.
|
||||
|
||||
epoch_date
|
||||
~~~~~~~~~~
|
||||
The epoch's date, in YYYYMMDD format.
|
||||
|
||||
epoch_hour
|
||||
~~~~~~~~~~
|
||||
The epoch's hour
|
||||
|
||||
ext
|
||||
~~~
|
||||
The downloaded entry's file extension
|
||||
|
||||
extractor
|
||||
~~~~~~~~~
|
||||
The yt-dlp extractor name
|
||||
|
||||
extractor_key
|
||||
~~~~~~~~~~~~~
|
||||
The yt-dlp extractor key
|
||||
|
||||
ie_key
|
||||
~~~~~~
|
||||
The ie_key, used in legacy yt-dlp things as the 'info-extractor key'
|
||||
|
||||
info_json_ext
|
||||
~~~~~~~~~~~~~
|
||||
The "info.json" extension
|
||||
|
||||
requested_subtitles
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
Subtitles if they are requested and exist
|
||||
|
||||
sponsorblock_chapters
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
Sponsorblock Chapters if they are requested and exist
|
||||
|
||||
thumbnail_ext
|
||||
~~~~~~~~~~~~~
|
||||
The download entry's thumbnail extension. Will always return 'jpg'. Until there is a
|
||||
need to support other image types, we always convert to jpg.
|
||||
|
||||
title
|
||||
~~~~~
|
||||
The title of the entry. If a title does not exist, returns its unique ID.
|
||||
|
||||
title_sanitized_plex
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
The sanitized title with additional sanitizing for Plex. It replaces numbers with
|
||||
fixed-width numbers so Plex does not recognize them as season or episode numbers.
|
||||
|
||||
uid
|
||||
~~~
|
||||
The entry's unique ID
|
||||
|
||||
uid_sanitized_plex
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
The sanitized uid with additional sanitizing for Plex. Replaces numbers with
|
||||
fixed-width numbers so Plex does not recognize them as season or episode numbers.
|
||||
|
||||
uploader
|
||||
~~~~~~~~
|
||||
The uploader if it exists, otherwise return the uploader ID.
|
||||
|
||||
uploader_id
|
||||
~~~~~~~~~~~
|
||||
The uploader id if it exists, otherwise return the unique ID.
|
||||
|
||||
uploader_url
|
||||
~~~~~~~~~~~~
|
||||
The uploader url if it exists, otherwise returns the webpage_url.
|
||||
|
||||
webpage_url
|
||||
~~~~~~~~~~~
|
||||
The url to the webpage.
|
||||
|
||||
Metadata Variables
|
||||
------------------
|
||||
|
||||
entry_metadata
|
||||
~~~~~~~~~~~~~~
|
||||
The entry's info.json
|
||||
|
||||
playlist_metadata
|
||||
~~~~~~~~~~~~~~~~~
|
||||
Metadata from the playlist (i.e. the parent metadata, like playlist -> entry)
|
||||
|
||||
sibling_metadata
|
||||
~~~~~~~~~~~~~~~~
|
||||
Metadata from any sibling entries that reside in the same playlist as this entry.
|
||||
|
||||
source_metadata
|
||||
~~~~~~~~~~~~~~~
|
||||
Metadata from the source (i.e. the grandparent metadata, like channel -> playlist -> entry)
|
||||
|
||||
Playlist Variables
|
||||
------------------
|
||||
|
||||
playlist_count
|
||||
~~~~~~~~~~~~~~
|
||||
Playlist count if it exists, otherwise returns ``1``.
|
||||
|
||||
Note that for channels/playlists, any change (i.e. adding or removing a video) will make
|
||||
this value change. Use with caution.
|
||||
|
||||
playlist_description
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
The playlist description if it exists, otherwise returns the entry's description.
|
||||
|
||||
playlist_index
|
||||
~~~~~~~~~~~~~~
|
||||
Playlist index if it exists, otherwise returns ``1``.
|
||||
|
||||
Note that for channels/playlists, any change (i.e. adding or removing a video) will make
|
||||
this value change. Use with caution.
|
||||
|
||||
playlist_index_padded
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
playlist_index padded two digits
|
||||
|
||||
playlist_index_padded6
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
playlist_index padded six digits.
|
||||
|
||||
playlist_index_reversed
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Playlist index reversed via ``playlist_count - playlist_index + 1``
|
||||
|
||||
playlist_index_reversed_padded
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
playlist_index_reversed padded two digits
|
||||
|
||||
playlist_index_reversed_padded6
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
playlist_index_reversed padded six digits.
|
||||
|
||||
playlist_max_upload_date
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Max upload_date for all entries in this entry's playlist if it exists, otherwise returns
|
||||
``upload_date``
|
||||
|
||||
playlist_max_upload_year
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Max upload_year for all entries in this entry's playlist if it exists, otherwise returns
|
||||
``upload_year``
|
||||
|
||||
playlist_max_upload_year_truncated
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The max playlist truncated upload year for all entries in this entry's playlist if it
|
||||
exists, otherwise returns ``upload_year_truncated``.
|
||||
|
||||
playlist_title
|
||||
~~~~~~~~~~~~~~
|
||||
Name of its parent playlist/channel if it exists, otherwise returns its title.
|
||||
|
||||
playlist_uid
|
||||
~~~~~~~~~~~~
|
||||
The playlist unique ID if it exists, otherwise return the entry unique ID.
|
||||
|
||||
playlist_uploader
|
||||
~~~~~~~~~~~~~~~~~
|
||||
The playlist uploader if it exists, otherwise return the entry uploader.
|
||||
|
||||
playlist_uploader_id
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
The playlist uploader id if it exists, otherwise returns the entry uploader ID.
|
||||
|
||||
playlist_uploader_url
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
The playlist uploader url if it exists, otherwise returns the playlist webpage_url.
|
||||
|
||||
playlist_webpage_url
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
The playlist webpage url if it exists. Otherwise, returns the entry webpage url.
|
||||
|
||||
Release Date Variables
|
||||
----------------------
|
||||
|
||||
release_date
|
||||
~~~~~~~~~~~~
|
||||
The entry’s release date, in YYYYMMDD format. If not present, return the upload date.
|
||||
|
||||
release_date_standardized
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The release date formatted as YYYY-MM-DD
|
||||
|
||||
release_day
|
||||
~~~~~~~~~~~
|
||||
The release day as an integer (no padding).
|
||||
|
||||
release_day_of_year
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
The day of the year, i.e. February 1st returns ``32``
|
||||
|
||||
release_day_of_year_padded
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The release day of year, but padded i.e. February 1st returns "032"
|
||||
|
||||
release_day_of_year_reversed
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The release day, but reversed using ``{total_days_in_year} + 1 - {release_day}``,
|
||||
i.e. February 2nd would have release_day_of_year_reversed of ``365 + 1 - 32`` = ``334``
|
||||
|
||||
release_day_of_year_reversed_padded
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The reversed release day of year, but padded i.e. December 31st returns "001"
|
||||
|
||||
release_day_padded
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
The entry's release day padded to two digits, i.e. the fifth returns "05"
|
||||
|
||||
release_day_reversed
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
The release day, but reversed using ``{total_days_in_month} + 1 - {release_day}``,
|
||||
i.e. August 8th would have release_day_reversed of ``31 + 1 - 8`` = ``24``
|
||||
|
||||
release_day_reversed_padded
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The reversed release day, but padded. i.e. August 30th returns "02".
|
||||
|
||||
release_month
|
||||
~~~~~~~~~~~~~
|
||||
The release month as an integer (no padding).
|
||||
|
||||
release_month_padded
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
The entry's release month padded to two digits, i.e. March returns "03"
|
||||
|
||||
release_month_reversed
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
The release month, but reversed
|
||||
using ``13 - {release_month}``, i.e. March returns ``10``
|
||||
|
||||
release_month_reversed_padded
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The reversed release month, but padded. i.e. November returns "02"
|
||||
|
||||
release_year
|
||||
~~~~~~~~~~~~
|
||||
The entry's release year
|
||||
|
||||
release_year_truncated
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
The last two digits of the release year, i.e. 22 in 2022
|
||||
|
||||
release_year_truncated_reversed
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The release year truncated, but reversed using ``100 - {release_year_truncated}``, i.e.
|
||||
2022 returns ``100 - 22`` = ``78``
|
||||
|
||||
Source Variables
|
||||
----------------
|
||||
|
||||
source_count
|
||||
~~~~~~~~~~~~
|
||||
The source count if it exists, otherwise returns the playlist count.
|
||||
|
||||
source_description
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
The source description if it exists, otherwise returns the playlist description.
|
||||
|
||||
source_index
|
||||
~~~~~~~~~~~~
|
||||
Source index if it exists, otherwise returns ``1``.
|
||||
|
||||
It is recommended to not use this unless you know the source will never add new content
|
||||
(it is easy for this value to change).
|
||||
|
||||
source_index_padded
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
The source index, padded.
|
||||
|
||||
source_title
|
||||
~~~~~~~~~~~~
|
||||
Name of the source (i.e. channel with multiple playlists) if it exists, otherwise
|
||||
returns its playlist_title.
|
||||
|
||||
source_uid
|
||||
~~~~~~~~~~
|
||||
The source unique id if it exists, otherwise returns the playlist unique ID.
|
||||
|
||||
source_uploader
|
||||
~~~~~~~~~~~~~~~
|
||||
The source uploader if it exists, otherwise return the playlist_uploader
|
||||
|
||||
source_uploader_id
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
The source uploader id if it exists, otherwise returns the playlist_uploader_id
|
||||
|
||||
source_uploader_url
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
The source uploader url if it exists, otherwise returns the source webpage_url.
|
||||
|
||||
source_webpage_url
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
The source webpage url if it exists, otherwise returns the playlist webpage url.
|
||||
|
||||
Upload Date Variables
|
||||
---------------------
|
||||
|
||||
upload_date
|
||||
~~~~~~~~~~~
|
||||
The entry’s uploaded date, in YYYYMMDD format. If not present, return today’s date.
|
||||
|
||||
upload_date_standardized
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The uploaded date formatted as YYYY-MM-DD
|
||||
|
||||
upload_day
|
||||
~~~~~~~~~~
|
||||
The upload day as an integer (no padding).
|
||||
|
||||
upload_day_of_year
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
The day of the year, i.e. February 1st returns ``32``
|
||||
|
||||
upload_day_of_year_padded
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The upload day of year, but padded i.e. February 1st returns "032"
|
||||
|
||||
upload_day_of_year_reversed
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The upload day, but reversed using ``{total_days_in_year} + 1 - {upload_day}``,
|
||||
i.e. February 2nd would have upload_day_of_year_reversed of ``365 + 1 - 32`` = ``334``
|
||||
|
||||
upload_day_of_year_reversed_padded
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The reversed upload day of year, but padded i.e. December 31st returns "001"
|
||||
|
||||
upload_day_padded
|
||||
~~~~~~~~~~~~~~~~~
|
||||
The entry's upload day padded to two digits, i.e. the fifth returns "05"
|
||||
|
||||
upload_day_reversed
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
The upload day, but reversed using ``{total_days_in_month} + 1 - {upload_day}``,
|
||||
i.e. August 8th would have upload_day_reversed of ``31 + 1 - 8`` = ``24``
|
||||
|
||||
upload_day_reversed_padded
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The reversed upload day, but padded. i.e. August 30th returns "02".
|
||||
|
||||
upload_month
|
||||
~~~~~~~~~~~~
|
||||
The upload month as an integer (no padding).
|
||||
|
||||
upload_month_padded
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
The entry's upload month padded to two digits, i.e. March returns "03"
|
||||
|
||||
upload_month_reversed
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
The upload month, but reversed using ``13 - {upload_month}``, i.e. March returns ``10``
|
||||
|
||||
upload_month_reversed_padded
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The reversed upload month, but padded. i.e. November returns "02"
|
||||
|
||||
upload_year
|
||||
~~~~~~~~~~~
|
||||
The entry's upload year
|
||||
|
||||
upload_year_truncated
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
The last two digits of the upload year, i.e. 22 in 2022
|
||||
|
||||
upload_year_truncated_reversed
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The upload year truncated, but reversed using ``100 - {upload_year_truncated}``, i.e.
|
||||
2022 returns ``100 - 22`` = ``78``
|
||||
|
||||
Ytdl-Sub Variables
|
||||
------------------
|
||||
|
||||
download_index
|
||||
~~~~~~~~~~~~~~
|
||||
The i'th entry downloaded. NOTE that this is fetched dynamically from the download
|
||||
archive.
|
||||
|
||||
download_index_padded6
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
The download_index padded six digits
|
||||
|
||||
upload_date_index
|
||||
~~~~~~~~~~~~~~~~~
|
||||
The i'th entry downloaded with this upload date.
|
||||
|
||||
upload_date_index_padded
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The upload_date_index padded two digits
|
||||
|
||||
upload_date_index_reversed
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
100 - upload_date_index
|
||||
|
||||
upload_date_index_reversed_padded
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The upload_date_index padded two digits
|
||||
|
||||
ytdl_sub_input_url
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
The input URL used in ytdl-sub to create this entry.
|
||||
9
docs/source/config_reference/scripting/index.rst
Normal file
9
docs/source/config_reference/scripting/index.rst
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
=========
|
||||
Scripting
|
||||
=========
|
||||
|
||||
.. toctree::
|
||||
entry_variables
|
||||
override_variables
|
||||
scripting_functions
|
||||
config_types
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
Override Variables
|
||||
==================
|
||||
|
||||
subscription_indent_i
|
||||
---------------------
|
||||
For subscriptions in the form of
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
Preset | = Indent Value 1:
|
||||
= Indent Value 2:
|
||||
"Subscription Name": "https://..."
|
||||
|
||||
``subscription_indent_1`` and ``subscription_indent_2`` get set to
|
||||
``Indent Value 1`` and ``Indent Value 2``.
|
||||
|
||||
subscription_name
|
||||
-----------------
|
||||
Name of the subscription
|
||||
|
||||
subscription_value
|
||||
------------------
|
||||
For subscriptions in the form of
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
"Subscription Name": "https://..."
|
||||
|
||||
``subscription_value`` gets set to ``https://...``.
|
||||
|
||||
subscription_value_i
|
||||
--------------------
|
||||
For subscriptions in the form of
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
"Subscription Name":
|
||||
- "https://url1.com/..."
|
||||
- "https://url2.com/..."
|
||||
|
||||
``subscription_value_1`` and ``subscription_value_2`` get set to ``https://url1.com/...``
|
||||
and ``https://url2.com/...``. Note that ``subscription_value_1`` also gets set to
|
||||
``subscription_value``.
|
||||
|
||||
474
docs/source/config_reference/scripting/scripting_functions.rst
Normal file
474
docs/source/config_reference/scripting/scripting_functions.rst
Normal file
|
|
@ -0,0 +1,474 @@
|
|||
|
||||
Scripting Functions
|
||||
===================
|
||||
|
||||
Array Functions
|
||||
---------------
|
||||
|
||||
array
|
||||
~~~~~
|
||||
``array(maybe_array: AnyArgument) -> Array``
|
||||
|
||||
Tries to cast an unknown variable type to an Array.
|
||||
|
||||
array_apply
|
||||
~~~~~~~~~~~
|
||||
``array_apply(array: Array, lambda_function: Lambda) -> Array``
|
||||
|
||||
Apply a lambda function on every element in the Array.
|
||||
|
||||
array_at
|
||||
~~~~~~~~
|
||||
``array_at(array: Array, idx: Integer) -> AnyArgument``
|
||||
|
||||
Return the element in the Array at index ``idx``.
|
||||
|
||||
array_contains
|
||||
~~~~~~~~~~~~~~
|
||||
``array_contains(array: Array, value: AnyArgument) -> Boolean``
|
||||
|
||||
Return True if the value exists in the Array. False otherwise.
|
||||
|
||||
array_enumerate
|
||||
~~~~~~~~~~~~~~~
|
||||
``array_enumerate(array: Array, lambda_function: LambdaTwo) -> Array``
|
||||
|
||||
Apply a lambda function on every element in the Array, where each arg
|
||||
passed to the lambda function is ``idx, element`` as two separate args.
|
||||
|
||||
array_extend
|
||||
~~~~~~~~~~~~
|
||||
``array_extend(arrays: Array, ...) -> Array``
|
||||
|
||||
Combine multiple Arrays into a single Array.
|
||||
|
||||
array_flatten
|
||||
~~~~~~~~~~~~~
|
||||
``array_flatten(array: Array) -> Array``
|
||||
|
||||
Flatten any nested Arrays into a single-dimensional Array.
|
||||
|
||||
array_index
|
||||
~~~~~~~~~~~
|
||||
``array_index(array: Array, value: AnyArgument) -> Integer``
|
||||
|
||||
Return the index of the value within the Array if it exists. If it does not, it will
|
||||
throw an error.
|
||||
|
||||
array_product
|
||||
~~~~~~~~~~~~~
|
||||
``array_product(arrays: Array, ...) -> Array``
|
||||
|
||||
Returns the Cartesian product of elements from different arrays
|
||||
|
||||
array_reduce
|
||||
~~~~~~~~~~~~
|
||||
``array_reduce(array: Array, lambda_reduce_function: LambdaReduce) -> AnyArgument``
|
||||
|
||||
Apply a reduce function on pairs of elements in the Array, until one element remains.
|
||||
Executes using the left-most and reduces in the right direction.
|
||||
|
||||
array_reverse
|
||||
~~~~~~~~~~~~~
|
||||
``array_reverse(array: Array) -> Array``
|
||||
|
||||
Reverse an Array.
|
||||
|
||||
array_size
|
||||
~~~~~~~~~~
|
||||
``array_size(array: Array) -> Integer``
|
||||
|
||||
Returns the size of an Array.
|
||||
|
||||
array_slice
|
||||
~~~~~~~~~~~
|
||||
``array_slice(array: Array, start: Integer, end: Optional[Integer]) -> Array``
|
||||
|
||||
Returns the slice of the Array.
|
||||
|
||||
Boolean Functions
|
||||
-----------------
|
||||
|
||||
and
|
||||
~~~
|
||||
``and(values: AnyArgument, ...) -> Boolean``
|
||||
|
||||
``and`` operator. Returns True if all values evaluate to True. False otherwise.
|
||||
|
||||
bool
|
||||
~~~~
|
||||
``bool(value: AnyArgument) -> Boolean``
|
||||
|
||||
Cast any type to a Boolean.
|
||||
|
||||
eq
|
||||
~~
|
||||
``eq(left: AnyArgument, right: AnyArgument) -> Boolean``
|
||||
|
||||
``==`` operator. Returns True if left == right. False otherwise.
|
||||
|
||||
gt
|
||||
~~
|
||||
``gt(left: AnyArgument, right: AnyArgument) -> Boolean``
|
||||
|
||||
``>`` operator. Returns True if left > right. False otherwise.
|
||||
|
||||
gte
|
||||
~~~
|
||||
``gte(left: AnyArgument, right: AnyArgument) -> Boolean``
|
||||
|
||||
``>=`` operator. Returns True if left >= right. False otherwise.
|
||||
|
||||
lt
|
||||
~~
|
||||
``lt(left: AnyArgument, right: AnyArgument) -> Boolean``
|
||||
|
||||
``<`` operator. Returns True if left < right. False otherwise.
|
||||
|
||||
lte
|
||||
~~~
|
||||
``lte(left: AnyArgument, right: AnyArgument) -> Boolean``
|
||||
|
||||
``<=`` operator. Returns True if left <= right. False otherwise.
|
||||
|
||||
ne
|
||||
~~
|
||||
``ne(left: AnyArgument, right: AnyArgument) -> Boolean``
|
||||
|
||||
``!=`` operator. Returns True if left != right. False otherwise.
|
||||
|
||||
not
|
||||
~~~
|
||||
``not(value: Boolean) -> Boolean``
|
||||
|
||||
``not`` operator. Returns the opposite of value.
|
||||
|
||||
or
|
||||
~~
|
||||
``or(values: AnyArgument, ...) -> Boolean``
|
||||
|
||||
``or`` operator. Returns True if any value evaluates to True. False otherwise.
|
||||
|
||||
xor
|
||||
~~~
|
||||
``xor(values: AnyArgument, ...) -> Boolean``
|
||||
|
||||
``^`` operator. Returns True if exactly one value is set to True. False otherwise.
|
||||
|
||||
Conditional Functions
|
||||
---------------------
|
||||
|
||||
if
|
||||
~~
|
||||
``if(condition: Boolean, true: ReturnableArgumentA, false: ReturnableArgumentB) -> Union[ReturnableArgumentA, ReturnableArgumentB]``
|
||||
|
||||
Conditional ``if`` statement that returns the ``true`` or ``false`` parameter
|
||||
depending on the ``condition`` value.
|
||||
|
||||
if_passthrough
|
||||
~~~~~~~~~~~~~~
|
||||
``if_passthrough(maybe_true_arg: ReturnableArgumentA, else_arg: ReturnableArgumentB) -> Union[ReturnableArgumentA, ReturnableArgumentB]``
|
||||
|
||||
Conditional ``if`` statement that returns the ``maybe_true_arg`` if it evaluates to True,
|
||||
otherwise returns ``else_arg``.
|
||||
|
||||
Date Functions
|
||||
--------------
|
||||
|
||||
datetime_strftime
|
||||
~~~~~~~~~~~~~~~~~
|
||||
``datetime_strftime(posix_timestamp: Integer, date_format: String) -> String``
|
||||
|
||||
Converts a posix timestamp to a date using strftime formatting.
|
||||
|
||||
Error Functions
|
||||
---------------
|
||||
|
||||
assert
|
||||
~~~~~~
|
||||
``assert(value: ReturnableArgument, assert_message: String) -> ReturnableArgument``
|
||||
|
||||
Explicitly throw an error with the provided assert message if ``value`` evaluates to False.
|
||||
If it evaluates to True, it will return ``value``.
|
||||
|
||||
throw
|
||||
~~~~~
|
||||
``throw(error_message: String) -> AnyArgument``
|
||||
|
||||
Explicitly throw an error with the provided error message.
|
||||
|
||||
Json Functions
|
||||
--------------
|
||||
|
||||
from_json
|
||||
~~~~~~~~~
|
||||
``from_json(argument: String) -> AnyArgument``
|
||||
|
||||
Converts a JSON string into an actual type.
|
||||
|
||||
Map Functions
|
||||
-------------
|
||||
|
||||
map
|
||||
~~~
|
||||
``map(maybe_mapping: AnyArgument) -> Map``
|
||||
|
||||
Tries to cast an unknown variable type to a Map.
|
||||
|
||||
map_apply
|
||||
~~~~~~~~~
|
||||
``map_apply(mapping: Map, lambda_function: LambdaTwo) -> Array``
|
||||
|
||||
Apply a lambda function on the Map, where each arg
|
||||
passed to the lambda function is ``key, value`` as two separate args.
|
||||
|
||||
map_contains
|
||||
~~~~~~~~~~~~
|
||||
``map_contains(mapping: Map, key: AnyArgument) -> Boolean``
|
||||
|
||||
Returns True if the key is in the Map. False otherwise.
|
||||
|
||||
map_enumerate
|
||||
~~~~~~~~~~~~~
|
||||
``map_enumerate(mapping: Map, lambda_function: LambdaThree) -> Array``
|
||||
|
||||
Apply a lambda function on the Map, where each arg
|
||||
passed to the lambda function is ``idx, key, value`` as three separate args.
|
||||
|
||||
map_get
|
||||
~~~~~~~
|
||||
``map_get(mapping: Map, key: AnyArgument, default: Optional[AnyArgument]) -> AnyArgument``
|
||||
|
||||
Return ``key``'s value within the Map. If ``key`` does not exist, and ``default`` is
|
||||
provided, it will return ``default``. Otherwise, will error.
|
||||
|
||||
map_get_non_empty
|
||||
~~~~~~~~~~~~~~~~~
|
||||
``map_get_non_empty(mapping: Map, key: AnyArgument, default: AnyArgument) -> AnyArgument``
|
||||
|
||||
Return ``key``'s value within the Map. If ``key`` does not exist or is an empty string,
|
||||
return ``default``. Otherwise, will error.
|
||||
|
||||
map_size
|
||||
~~~~~~~~
|
||||
``map_size(mapping: Map) -> Integer``
|
||||
|
||||
Returns the size of a Map.
|
||||
|
||||
Numeric Functions
|
||||
-----------------
|
||||
|
||||
add
|
||||
~~~
|
||||
``add(values: Numeric, ...) -> Numeric``
|
||||
|
||||
``+`` operator. Returns the sum of all values.
|
||||
|
||||
div
|
||||
~~~
|
||||
``div(left: Numeric, right: Numeric) -> Numeric``
|
||||
|
||||
``/`` operator. Returns ``left / right``.
|
||||
|
||||
float
|
||||
~~~~~
|
||||
``float(value: AnyArgument) -> Float``
|
||||
|
||||
Cast to Float.
|
||||
|
||||
int
|
||||
~~~
|
||||
``int(value: AnyArgument) -> Integer``
|
||||
|
||||
Cast to Integer.
|
||||
|
||||
max
|
||||
~~~
|
||||
``max(values: Numeric, ...) -> Numeric``
|
||||
|
||||
Returns max of all values.
|
||||
|
||||
min
|
||||
~~~
|
||||
``min(values: Numeric, ...) -> Numeric``
|
||||
|
||||
Returns min of all values.
|
||||
|
||||
mod
|
||||
~~~
|
||||
``mod(left: Numeric, right: Numeric) -> Numeric``
|
||||
|
||||
``%`` operator. Returns ``left % right``.
|
||||
|
||||
mul
|
||||
~~~
|
||||
``mul(values: Numeric, ...) -> Numeric``
|
||||
|
||||
``*`` operator. Returns the product of all values.
|
||||
|
||||
pow
|
||||
~~~
|
||||
``pow(base: Numeric, exponent: Numeric) -> Numeric``
|
||||
|
||||
``**`` operator. Returns the exponential of the base and exponent value.
|
||||
|
||||
sub
|
||||
~~~
|
||||
``sub(values: Numeric, ...) -> Numeric``
|
||||
|
||||
``-`` operator. Subtracts all values from left to right.
|
||||
|
||||
Regex Functions
|
||||
---------------
|
||||
|
||||
regex_fullmatch
|
||||
~~~~~~~~~~~~~~~
|
||||
``regex_fullmatch(regex: String, string: String) -> Array``
|
||||
|
||||
Checks for entire string to be a match. If a match exists, returns
|
||||
the string as the first element of the Array. If there are capture groups, returns each
|
||||
group as a subsequent element in the Array.
|
||||
|
||||
regex_match
|
||||
~~~~~~~~~~~
|
||||
``regex_match(regex: String, string: String) -> Array``
|
||||
|
||||
Checks for a match only at the beginning of the string. If a match exists, returns
|
||||
the string as the first element of the Array. If there are capture groups, returns each
|
||||
group as a subsequent element in the Array.
|
||||
|
||||
regex_search
|
||||
~~~~~~~~~~~~
|
||||
``regex_search(regex: String, string: String) -> Array``
|
||||
|
||||
Checks for a match anywhere in the string. If a match exists, returns
|
||||
the string as the first element of the Array. If there are capture groups, returns each
|
||||
group as a subsequent element in the Array.
|
||||
|
||||
String Functions
|
||||
----------------
|
||||
|
||||
capitalize
|
||||
~~~~~~~~~~
|
||||
``capitalize(string: String) -> String``
|
||||
|
||||
Capitalize the first character in the string.
|
||||
|
||||
concat
|
||||
~~~~~~
|
||||
``concat(values: String, ...) -> String``
|
||||
|
||||
Concatenate multiple Strings into a single String.
|
||||
|
||||
lower
|
||||
~~~~~
|
||||
``lower(string: String) -> String``
|
||||
|
||||
Lower-case the entire String.
|
||||
|
||||
pad
|
||||
~~~
|
||||
``pad(string: String, length: Integer, char: String) -> String``
|
||||
|
||||
Pads the string to the given length
|
||||
|
||||
pad_zero
|
||||
~~~~~~~~
|
||||
``pad_zero(numeric: Numeric, length: Integer) -> String``
|
||||
|
||||
Pads a numeric with zeros to the given length
|
||||
|
||||
replace
|
||||
~~~~~~~
|
||||
``replace(string: String, old: String, new: String, count: Optional[Integer]) -> String``
|
||||
|
||||
Replace the ``old`` part of the String with the ``new``. Optionally only replace it
|
||||
``count`` number of times.
|
||||
|
||||
slice
|
||||
~~~~~
|
||||
``slice(string: String, start: Integer, end: Optional[Integer]) -> String``
|
||||
|
||||
Returns the slice of the Array.
|
||||
|
||||
string
|
||||
~~~~~~
|
||||
``string(value: AnyArgument) -> String``
|
||||
|
||||
Cast to String.
|
||||
|
||||
titlecase
|
||||
~~~~~~~~~
|
||||
``titlecase(string: String) -> String``
|
||||
|
||||
Capitalize each word in the string.
|
||||
|
||||
upper
|
||||
~~~~~
|
||||
``upper(string: String) -> String``
|
||||
|
||||
Upper-case the entire String.
|
||||
|
||||
Ytdl-Sub Functions
|
||||
------------------
|
||||
|
||||
legacy_bracket_safety
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
``legacy_bracket_safety(value: ReturnableArgument) -> ReturnableArgument``
|
||||
|
||||
ytdl-sub used to replace brackets ('{', '}') with unicode brackets ('{', '}') to not
|
||||
interfere with its legacy variable scripting system. This function replicates that
|
||||
behavior.
|
||||
|
||||
sanitize
|
||||
~~~~~~~~
|
||||
``sanitize(value: AnyArgument) -> String``
|
||||
|
||||
Sanitize a string using yt-dlp's ``sanitize_filename`` method to ensure it's safe to use
|
||||
for file/directory names on any OS.
|
||||
|
||||
sanitize_plex_episode
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
``sanitize_plex_episode(string: String) -> String``
|
||||
|
||||
Sanitize a string using ``sanitize`` and replace numerics with their respective fixed-width
|
||||
numbers. This is used to have Plex avoid scraping numbers like ``4x4`` as the
|
||||
season and/or episode.
|
||||
|
||||
to_date_metadata
|
||||
~~~~~~~~~~~~~~~~
|
||||
``to_date_metadata(yyyymmdd: String) -> Map``
|
||||
|
||||
Takes a date in the form of YYYYMMDD and returns a Map containing:
|
||||
|
||||
- date (String, YYYYMMDD)
|
||||
- date_standardized (String, YYYY-MM-DD)
|
||||
- year (Integer)
|
||||
- month (Integer)
|
||||
- day (Integer)
|
||||
- year_truncated (String, YY from YY[YY])
|
||||
- month_padded (String)
|
||||
- day_padded (String)
|
||||
- year_truncated_reversed (Integer, 100 - year_truncated)
|
||||
- month_reversed (Integer, 13 - month)
|
||||
- month_reversed_padded (String)
|
||||
- day_reversed (Integer, total_days_in_month + 1 - day)
|
||||
- day_reversed_padded (String)
|
||||
- day_of_year (Integer)
|
||||
- day_of_year_padded (String, padded 3)
|
||||
- day_of_year_reversed (Integer, total_days_in_year + 1 - day_of_year)
|
||||
- day_of_year_reversed_padded (String, padded 3)
|
||||
|
||||
to_native_filepath
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
``to_native_filepath(filepath: String) -> String``
|
||||
|
||||
Convert any unix-based path separators ('/') with the OS's native
|
||||
separator.
|
||||
|
||||
truncate_filepath_if_too_long
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
``truncate_filepath_if_too_long(filepath: String) -> String``
|
||||
|
||||
If a file-path is too long for the OS, this function will truncate it while preserving
|
||||
the extension.
|
||||
149
docs/source/config_reference/subscriptions_yaml.rst
Normal file
149
docs/source/config_reference/subscriptions_yaml.rst
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
==================
|
||||
Subscriptions File
|
||||
==================
|
||||
------------------
|
||||
subscriptions.yaml
|
||||
------------------
|
||||
|
||||
The ``subscriptions.yaml`` file is where we use our :ref:`config_reference/config_yaml:presets` in the :ref:`config_reference/config_yaml:config.yaml`
|
||||
to define a ``subscription``: something we want to recurrently download such as a specific
|
||||
channel or playlist.
|
||||
|
||||
The only difference between a ``subscription`` and ``preset`` is that the subscription
|
||||
must have all required fields and ``{override_variables}`` defined so it can perform a download.
|
||||
|
||||
Below is an example that downloads a YouTube playlist:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: config.yaml
|
||||
|
||||
presets:
|
||||
playlist_preset_ex:
|
||||
download:
|
||||
download_strategy: "url"
|
||||
url: "{url}"
|
||||
output_options:
|
||||
output_directory: "{output_directory}/{playlist_name}"
|
||||
file_name: "{playlist_name}.{title}.{ext}"
|
||||
overrides:
|
||||
output_directory: "/path/to/ytdl-sub-videos"
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: subscription.yaml
|
||||
|
||||
my_subscription_name:
|
||||
preset: "playlist_preset_ex"
|
||||
overrides:
|
||||
playlist_name: "diy-playlist"
|
||||
url: "https://youtube.com/playlist?list=UCsvn_Po0SmunchJYtttWpOxMg"
|
||||
|
||||
Our preset ``playlist_preset_ex`` defines three
|
||||
custom variables: ``{output_directory}``, ``{playlist_name}``, and ``{url}``. The subscription sets
|
||||
the ``parent preset`` to ``playlist_preset_ex``, and must define the variables ``{playlist_name}``
|
||||
and ``{url}`` since the preset did not.
|
||||
|
||||
Beautifying Subscriptions
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Subscriptions support using presets as keys, and using keys to set override variables as values.
|
||||
For example:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: subscription.yaml
|
||||
|
||||
TV Show Full Archive:
|
||||
= News:
|
||||
"Breaking News": "https://www.youtube.com/@SomeBreakingNews"
|
||||
|
||||
TV Show Only Recent:
|
||||
= Tech | TV-Y:
|
||||
"Two Minute Papers": "https://www.youtube.com/@TwoMinutePapers"
|
||||
|
||||
Will create two subscriptions named "Breaking News" and "Two Minute Papers", equivalent to:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
"Breaking News":
|
||||
preset:
|
||||
- "TV Show Full Archive"
|
||||
|
||||
overrides:
|
||||
subscription_indent_1: "News"
|
||||
subscription_name: "Breaking News"
|
||||
subscription_value: "https://www.youtube.com/@SomeBreakingNews"
|
||||
|
||||
"Two Minute Papers":
|
||||
preset:
|
||||
- "TV Show Only Recent"
|
||||
|
||||
overrides:
|
||||
subscription_indent_1: "Tech"
|
||||
subscription_indent_2: "TV-Y"
|
||||
subscription_name: "Two Minute Papers"
|
||||
subscription_value: "https://www.youtube.com/@TwoMinutePapers"
|
||||
|
||||
You can provide as many parent presets in the form of ``keys``, and subscription indents as ``= keys``.
|
||||
This can drastically simplify subscription definitions by setting things like so in your
|
||||
parent preset:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
"TV Show Preset":
|
||||
overrides:
|
||||
subscription_indent_1: "default-genre"
|
||||
subscription_indent_2: "default-content-rating"
|
||||
|
||||
tv_show_name: "{subscription_name}"
|
||||
url: "{subscription_value}"
|
||||
genre: "{subscription_indent_1}"
|
||||
content_rating: "{subscription_indent_2}"
|
||||
|
||||
.. _subscription value:
|
||||
|
||||
File Preset
|
||||
~~~~~~~~~~~
|
||||
|
||||
You can apply a preset to all subscriptions in the ``subscription.yaml`` file
|
||||
by using the file-wide ``__preset__``:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: subscription.yaml
|
||||
|
||||
__preset__:
|
||||
preset: "playlist_preset_ex"
|
||||
|
||||
my_subscription_name:
|
||||
overrides:
|
||||
url: "https://youtube.com/playlist?list=UCsvn_Po0SmunchJYtttWpOxMg"
|
||||
playlist_name: "diy-playlist"
|
||||
|
||||
This ``subscription.yaml`` is equivalent to the one above it because all
|
||||
subscriptions automatically set ``__preset__`` as a ``parent preset``.
|
||||
|
||||
|
||||
Subscription Value
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
NOTE: This is deprecated in favor of using the method in :ref:`config_reference/subscriptions_yaml:beautifying subscriptions`.
|
||||
|
||||
With a clever config and use of ``__preset__``, your subscriptions can typically boil
|
||||
down to a name and url. You can set ``__value__`` to the name of an override variable,
|
||||
and use the override variable ``subscription_name`` to achieve one-liner subscriptions.
|
||||
Using the example above, we can do:
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: subscription.yaml
|
||||
|
||||
__preset__:
|
||||
preset:
|
||||
- "tv_show"
|
||||
overrides:
|
||||
tv_show_name: "{subscription_name}"
|
||||
|
||||
__value__: "url"
|
||||
|
||||
# single-line subscription, sets "Brandon Acker" and the subscription value
|
||||
# to the override variables tv_show_name and url
|
||||
"Brandon Acker": "https://www.youtube.com/@brandonacker"
|
||||
|
||||
Traditional subscriptions that can override presets will still work when using ``__value__``.
|
||||
``__value__`` can also be set within a :ref:`config_reference/config_yaml:config.yaml`.
|
||||
|
|
@ -5,55 +5,55 @@ Oct 2023
|
|||
--------
|
||||
|
||||
subscription preset and value
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The use of ``__value__`` will go away in Dec 2023 in favor of the method found in
|
||||
:ref:`beautifying subscriptions`. ``__preset__`` will still be supported for the time being.
|
||||
:ref:`config_reference/subscriptions_yaml:beautifying subscriptions`. ``__preset__`` will still be supported for the time being.
|
||||
|
||||
July 2023
|
||||
---------
|
||||
|
||||
music_tags
|
||||
^^^^^^^^^^
|
||||
~~~~~~~~~~
|
||||
|
||||
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:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
my_example_preset:
|
||||
music_tags:
|
||||
embed_thumbnail: True
|
||||
tags:
|
||||
artist: "Elvis Presley"
|
||||
my_example_preset:
|
||||
music_tags:
|
||||
embed_thumbnail: True
|
||||
tags:
|
||||
artist: "Elvis Presley"
|
||||
|
||||
To the following:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
my_example_preset:
|
||||
embed_thumbnail: True
|
||||
music_tags:
|
||||
artist: "Elvis Presley"
|
||||
my_example_preset:
|
||||
embed_thumbnail: True
|
||||
music_tags:
|
||||
artist: "Elvis Presley"
|
||||
|
||||
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"
|
||||
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"
|
||||
my_example_preset:
|
||||
video_tags:
|
||||
title: "Elvis Presley Documentary"
|
||||
59
docs/source/faq/index.rst
Normal file
59
docs/source/faq/index.rst
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
FAQ
|
||||
===
|
||||
|
||||
Since ytdl-sub is relatively new to the public, there has not been many question asked yet. We will update this as
|
||||
more questions get asked.
|
||||
|
||||
.. contents:: Frequently Asked Questions
|
||||
:depth: 3
|
||||
|
||||
How do I...
|
||||
-----------
|
||||
|
||||
...download age-restricted YouTube videos?
|
||||
''''''''''''''''''''''''''''''''''''''''''
|
||||
See
|
||||
`ytdls recommended way <https://github.com/ytdl-org/youtube-dl#how-do-i-pass-cookies-to-youtube-dl>`_
|
||||
to download your YouTube cookie, then add it to your
|
||||
`ytdl options <https://ytdl-sub.readthedocs.io/en/latest/config.html#ytdl-options>`_ section of your config:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
ytdl_options:
|
||||
cookiefile: "/path/to/cookies/file.txt"
|
||||
|
||||
...automate my downloads?
|
||||
'''''''''''''''''''''''''
|
||||
`This part of the wiki <https://github.com/jmbannon/ytdl-sub/wiki/7.-Automate-Downloading-New-Content-Using-Your-Configs>`_ shows how to set up ``ytdl-sub`` to run in a cron job within Docker.
|
||||
|
||||
There is a bug where...
|
||||
-----------------------
|
||||
|
||||
...date_range is not downloading older videos after I changed the range
|
||||
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
Your preset most likely has ``break_on_existing`` set to True, which will stop downloading additional metadata/videos if the video exists in your download archive. Set the following in your config to skip downloading videos that exist instead of stopping altogether.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
ytdl_options:
|
||||
break_on_existing: False
|
||||
|
||||
After your download your new date_range duration, re-enable ``break_on_existing`` to speed up successive downloads.
|
||||
|
||||
...it is downloading non-English title and description metadata
|
||||
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
Most likely the video has a non-English language set to its 'native' language. You can tell yt-dlp to explicitly download English metadata using
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
ytdl_options:
|
||||
extractor_args:
|
||||
youtube:
|
||||
lang:
|
||||
- "en"
|
||||
|
||||
...Plex is not showing my TV shows correctly
|
||||
''''''''''''''''''''''''''''''''''''''''''''
|
||||
Set the following
|
||||
`Scanner and Agent <https://i.imgur.com/zdZhCLZ.png>`_
|
||||
for your library.
|
||||
5
docs/source/guides/development/index.rst
Normal file
5
docs/source/guides/development/index.rst
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
Development and Contributing
|
||||
============================
|
||||
|
||||
.. toctree::
|
||||
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
Advanced Configuration
|
||||
======================
|
||||
|
||||
If the :doc:`prebuilt presets </prebuilt_presets/index>` aren't suitable for your needs, you may want to set up an advanced configuration.
|
||||
|
||||
Layout of a Config file
|
||||
-----------------------
|
||||
|
||||
The layout of the ``config.yaml`` file is relatively straightforward:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
|
||||
preset_name:
|
||||
plugin1:
|
||||
plugin1_option1: value1
|
||||
|
||||
|
||||
Preset Inheritance
|
||||
------------------
|
||||
140
docs/source/guides/getting_started/automating_downloads.rst
Normal file
140
docs/source/guides/getting_started/automating_downloads.rst
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
Automating Downloads
|
||||
====================
|
||||
|
||||
One of the key capabilities of ``ytdl-sub`` is how well it runs without user input, but to take advantage of this you must set up scheduling to execute the commands at some interval. How you set up this scheduling depends on which version of ``ytdl-sub`` you downloaded.
|
||||
|
||||
|
||||
:ref:`Guide for Docker and Unraid Containers <guides/getting_started/automating_downloads:docker and unraid>`
|
||||
|
||||
:ref:`Guide for Linux <guides/getting_started/automating_downloads:linux>`
|
||||
|
||||
:ref:`Guide for Windows <guides/getting_started/automating_downloads:windows>`
|
||||
|
||||
.. _cron tab manpage: https://man7.org/linux/man-pages/man5/crontab.5.html#EXAMPLE_CRON_FILE
|
||||
|
||||
.. _docker-unraid-setup:
|
||||
|
||||
Docker and Unraid
|
||||
-----------------
|
||||
|
||||
.. tab-set::
|
||||
|
||||
.. tab-item:: GUI Image
|
||||
|
||||
The script that will execute automatically is located at ``/config/ytdl-sub-configs/run-cron``.
|
||||
|
||||
Access your container at http://localhost:8443/, then in the GUI terminal run these commands:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
echo '#!/bin/bash' > /config/ytdl-sub-configs/run_cron
|
||||
echo "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" >> /config/ytdl-sub-configs/run_cron
|
||||
echo "echo 'Cron started, running ytdl-sub...'" >> /config/ytdl-sub-configs/run_cron
|
||||
echo "cd /config/ytdl-sub-configs" >> /config/ytdl-sub-configs/run_cron
|
||||
echo "ytdl-sub --config=config.yaml sub subscriptions.yaml" >> /config/ytdl-sub-configs/run_cron
|
||||
chmod +x /config/ytdl-sub-configs/run_cron
|
||||
chown abc:abc /config/ytdl-sub-configs/run_cron
|
||||
|
||||
You can test the newly created script by running:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
/config/ytdl-sub-configs/run_cron
|
||||
|
||||
To create the cron definition, run the following command:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
echo "# min hour day month weekday command" > /config/crontabs/abc
|
||||
echo " 0 */6 * * * /config/ytdl-sub-configs/run_cron" >> /config/crontabs/abc
|
||||
|
||||
This will run the script every 6 hours. To run every hour, change ``*/6`` to ``*/1``, or to run once a day, change the same value to the hour (in 24hr format) that you want it to run at. See the `cron tab manpage`_ for more options.
|
||||
|
||||
.. tab-item:: Headless Image
|
||||
|
||||
.. _LinuxServer's Universal Cron mod: https://github.com/linuxserver/docker-mods/tree/universal-cron
|
||||
|
||||
The first step is to ensure you have `LinuxServer's Universal Cron mod`_ enabled via the environment variable. For the GUI image, this is already included (no need to add it).
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
services:
|
||||
ytdl-sub:
|
||||
image: ghcr.io/jmbannon/ytdl-sub:latest
|
||||
container_name: ytdl-sub
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/Los_Angeles
|
||||
- DOCKER_MODS=linuxserver/mods:universal-cron # <-- Make sure you have this!
|
||||
volumes:
|
||||
# ensure directories have user permissions
|
||||
- </path/to/ytdl-sub/config>:/config
|
||||
- </path/to/ytdl-sub/tv_shows>:/tv_shows
|
||||
restart: unless-stopped
|
||||
|
||||
This line will tell your container to install and enable cron on start.
|
||||
|
||||
If you had to add this line, you will need to restart your container.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
docker compose restart
|
||||
|
||||
The script that will execute automatically is located at ``/config/run-cron``.
|
||||
|
||||
Access your container from the terminal by running:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
docker exec -itu abc ytdl-sub /bin/bash
|
||||
|
||||
then in the terminal run these commands:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
echo '#!/bin/bash' > /config/ytdl-sub-configs/run_cron
|
||||
echo "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" >> /config/ytdl-sub-configs/run_cron
|
||||
echo "echo 'Cron started, running ytdl-sub...'" >> /config/ytdl-sub-configs/run_cron
|
||||
echo "cd /config/ytdl-sub-configs" >> /config/ytdl-sub-configs/run_cron
|
||||
echo "ytdl-sub --config=config.yaml sub subscriptions.yaml" >> /config/ytdl-sub-configs/run_cron
|
||||
chmod +x /config/ytdl-sub-configs/run_cron
|
||||
chown abc:abc /config/ytdl-sub-configs/run_cron
|
||||
|
||||
You can test the newly created script by running:
|
||||
|
||||
.. code-block::
|
||||
|
||||
/config/run_cron
|
||||
|
||||
To create the cron definition, run the following command:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
echo "# min hour day month weekday command" > /config/crontabs/abc
|
||||
echo " 0 */6 * * * /config/run_cron" >> /config/crontabs/abc
|
||||
|
||||
This will run the script every 6 hours. To run every hour, change ``*/6`` to ``*/1``, or to run once a day, change the same value to the hour (in 24hr format) that you want it to run at. See the `cron tab manpage`_ for more options.
|
||||
|
||||
.. _linux-setup:
|
||||
|
||||
Linux
|
||||
-----
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
crontab -e
|
||||
0 */6 * * * /config/run_cron
|
||||
|
||||
|
||||
|
||||
|
||||
.. _windows-setup:
|
||||
|
||||
Windows
|
||||
-------
|
||||
To be tested (please contact code owner or join the discord server if you can test this out for us)
|
||||
|
||||
.. code-block:: powershell
|
||||
|
||||
ytdl-sub.exe --config \path\to\config\config.yaml sub \path\to\config\subscriptions.yaml
|
||||
15
docs/source/guides/getting_started/examples.rst
Normal file
15
docs/source/guides/getting_started/examples.rst
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
=====================
|
||||
Using Example Configs
|
||||
=====================
|
||||
Copy and paste the examples into local yaml files, modify the
|
||||
``working_directory`` and ``output_directory`` with your desired paths,
|
||||
and perform a dry-run using
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
ytdl-sub \
|
||||
--dry-run \
|
||||
--config path/to/config.yaml \
|
||||
sub path/to/subscriptions.yaml
|
||||
|
||||
This will simulate what a download will look like.
|
||||
25
docs/source/guides/getting_started/first_config.rst
Normal file
25
docs/source/guides/getting_started/first_config.rst
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
Basic Configuration
|
||||
===================
|
||||
|
||||
Your first configuration will look pretty simple:
|
||||
|
||||
.. code-block:: yaml
|
||||
:linenos:
|
||||
|
||||
configuration:
|
||||
working_directory: '.ytdl-sub-downloads'
|
||||
|
||||
|
||||
|
||||
The first two lines in this ``config.yaml`` file are the ``configuration``, and define the ``working_directory``, which is described near the bottom of :ref:`this section <guides/getting_started/index:quick overview of \`\`ytdl-sub\`\`>`
|
||||
|
||||
|
||||
Line 4 begins the definition of your custom ``presets``, with line 5 being the name of your first custom ``preset``.
|
||||
|
||||
Lines 7 and 8 tell ``ytdl-sub`` which :doc:`/prebuilt_presets/index` to expand on; these ``presets`` already indicate that the downloaded files should be:
|
||||
|
||||
- in a format usable by, and with metadata accessible to, Jellyfin
|
||||
- sorted by upload date, and
|
||||
- only uploaded in the last 2 months (and will also delete any files in the media library which were uploaded over 2 months ago)
|
||||
|
||||
Line 11 is an override variable, ``tv_show_directory``, that tells ``ytdl-sub`` where to save your downloaded files once they've been processed, also known as the ``output_directory``. In this case, the downloaded files will be saved to the ``youtube`` folder in the root ``tv_shows`` directory.
|
||||
30
docs/source/guides/getting_started/first_download.rst
Normal file
30
docs/source/guides/getting_started/first_download.rst
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
Initial Download
|
||||
================
|
||||
|
||||
Once you have the ``config.yaml`` and ``subscriptions.yaml`` files created and filled out, you can perform your first download. Access ``ytdl-sub``, navigate to the directory containing your ``config.yaml`` and ``subscriptions.yaml`` files, then run the below command:
|
||||
|
||||
.. tab-set::
|
||||
|
||||
.. tab-item:: Dry run
|
||||
|
||||
A dry run lets you check that your configuration doesn't throw any errors and what the expected output files of actually doing the download are, without actually downloading the full media.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
ytdl-sub --dry-run sub
|
||||
|
||||
.. tab-item:: Normal run
|
||||
|
||||
A normal run will download all files as determined by your ``presets`` and, once processing is finished, move the downloaded and processed files to your ``output_directory``.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
ytdl-sub sub
|
||||
|
||||
.. tab-item:: One-time download
|
||||
|
||||
Sometimes you may only want to download media once, in which case adding them to your ``subscriptions.yaml`` file is unneccessary. As an example, the below code will download the same videos as our subscription file:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
ytdl-sub dl --preset "My Favorite YouTube Channels" --overrides.subscription_name "Rick Astley" --overrides.subscription_value "https://www.youtube.com/@RickAstleyYT/videos"
|
||||
21
docs/source/guides/getting_started/first_sub.rst
Normal file
21
docs/source/guides/getting_started/first_sub.rst
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
Initial Subscription
|
||||
====================
|
||||
|
||||
Your first subscription should look similar to the below:
|
||||
|
||||
.. code-block:: yaml
|
||||
:linenos:
|
||||
|
||||
__preset__:
|
||||
overrides:
|
||||
tv_show_directory: "/tv_shows"
|
||||
|
||||
"My Favorite YouTube Channels":
|
||||
"Rick Astley": "https://www.youtube.com/@RickAstleyYT/videos"
|
||||
|
||||
|
||||
The first three lines in this subscription file define where to save the downloaded files associated with all subscriptions in this file.
|
||||
|
||||
The fifth line in this subscription file is the ``preset``, which provides the "definitions" for the subscription as listed in :doc:`/guides/getting_started/first_config`.
|
||||
|
||||
The sixth line is the actual ``subscription``, named ``Rick Astley``, with a link to a :yt-dlp:`yt-dlp supported site <blob/master/supportedsites.md>`, in this case a YouTube channel.
|
||||
88
docs/source/guides/getting_started/index.rst
Normal file
88
docs/source/guides/getting_started/index.rst
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
Getting Started
|
||||
===============
|
||||
|
||||
Now that you've completed your install of ``ytdl-sub``, it's time to get started. This is a 3-step process:
|
||||
|
||||
- Create your configuration file (if the :doc:`/prebuilt_presets/index` don't fit your needs)
|
||||
- Create your subscription file
|
||||
- Automate starting YTDL-Sub
|
||||
|
||||
Prerequisite Knowledge
|
||||
----------------------
|
||||
|
||||
.. _navigate directories: https://en.wikipedia.org/wiki/Cd_(command)
|
||||
.. _YAML syntax: https://yaml.org/spec/1.2.2/#chapter-2-language-overview
|
||||
|
||||
|
||||
In order to use ``ytdl-sub`` in any of the forms listed in these docs, you will need some basic knowledge.
|
||||
|
||||
Be sure that you:
|
||||
☑ Can `navigate directories`_ in a command line interface (or CLI)
|
||||
|
||||
☑ Have a basic understanding of `YAML syntax`_
|
||||
|
||||
If you plan on using the headless image of ``ytdl-sub``, you:
|
||||
☑ Can use ``nano`` or ``vim`` to edit OR
|
||||
|
||||
☑ Can mount the config directory somewhere you can open it using gui text editors
|
||||
|
||||
Additional useful (but not required) knowledge:
|
||||
☑ Understanding how :yt-dlp:`\ ` works
|
||||
|
||||
|
||||
Quick Overview of ``ytdl-sub``
|
||||
------------------------------
|
||||
|
||||
``ytdl-sub`` uses two types of YAML files:
|
||||
|
||||
- ``config.yaml`` defines ``presets``, which are the "definitions" of your media. ``presets`` "define" how you want your media downloaded, which formats, naming conventions to follow when saving them, etc. These ``presets`` can also inherit other ``presets``, so that you can easily modify an existing ``preset``.
|
||||
- ``subscriptions.yaml`` defines ``subscriptions``, which specify the media we want to recurrently download, like YouTube channels and playlists, SoundCloud artists, or any :yt-dlp:`yt-dlp supported site <blob/master/supportedsites.md>`. ``subscriptions`` use ``presets`` to define how ``ytdl-sub`` should handle downloading, processing, and saving them.
|
||||
|
||||
When ``ytdl-sub`` is run, in its most basic form:
|
||||
|
||||
.. tab-set-code::
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
ytdl-sub sub
|
||||
|
||||
.. code-block:: powershell
|
||||
|
||||
ytdl-sub.exe sub
|
||||
|
||||
``ytdl-sub`` initially downloads all files to a defined ``working_directory``. This is a temporary storage spot for metadata and media files so that errors during processing- if they occur- don't affect your existing media library. Once all file processing is complete, your media files are moved to the ``output_directory``.
|
||||
|
||||
Ready to Start?
|
||||
---------------
|
||||
|
||||
Now that you have installed ``ytdl-sub``, checked your skills, and gotten a bit of background on how ``ytdl-sub`` functions, read through the articles below to get started:
|
||||
|
||||
:doc:`Step 1: Initial Subscriptions <first_sub>`
|
||||
|
||||
:doc:`Step 2: Your First Download <first_download>`
|
||||
|
||||
:doc:`Step 3: Automating Downloads <automating_downloads>`
|
||||
|
||||
Want to go a step further?
|
||||
|
||||
If you want to use atypical paths or specific configuration options, check out :doc:`Basic Configuration <first_config>`
|
||||
|
||||
For tips on creating your own presets when the prebuilt presets aren't cutting it, check out :doc:`Advanced Configuration <advanced_configuration>`
|
||||
|
||||
Other docs that may be of use:
|
||||
|
||||
:doc:`/prebuilt_presets/index`
|
||||
|
||||
:doc:`examples`
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
:caption: Getting Started Guide
|
||||
:maxdepth: 1
|
||||
|
||||
first_sub
|
||||
first_download
|
||||
automating_downloads
|
||||
first_config
|
||||
advanced_configuration
|
||||
examples
|
||||
7
docs/source/guides/index.rst
Normal file
7
docs/source/guides/index.rst
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Guides
|
||||
======
|
||||
|
||||
.. toctree::
|
||||
install/index
|
||||
getting_started/index
|
||||
development/index
|
||||
43
docs/source/guides/install/agnostic.rst
Normal file
43
docs/source/guides/install/agnostic.rst
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
====================
|
||||
Environment Agnostic
|
||||
====================
|
||||
|
||||
The PIP install method is not recommended; use of this method may cause unintended requirement conflicts if you have other locally installed apps that depend on ffmpeg.
|
||||
|
||||
PIP Install
|
||||
--------------
|
||||
You can install our
|
||||
`PyPI package <https://pypi.org/project/ytdl-sub/>`_.
|
||||
Both ffmpeg and Python 3.10 or greater are required.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
python3 -m pip install -U ytdl-sub
|
||||
|
||||
Install for Development
|
||||
=======================
|
||||
|
||||
These environment-agnostic methods of installing ``ytdl-sub`` are meant for local development of ``ytdl-sub``. If you want to contribute your changes, please read :doc:`/guides/development/index`.
|
||||
|
||||
Local Install
|
||||
--------------
|
||||
With a Python 3.10 virtual environment, you can clone and install the repo.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git clone https://github.com/jmbannon/ytdl-sub.git
|
||||
cd ytdl-sub
|
||||
|
||||
pip install -e .
|
||||
|
||||
Local Docker Build
|
||||
-------------------
|
||||
Run ``make docker`` in the root directory of this repo to build the image. This
|
||||
will build the python wheel and install it in the Dockerfile.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git clone https://github.com/jmbannon/ytdl-sub.git
|
||||
cd ytdl-sub
|
||||
|
||||
make docker
|
||||
155
docs/source/guides/install/docker.rst
Normal file
155
docs/source/guides/install/docker.rst
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
======
|
||||
Docker
|
||||
======
|
||||
|
||||
For automating ``subscriptions.yaml`` downloads to pull new media, see :ref:`this page <guides/getting_started/automating_downloads:docker and unraid>` on how to set up a cron job in any of the docker containers.
|
||||
|
||||
The ``ytdl-sub`` Docker images use :lsio:`LSIO-based images <\ >` and install ytdl-sub on top. There are two flavors to choose from.
|
||||
|
||||
.. margin::
|
||||
|
||||
.. tip::
|
||||
|
||||
The recommended docker image is the GUI image.
|
||||
|
||||
:ref:`Docker Compose <guides/install/docker:install with docker compose>` is the recommended way of setting up a ``ytdl-sub`` docker container.
|
||||
|
||||
GUI Image
|
||||
---------
|
||||
|
||||
The GUI image uses LSIO's :lsio-gh:`docker-code-server image` for its base image. More info on other code-server environment variables can be found within its documentation.
|
||||
|
||||
After starting, code-server will be running at http://localhost:8443. Open this page in a browser to access and interact with ``ytdl-sub``.
|
||||
|
||||
Headless Image
|
||||
--------------
|
||||
|
||||
The headless image uses LSIO's :lsio-gh:`docker-baseimage-alpine image` for its base image. Execute the following command to access and interact with ``ytdl-sub``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
docker exec -u abc -it ytdl-sub /bin/bash
|
||||
|
||||
Install with Docker Compose
|
||||
---------------------------
|
||||
|
||||
Docker Compose is an easy "set it and forget it" install method. Follow the instructions below to create a ``compose.yaml`` file for your chosen ``ytdl-sub`` image.
|
||||
|
||||
.. margin::
|
||||
|
||||
.. important::
|
||||
|
||||
Set the PUID and PGID to the UID and GID associated with the user you want to own the downloaded files. Setting these values to root UID and GID may create issues with your media managers.
|
||||
|
||||
.. tab-set::
|
||||
|
||||
.. tab-item:: GUI Image
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: compose.yaml
|
||||
|
||||
services:
|
||||
ytdl-sub:
|
||||
image: ghcr.io/jmbannon/ytdl-sub-gui:latest
|
||||
container_name: ytdl-sub
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/Los_Angeles
|
||||
volumes:
|
||||
- <path/to/ytdl-sub/config>:/config
|
||||
- <path/to/tv_shows>:/tv_shows # optional
|
||||
- <path/to/movies>:/movies # optional
|
||||
- <path/to/music_videos>:/music_videos # optional
|
||||
- <path/to/music>:/music # optional
|
||||
ports:
|
||||
- 8443:8443
|
||||
restart: unless-stopped
|
||||
|
||||
.. tab-item:: Headless Image
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: compose.yaml
|
||||
|
||||
services:
|
||||
ytdl-sub:
|
||||
image: ghcr.io/jmbannon/ytdl-sub:latest
|
||||
container_name: ytdl-sub
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/Los_Angeles
|
||||
- DOCKER_MODS=linuxserver/mods:universal-cron
|
||||
volumes:
|
||||
- <path/to/ytdl-sub/config>:/config
|
||||
- <path/to/tv_shows>:/tv_shows # optional
|
||||
- <path/to/movies>:/movies # optional
|
||||
- <path/to/music_videos>:/music_videos # optional
|
||||
- <path/to/music>:/music # optional
|
||||
restart: unless-stopped
|
||||
|
||||
Device Passthrough
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
For CPU or GPU passthrough, you must use either the GUI image or the headless Ubuntu image
|
||||
``ghcr.io/jmbannon/ytdl-sub:ubuntu-latest``.
|
||||
|
||||
The docker-compose examples use the GUI image.
|
||||
|
||||
CPU Passthrough
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: yaml
|
||||
:emphasize-lines: 5-6
|
||||
:caption: compose.yaml
|
||||
|
||||
services:
|
||||
ytdl-sub:
|
||||
image: ghcr.io/jmbannon/ytdl-sub-gui:latest
|
||||
container_name: ytdl-sub
|
||||
devices:
|
||||
- /dev/dri:/dev/dri # CPU passthrough
|
||||
restart: unless-stopped
|
||||
|
||||
GPU Passthrough
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
.. Awe
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: compose.yaml
|
||||
:emphasize-lines: 5-13
|
||||
|
||||
services:
|
||||
ytdl-sub:
|
||||
image: ghcr.io/jmbannon/ytdl-sub-gui:latest
|
||||
container_name: ytdl-sub
|
||||
environment:
|
||||
- ..
|
||||
- NVIDIA_DRIVER_CAPABILITIES=all # Nvidia ENV args
|
||||
- NVIDIA_VISIBLE_DEVICES=all
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices:
|
||||
- capabilities: ["gpu"] # GPU passthrough
|
||||
restart: unless-stopped
|
||||
|
||||
Docker CLI
|
||||
----------
|
||||
|
||||
If you prefer to only run the container once, you can use the CLI command instead. The following command is for the gui image, and will not restart if it comes down for any reason. See `the Docker reference <https://docs.docker.com/engine/reference/run/>`_ for further information on the parameters and other options you can use.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
docker run -d \
|
||||
--name=ytdl-sub \
|
||||
-e PUID=1000 \
|
||||
-e PGID=1000 \
|
||||
-e TZ=America/Los_Angeles \
|
||||
-p 8443:8443 \
|
||||
-v <path/to/ytdl-sub/config>:/config \
|
||||
-v <OPTIONAL/path/to/tv_shows>:/tv_shows \
|
||||
-v <OPTIONAL/path/to/movies>:/movies \
|
||||
-v <OPTIONAL/path/to/music_videos>:/music_videos \
|
||||
-v <OPTIONAL/path/to/music>:/music \
|
||||
ghcr.io/jmbannon/ytdl-sub-gui:latest
|
||||
34
docs/source/guides/install/index.rst
Normal file
34
docs/source/guides/install/index.rst
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
Install by Platform
|
||||
===================
|
||||
``ytdl-sub`` can be installed on the following platforms.
|
||||
|
||||
All installations require a 64-bit CPU. 32-bit is not supported.
|
||||
|
||||
.. margin::
|
||||
|
||||
.. tip::
|
||||
|
||||
The recommended install method of ``ytdl-sub`` is one of our :doc:`docker containers </guides/install/docker>`. For install on Unraid, check out our :unraid:`unraid community apps <community/apps?q=ytdl-sub#r>`.
|
||||
|
||||
:doc:`/guides/install/docker`
|
||||
|
||||
:doc:`/guides/install/unraid`
|
||||
|
||||
:doc:`/guides/install/linux`
|
||||
|
||||
:doc:`/guides/install/windows`
|
||||
|
||||
:doc:`/guides/install/agnostic`
|
||||
|
||||
|
||||
|
||||
Once you've completed your installation, please refer to the :doc:`../getting_started/index` guide for next steps
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
docker
|
||||
linux
|
||||
unraid
|
||||
windows
|
||||
agnostic
|
||||
50
docs/source/guides/install/linux.rst
Normal file
50
docs/source/guides/install/linux.rst
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
=====
|
||||
Linux
|
||||
=====
|
||||
|
||||
``ytdl-sub`` should be installable using any Linux package manager, and requires ffmpeg to be installed.
|
||||
|
||||
|
||||
.. tab-set::
|
||||
|
||||
.. tab-item:: Linux
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
curl -L -o ytdl-sub https://github.com/jmbannon/ytdl-sub/releases/latest/download/ytdl-sub
|
||||
chmod +x ytdl-sub
|
||||
ytdl-sub -h
|
||||
|
||||
You can also install using yt-dlp's ffmpeg builds. This ensures your ffmpeg is up to date:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
curl -L -o ffmpeg.tar.gz https://github.com/yt-dlp/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-linux64-gpl.tar.xz
|
||||
tar -xf ffmpeg.tar.gz
|
||||
chmod +x ffmpeg-master-latest-linux64-gpl/bin/ffmpeg
|
||||
chmod +x ffmpeg-master-latest-linux64-gpl/bin/ffprobe
|
||||
|
||||
# May need sudo / root permissions to perform
|
||||
mv ffmpeg-master-latest-linux64-gpl/bin/ffmpeg /usr/bin/ffmpeg
|
||||
mv ffmpeg-master-latest-linux64-gpl/bin/ffprobe /usr/bin/ffprobe
|
||||
|
||||
.. tab-item:: Linux ARM
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
curl -L -o ytdl-sub https://github.com/jmbannon/ytdl-sub/releases/latest/download/ytdl-sub_aarch64
|
||||
chmod +x ytdl-sub
|
||||
ytdl-sub -h
|
||||
|
||||
You can also install using yt-dlp's ffmpeg builds. This ensures your ffmpeg is up to date:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
curl -L -o ffmpeg.tar.gz https://github.com/yt-dlp/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-linuxarm64-gpl.tar.xz
|
||||
tar -xf ffmpeg.tar.gz
|
||||
chmod +x ffmpeg-master-latest-linuxarm64-gpl/bin/ffmpeg
|
||||
chmod +x ffmpeg-master-latest-linuxarm64-gpl/bin/ffprobe
|
||||
|
||||
# May need sudo / root permissions to perform
|
||||
mv ffmpeg-master-latest-linuxarm64-gpl/bin/ffmpeg /usr/bin/ffmpeg
|
||||
mv ffmpeg-master-latest-linuxarm64-gpl/bin/ffprobe /usr/bin/ffprobe
|
||||
3
docs/source/guides/install/unraid.rst
Normal file
3
docs/source/guides/install/unraid.rst
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
Unraid
|
||||
--------------
|
||||
You can install our :unraid:`unraid community apps <community/apps?q=ytdl-sub#r>` through the `Unraid Community Apps plugin <https://unraid.net/community/apps>`_. Uses Docker under the hood.
|
||||
15
docs/source/guides/install/windows.rst
Normal file
15
docs/source/guides/install/windows.rst
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
Windows
|
||||
--------------
|
||||
From powershell, run:
|
||||
|
||||
.. code-block:: powershell
|
||||
|
||||
# Download ffmpeg/ffprobe dependencies from yt-dlp
|
||||
curl.exe -L -o ffmpeg.zip https://github.com/yt-dlp/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-win64-gpl.zip
|
||||
tar -xf ffmpeg.zip
|
||||
move "ffmpeg-master-latest-win64-gpl\bin\ffmpeg.exe" "ffmpeg.exe"
|
||||
move "ffmpeg-master-latest-win64-gpl\bin\ffprobe.exe" "ffprobe.exe"
|
||||
|
||||
# Download ytdl-sub
|
||||
curl.exe -L -o ytdl-sub.exe https://github.com/jmbannon/ytdl-sub/releases/latest/download/ytdl-sub.exe
|
||||
ytdl-sub.exe -h
|
||||
22
docs/source/index.rst
Normal file
22
docs/source/index.rst
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
ytdl-sub User Guide
|
||||
===================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:titlesonly:
|
||||
|
||||
introduction
|
||||
guides/index
|
||||
prebuilt_presets/index
|
||||
usage
|
||||
config_reference/index
|
||||
faq/index
|
||||
deprecation_notices
|
||||
|
||||
.. note:: End goal similar to: https://picard-docs.musicbrainz.org/en/functions/list_by_type.html
|
||||
Initial plans:
|
||||
|
||||
- pages for each prebuilt preset, showing which variables that can be overridden to do different things (i.e. episode_title)
|
||||
- new wiki walkthrough that uses the README config as a starting point, and gradually adds custom changes
|
||||
- pages for how to enable custom metadata agents for Kodi/Plex/jellyfin
|
||||
- page dedicated to explaining the structure of a config (it's only lightly touched on now, many folks struggle to understand the 'pattern' of presets/plugins/overrides)
|
||||
43
docs/source/introduction.rst
Normal file
43
docs/source/introduction.rst
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
=================
|
||||
What is ytdl-sub?
|
||||
=================
|
||||
|
||||
.. _yt-dlp: https://github.com/yt-dlp/yt-dlp
|
||||
.. _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
|
||||
|
||||
``ytdl-sub`` is a command-line tool that downloads media via `yt-dlp`_ and prepares it for your favorite media player (`Kodi`_, `Jellyfin`_, `Plex`_, `Emby`_, modern music players).
|
||||
|
||||
Visual examples
|
||||
===============
|
||||
|
||||
.. figure:: https://user-images.githubusercontent.com/10107080/182677243-b4184e51-9780-4094-bd40-ea4ff58555d0.PNG
|
||||
:alt: The Jellyfin web interface, showing the thumbnails of various YouTube shows.
|
||||
|
||||
Youtube channels as TV shows in Jellyfin
|
||||
|
||||
.. figure:: https://user-images.githubusercontent.com/10107080/182677256-43aeb029-0c3f-4648-9fd2-352b9666b262.PNG
|
||||
:alt: The Jellyfin web interace, showing the thumbnails of various music videos starring the Red Hot Chili Peppers
|
||||
|
||||
Music videos and concerts in Jellyfin
|
||||
|
||||
.. figure:: https://user-images.githubusercontent.com/10107080/182677268-d1bf2ff0-9b9c-4a04-98ec-443a67ada734.png
|
||||
:alt: The Kodi app interface, showing a list of artists available to watch under the "Music videos" heading
|
||||
|
||||
Music videos and concerts in Kodi
|
||||
|
||||
.. figure:: https://user-images.githubusercontent.com/10107080/182685415-06adf477-3dd3-475d-bbcd-53b0152b9f0a.PNG
|
||||
:alt: The MusicBee app interface, showing a list of album artists and the thumbnails of all downloaded songs produced by the currently selected artist
|
||||
|
||||
SoundCloud albums and singles in MusicBee
|
||||
|
||||
|
||||
Why ytdl-sub?
|
||||
-------------
|
||||
There is a lack of open-source tools to download media and generate metadata to play it in these players. Most solutions involve using multiple tools or bash scripts to achieve this. ``ytdl-sub`` aims to consolidate all of this logic into a single easy-to-use application that can run automatically once configured.
|
||||
|
||||
Why download instead of stream?
|
||||
-------------------------------
|
||||
We believe it is important to download what you like because there is no guarantee it will stay online forever. We also believe it is important to download it in such a way that it is easy to consume. Most solutions today force you to watch/listen to your downloaded content via file system or web browser. ``ytdl-sub`` aims to format downloaded content for any media player.
|
||||
37
docs/source/prebuilt_presets/helpers.rst
Normal file
37
docs/source/prebuilt_presets/helpers.rst
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
==============
|
||||
Helper Presets
|
||||
==============
|
||||
|
||||
Common presets are not usable by themselves- setting one of these as the sole preset of your subscription and attempting to download will not work. But you can add these presets to quickly modify an existing preset to better suit your needs.
|
||||
|
||||
Best A/V Quality
|
||||
----------------
|
||||
|
||||
Add the following preset to download the best available video and audio quality, and remux it into an MP4 container:
|
||||
|
||||
``best_video_quality``
|
||||
|
||||
|
||||
Max 1080p Video
|
||||
---------------
|
||||
|
||||
Add the following preset to download the best available audio and video quality, with the video not greater than 1080p, and remux it into an MP4 container:
|
||||
|
||||
``max_1080p``
|
||||
|
||||
Chunk Initial Download
|
||||
----------------------
|
||||
|
||||
If you are archiving a large channel, ``ytdl-sub`` will try pulling each video's metadata from newest to oldest before starting any downloads. It is a long process and not ideal. A better method is to chunk the process by using the following preset:
|
||||
|
||||
``chunk_initial_download``
|
||||
|
||||
It will download videos starting from the oldest one, and only download 20 at a time. You can
|
||||
change this number by setting:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
ytdl_options:
|
||||
max_downloads: 30 # Desired number to download per invocation
|
||||
|
||||
Once the entire channel is downloaded, remove this preset. Then it will pull metadata from newest to oldest again, and stop pulling additional metadata once it reaches a video that has already been downloaded.
|
||||
14
docs/source/prebuilt_presets/index.rst
Normal file
14
docs/source/prebuilt_presets/index.rst
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
================
|
||||
Prebuilt Presets
|
||||
================
|
||||
|
||||
``ytdl-sub`` offers a number of built-in presets using best practices for formatting
|
||||
media in various players. For advanced users, you can review the prebuilt preset
|
||||
definitions :doc:`here </config_reference/prebuilt_presets/index>`.
|
||||
|
||||
.. toctree::
|
||||
:titlesonly:
|
||||
|
||||
helpers
|
||||
tv_shows
|
||||
music
|
||||
3
docs/source/prebuilt_presets/music.rst
Normal file
3
docs/source/prebuilt_presets/music.rst
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
=============
|
||||
Music Presets
|
||||
=============
|
||||
171
docs/source/prebuilt_presets/tv_shows.rst
Normal file
171
docs/source/prebuilt_presets/tv_shows.rst
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
===============
|
||||
TV Show Presets
|
||||
===============
|
||||
|
||||
Player-Specific Presets
|
||||
=======================
|
||||
|
||||
``ytdl-sub`` provides player-specific versions of certain presets, which apply settings to optimize the downloads for that player.
|
||||
|
||||
The following actions are taken based on the indicated player:
|
||||
|
||||
|
||||
Jellyfin
|
||||
~~~~~~~~
|
||||
* Places any season-specific poster art in the main show folder
|
||||
* Generates NFO tags
|
||||
|
||||
Kodi
|
||||
~~~~
|
||||
* Everything that the Jellyfin version does
|
||||
* Turns on :ref:`config_reference/plugins:kodi_safe`, replacing characters that would break kodi with safer characters
|
||||
|
||||
Plex
|
||||
~~~~
|
||||
* :ref:`Special sanitization <config_reference/scripting/entry_variables:title_sanitized_plex>` of numbers so Plex doesn't recognize numbers that are part of the title as the episode number
|
||||
* Converts all downloaded videos to the mp4 format
|
||||
* Places any season-specific poster art into the season folder
|
||||
|
||||
----------------------------------------------
|
||||
|
||||
Generic Presets
|
||||
===============
|
||||
|
||||
There are two main methods for downloading and formatting videos as a TV show.
|
||||
|
||||
TV Show by Date
|
||||
---------------
|
||||
|
||||
TV Show by Date will organize something like a YouTube channel or playlist into a tv show, where seasons and episodes are organized using upload date.
|
||||
|
||||
Plug and Play Presets
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You can use any of these presets in your ``subscriptions.yaml`` as a "One size fits all" solution- they should set all appropriate values. These will organize seasons by year and episodes by month, then day.
|
||||
|
||||
Must define ``tv_show_directory``
|
||||
|
||||
* ``"Kodi TV Show by Date"``
|
||||
* ``"Jellyfin TV Show by Date"``
|
||||
* ``"Plex TV Show by Date"``
|
||||
|
||||
Advanced Usage
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
If you prefer a different organization method, you can instead apply multiple presets to your subscriptions.
|
||||
|
||||
You will need a base of one of the below:
|
||||
|
||||
* ``kodi_tv_show_by_date``
|
||||
* ``jellyfin_tv_show_by_date``
|
||||
* ``plex_tv_show_by_date``
|
||||
|
||||
And then add one of these:
|
||||
|
||||
* ``season_by_year__episode_by_month_day``
|
||||
* ``season_by_year_month__episode_by_day``
|
||||
* ``season_by_year__episode_by_month_day_reversed``
|
||||
|
||||
* Episode numbers are reversed, meaning more recent episodes appear at the top of a season by having a lower value.
|
||||
* ``season_by_year__episode_by_download_index``
|
||||
|
||||
* Episodes are numbered by the download order. NOTE that this is fetched using the length of the download archive. Do not use if you intend to remove old videos.
|
||||
|
||||
An example of a subscription that will be played on Kodi, organized by year with the most recent episode at the top (having a lower episode number), with a genre of "Pop":
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: subscriptions.yaml
|
||||
|
||||
__preset__:
|
||||
overrides:
|
||||
tv_show_directory: "/tv_shows"
|
||||
|
||||
kodi_tv_show_by_date:
|
||||
season_by_year_episode_by_month_day_reversed:
|
||||
= Pop:
|
||||
"Rick A": "https://www.youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw"
|
||||
|
||||
You can also choose to combine multiple URLs into one show. This will result in your videos being downloaded to the same folder, and the episode numbers being shared between them (so you won't have two episode 10's, for example). Note that you may :ytdl-sub-gh:`experience issues <issues/833>` if you use more than 20 URLs at this time.
|
||||
|
||||
.. code-block:: yaml
|
||||
:caption: subscriptions.yaml
|
||||
|
||||
__preset__:
|
||||
overrides:
|
||||
tv_show_directory: "/tv_shows"
|
||||
|
||||
kodi_tv_show_by_date:
|
||||
season_by_year_episode_by_month_day_reversed:
|
||||
= Pop:
|
||||
"~Rick A":
|
||||
url: "https://www.youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw"
|
||||
url2: "https://www.youtube.com/@just.rick_6"
|
||||
|
||||
|
||||
TV Show Collection
|
||||
------------------
|
||||
|
||||
TV Show Collections are made up of multiple URLs, where each URL is a season.
|
||||
If a video belongs to multiple URLs (i.e. a channel and a channel's playlist),
|
||||
it will resolve to the bottom-most season, as defined in the subscription.
|
||||
|
||||
Two main use cases of a collection are:
|
||||
1. Organize a YouTube channel TV show where Season 1 contains any video
|
||||
not in a 'season playlist', Season 2 for 'Playlist A', Season 3 for
|
||||
'Playlist B', etc.
|
||||
2. Organize one or more YouTube channels/playlists, where each season
|
||||
represents a separate channel/playlist.
|
||||
|
||||
Player Presets
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
* ``kodi_tv_show_collection``
|
||||
* ``jellyfin_tv_show_collection``
|
||||
* ``plex_tv_show_collection``
|
||||
|
||||
Episode Formatting Presets
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* ``season_by_collection__episode_by_year_month_day``
|
||||
* ``season_by_collection__episode_by_year_month_day_reversed``
|
||||
* ``season_by_collection__episode_by_playlist_index``
|
||||
|
||||
* Only use playlist_index episode formatting for playlists that will be fully downloaded once and never again. Otherwise, indices can change.
|
||||
* ``season_by_collection__episode_by_playlist_index_reversed``
|
||||
|
||||
Season Presets
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
* ``collection_season_1``
|
||||
* ``collection_season_2``
|
||||
* ``collection_season_3``
|
||||
* ``collection_season_4``
|
||||
* ``...``
|
||||
* ``collection_season_40``
|
||||
|
||||
Example
|
||||
~~~~~~~
|
||||
|
||||
A preset/subscription requires specifying a player, episode formatting, and
|
||||
one or more season presets, with the following override variables:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
rick_a_tv_show_collection:
|
||||
preset:
|
||||
- "jellyfin_tv_show_collection"
|
||||
- "season_by_collection__episode_by_year_month_day_reversed"
|
||||
- "collection_season_1"
|
||||
- "collection_season_2"
|
||||
overrides:
|
||||
# required
|
||||
tv_show_name: "Rick A"
|
||||
tv_show_directory: "/path/to/youtube_shows"
|
||||
collection_season_1_url: "https://www.youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw"
|
||||
collection_season_1_name: "All Videos"
|
||||
collection_season_2_url: "https://www.youtube.com/playlist?list=PLlaN88a7y2_plecYoJxvRFTLHVbIVAOoc"
|
||||
collection_season_2_name: "Official Music Videos"
|
||||
# can be modified from their default value
|
||||
# tv_show_genre: "ytdl-sub"
|
||||
# episode_title: "{upload_date_standardized} - {title}"
|
||||
# episode_description: "{webpage_url}"
|
||||
3
docs/source/requirements.txt
Normal file
3
docs/source/requirements.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
sphinx-book-theme==1.0.1
|
||||
sphinx-copybutton==0.5.2
|
||||
sphinx-design==0.5.0
|
||||
|
|
@ -3,7 +3,7 @@ Usage
|
|||
|
||||
.. code-block::
|
||||
|
||||
ytdl-sub [GENERAL OPTIONS] {sub,dl,view} [COMMAND OPTIONS]
|
||||
ytdl-sub [GENERAL OPTIONS] {sub,dl,view} [COMMAND OPTIONS]
|
||||
|
||||
For Windows users, it would be ``ytdl-sub.exe``
|
||||
|
||||
|
|
@ -43,28 +43,28 @@ Download a single subscription in the form of CLI arguments.
|
|||
|
||||
.. code-block::
|
||||
|
||||
ytdl-sub [GENERAL OPTIONS] dl [SUBSCRIPTION ARGUMENTS]
|
||||
ytdl-sub [GENERAL OPTIONS] dl [SUBSCRIPTION ARGUMENTS]
|
||||
|
||||
``SUBSCRIPTION ARGUMENTS`` are exactly the same as YAML arguments, but use periods (``.``) instead
|
||||
of indents for specifying YAML from the CLI. For example, you can represent this subscription:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
rick_a:
|
||||
preset:
|
||||
- "tv_show"
|
||||
overrides:
|
||||
tv_show_name: "Rick A"
|
||||
url: "https://www.youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw"
|
||||
rick_a:
|
||||
preset:
|
||||
- "tv_show"
|
||||
overrides:
|
||||
tv_show_name: "Rick A"
|
||||
url: "https://www.youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw"
|
||||
|
||||
Using the command:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
ytdl-sub dl \
|
||||
--preset "tv_show" \
|
||||
--overrides.tv_show_name "Rick A" \
|
||||
--overrides.url: "https://www.youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw"
|
||||
ytdl-sub dl \
|
||||
--preset "tv_show" \
|
||||
--overrides.tv_show_name "Rick A" \
|
||||
--overrides.url: "https://www.youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw"
|
||||
|
||||
See how to shorten commands using
|
||||
`download aliases <https://ytdl-sub.readthedocs.io/en/latest/config.html#ytdl_sub.config.config_validator.ConfigOptions.dl_aliases>`_.
|
||||
Loading…
Reference in a new issue