diff --git a/docs/config/index.rst b/docs/config.rst similarity index 90% rename from docs/config/index.rst rename to docs/config.rst index 0645cb36..5e502c32 100644 --- a/docs/config/index.rst +++ b/docs/config.rst @@ -73,6 +73,34 @@ soundcloud: albums_and_singles .. autoclass:: ytdl_sub.downloaders.soundcloud_downloader.SoundcloudAlbumsAndSinglesDownloadOptions() :members: :inherited-members: + :member-order: bysource + +Required: Output Options +^^^^^^^^^^^^^^^^^^^^^^^^ +TODO + +YTDL Options +^^^^^^^^^^^^ +TODO + +Overrides +^^^^^^^^^ +TODO + +Plugins +^^^^^^^ + +Music Tags +"""""""""" +TODO + +NFO +""" +TODO + +NFO Output Directory +"""""""""""""""""""" +TODO Format Variables ---------------- @@ -97,4 +125,3 @@ Soundcloud Variables :members: :inherited-members: :undoc-members: - diff --git a/docs/examples.rst b/docs/examples.rst new file mode 100644 index 00000000..c88fb86f --- /dev/null +++ b/docs/examples.rst @@ -0,0 +1,48 @@ +Examples +======== + +This page shows how you can use ytdl-sub for various use cases. These +are the configs I personally use and have incorporated as part of the e2e tests. + +Each example has a ``config.yaml`` and ``subscription.yaml``. The config defines +`how` you format your media, whereas the subscription defines `what` you +download plus some additional configuring if needed. + +Also note that ``kodi`` examples are applicable for ``jellyfin``, ``emby``, and +``plex`` with the +`XBMC Movies `_ +or +`XBMC TV Show `_ +Plex importer. We would like to improve Plex support, please chime in +`here `_ +if you have experience with importing custom videos with metadata. + +Kodi/Jellyfin TV Shows +---------------------- + +config.yaml +^^^^^^^^^^^ + +.. include:: ../examples/kodi_tv_shows_config.yaml + :literal: + +subscriptions.yaml +^^^^^^^^^^^^^^^^^^ + +.. include:: ../examples/kodi_tv_shows_subscriptions.yaml + :literal: + +Kodi/Jellyfin Music Videos +---------------------- + +config.yaml +^^^^^^^^^^^ + +.. include:: ../examples/kodi_music_videos_config.yaml + :literal: + +subscriptions.yaml +^^^^^^^^^^^^^^^^^^ + +.. include:: ../examples/kodi_music_videos_subscriptions.yaml + :literal: \ No newline at end of file diff --git a/docs/examples/index.rst b/docs/examples/index.rst deleted file mode 100644 index 2f3a6915..00000000 --- a/docs/examples/index.rst +++ /dev/null @@ -1,10 +0,0 @@ -Examples -======== - -Hello, WIP - -.. toctree:: - :titlesonly: - :maxdepth: 2 - - kodi_tv_shows diff --git a/docs/examples/kodi_tv_shows.rst b/docs/examples/kodi_tv_shows.rst deleted file mode 100644 index 02fcd1eb..00000000 --- a/docs/examples/kodi_tv_shows.rst +++ /dev/null @@ -1,12 +0,0 @@ -Kodi/Jellyfin TV Shows -====================== - -Config - -.. include:: ../../examples/kodi_tv_shows_config.yaml - :literal: - - - -.. include:: ../../examples/kodi_tv_shows_subscriptions.yaml - :literal: diff --git a/docs/getting_started.rst b/docs/getting_started.rst new file mode 100644 index 00000000..ff78131e --- /dev/null +++ b/docs/getting_started.rst @@ -0,0 +1,58 @@ +Getting Started +=============== + +The goal of this app is automate the downloading and metadata creation of audio and video files, then place the files +in a directory that gets read by your media player/server. Everyone stores and watches their media differently, so +we strive for comprehensive and simplistic customization to fit all self-hosting needs. + +Audio metadata is just a matter of adding tags to the audio file. The backend plugin we use supports practically every +common audio file type, so there should (hopefully) be no issues getting audio recognized by your media player. + +Video metadata on the other hand, is currently geared toward generating Kodi/Jellyfin/Emby NFO files. Plex uses metadata +written within MP4 containers - we do not support that currently, but could be added as a plugin in the future. + +Usage Ideas +----------- +Below is a list ways you can use ytdl-sub to download and consume different kinds of media in the representation you +prefer. + +* Download a Youtube channel + * Store the channel as its own TV Show + * Use the channel's avatar as the TV Show poster, banner as the fanart + * Format the season and episodes as ``Season YYYY/sYYYY.eMMDD - Video Title.mp4`` to easily navigate videos by upload date + * Store the channel as a single season under a TV Show shared with other channels + * Only download audio, store it as a Podcast + * Only keep video/audio uploaded in the last `N` days + * Great for news or podcast based channels + +* Download a Youtube playlist + * Download an artist's music videos playlist, store each video as a Kodi/Jellyfin/Emby Music Video + * Only download the audio, store the playlist as an album + +* Manually download a single Youtube video + * Store it as a Movie + * Download a one-hit wonder and store it as a Kodi/Jellyfin/Emby Music Video + +* Download a soundcloud artist's discography + * Add tags and album cover images so it shows up nicely in your music player + +If you want to jump the gun to see how ytdl-sub can be configured to do these things, head over to the +:doc:`examples `. + +Install +------- +Once we are ready for our first release, we will add this package to pypi. Then, +we plan to create a docker image that uses the +`LinuxServer.io `_ +base image, and hopefully become a part of their fleet someday. + +Until then, you will have to clone this repo and run it using python 3.10 + +.. code-block:: Bash + + git clone https://github.com/jmbannon/ytdl-sub.git + cd ytdl-sub + + pip install -e . + + diff --git a/docs/getting_started/index.rst b/docs/getting_started/index.rst deleted file mode 100644 index 7d80396e..00000000 --- a/docs/getting_started/index.rst +++ /dev/null @@ -1,19 +0,0 @@ -Getting Started -=============== - -The goal of this app is automate the downloading and metadata creation of audio and video files, then place the files -in a directory that gets read by your media player/server. Everyone stores and watches their media differently, so -we strive for comprehensive and simplistic customization to fit all self-hosting needs. - -Audio metadata is just a matter of adding tags to the audio file. The backend plugin we use supports practically every -common audio file type, so there should (hopefully) be no issues getting audio recognized by your media player. - -Video metadata on the other hand, is currently geared toward generating Kodi/Jellyfin/Emby NFO files. Plex uses metadata -written within MP4 containers - we do not support that currently, but could be added as a plugin in the future. - -.. toctree:: - :titlesonly: - :maxdepth: 2 - - usage_ideas - install diff --git a/docs/getting_started/install.rst b/docs/getting_started/install.rst deleted file mode 100644 index 50db1a92..00000000 --- a/docs/getting_started/install.rst +++ /dev/null @@ -1,2 +0,0 @@ -Install -======= \ No newline at end of file diff --git a/docs/getting_started/usage_ideas.rst b/docs/getting_started/usage_ideas.rst deleted file mode 100644 index 1905d20b..00000000 --- a/docs/getting_started/usage_ideas.rst +++ /dev/null @@ -1,28 +0,0 @@ -Usage Ideas -=========== -Below is a list ways you can use ytdl-sub to download and consume different kinds of media in the representation you -prefer. - -* Download a Youtube channel - * Store the channel as its own TV Show - * Use the channel's avatar as the TV Show poster, banner as the fanart - * Format the season and episodes as ``Season YYYY/sYYYY.eMMDD - Video Title.mp4`` to easily navigate videos by upload date - * Store the channel as a single season under a TV Show shared with other channels - * Only download audio, store it as a Podcast - * Only keep video/audio uploaded in the last `N` days - * Great for news or podcast based channels - -* Download a Youtube playlist - * Download an artist's music videos playlist, store each video as a Kodi/Jellyfin/Emby Music Video - * Only download the audio, store the playlist as an album - -* Manually download a single Youtube video - * Store it as a Movie - * Download a one-hit wonder and store it as a Kodi/Jellyfin/Emby Music Video - -* Download a soundcloud artist's discography - * Add tags and album cover images so it shows up nicely in your music player - -If you want to jump the gun to see how ytdl-sub can be configured to do these things, head over to the -:doc:`examples <../examples/index>`. - diff --git a/docs/index.rst b/docs/index.rst index 68327f33..bc38ce90 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -6,9 +6,10 @@ python app that strives to automate downloading media and preparing it for consumption in your favorite media player in the most hassle-free way possible. -If you are new to ytdl-sub, head over to the Getting Started page. This guide -shows how you can install ytdl-sub, configure it to download various types -of media, and start downloading. +If you are new to ytdl-sub, head over to the +:doc:`Getting Started ` +page. This guide shows how you can install ytdl-sub, configure it to download +various types of media, and start downloading. Contents ======== @@ -16,6 +17,6 @@ Contents .. toctree:: :maxdepth: 3 - getting_started/index - config/index - examples/index + getting_started + config + examples diff --git a/src/ytdl_sub/downloaders/soundcloud_downloader.py b/src/ytdl_sub/downloaders/soundcloud_downloader.py index af55b8d6..23f1a2e6 100644 --- a/src/ytdl_sub/downloaders/soundcloud_downloader.py +++ b/src/ytdl_sub/downloaders/soundcloud_downloader.py @@ -31,7 +31,7 @@ class SoundcloudDownloaderOptions(DownloaderValidator, ABC): @property def skip_premiere_tracks(self) -> bool: """ - True to skip tracks that require purchasing. False otherwise. + Optional. True to skip tracks that require purchasing. False otherwise. Defaults to True. """ return self._skip_premiere_tracks.value @@ -80,7 +80,7 @@ class SoundcloudAlbumsAndSinglesDownloadOptions(SoundcloudDownloaderOptions): @property def username(self) -> str: """ - The Soundcloud username + Required. The Soundcloud username found in the url of their page. """ return self._username.value diff --git a/src/ytdl_sub/downloaders/youtube_downloader.py b/src/ytdl_sub/downloaders/youtube_downloader.py index 4d82059f..676ccf9c 100644 --- a/src/ytdl_sub/downloaders/youtube_downloader.py +++ b/src/ytdl_sub/downloaders/youtube_downloader.py @@ -59,7 +59,15 @@ class YoutubeVideoDownloaderOptions(YoutubeDownloaderOptions): def __init__(self, name, value): super().__init__(name, value) - self.video_id = self._validate_key("video_id", StringValidator) + self._video_id = self._validate_key("video_id", StringValidator) + + @property + def video_id(self) -> str: + """ + Required. The ID of the video. Looks like the ``VMAPTo7RVDo`` in + ``youtube.com/watch?v=VMAPTo7RVDo``. + """ + return self._video_id.value class YoutubeVideoDownloader(YoutubeDownloader[YoutubeVideoDownloaderOptions, YoutubeVideo]): @@ -73,8 +81,7 @@ class YoutubeVideoDownloader(YoutubeDownloader[YoutubeVideoDownloaderOptions, Yo def download(self) -> List[YoutubeVideo]: """Download a single Youtube video""" - video_id = self.download_options.video_id.value - video_url = self.video_url(video_id=video_id) + video_url = self.video_url(video_id=self.download_options.video_id) entry_dict = self.extract_info(url=video_url) return [YoutubeVideo(entry_dict=entry_dict, working_directory=self.working_directory)] @@ -89,7 +96,14 @@ class YoutubePlaylistDownloaderOptions(YoutubeDownloaderOptions): def __init__(self, name, value): super().__init__(name, value) - self.playlist_id = self._validate_key("playlist_id", StringValidator) + self._playlist_id = self._validate_key("playlist_id", StringValidator) + + @property + def playlist_id(self) -> str: + """ + Required. The playlist's ID. + """ + return self._playlist_id.value class YoutubePlaylistDownloader( @@ -107,8 +121,7 @@ class YoutubePlaylistDownloader( """ Downloads all videos in a Youtube playlist """ - playlist_id = self.download_options.playlist_id.value - playlist_url = self.playlist_url(playlist_id=playlist_id) + playlist_url = self.playlist_url(playlist_id=self.download_options.playlist_id) playlist_videos: List[YoutubePlaylistVideo] = [] entry_dicts = self.extract_info_via_info_json(url=playlist_url) @@ -145,8 +158,8 @@ class YoutubeChannelDownloaderOptions(YoutubeDownloaderOptions, DateRangeValidat @property def channel_id(self) -> str: """ - The channel's ID. Not to be confused with the username. It should look something like - `UCsvn_Po0SmunchJYOWpOxMg`. You can get this by opening a video and clicking on the + Required. The channel's ID. Not to be confused with the username. It should look something + like `UCsvn_Po0SmunchJYOWpOxMg`. You can get this by opening a video and clicking on the channel's avatar image to take you to their channel, then check the url. """ return self.channel_id