add support for single youtube video

This commit is contained in:
jbannon 2022-04-09 06:31:13 +00:00
parent c0e31a28c3
commit 764678367f
7 changed files with 81 additions and 25 deletions

View file

@ -27,7 +27,6 @@ presets:
music_videos:
youtube:
download_strategy: "playlist"
ytdl_options:
format: 'best'
ignoreerrors: True

View file

@ -18,30 +18,42 @@
# artist: "DeLorra"
# genre: "Synthwave / Electronic"
#
bl00dwave:
preset: "soundcloud_with_id3_tags"
soundcloud:
username: bl00dwave
output_options:
output_directory: "/tmp/bl00dwave"
overrides:
artist: "bl00dwave"
genre: "Synthwave / Electronic"
#bl00dwave:
# preset: "soundcloud_with_id3_tags"
# soundcloud:
# username: bl00dwave
# output_options:
# output_directory: "/tmp/bl00dwave"
# overrides:
# artist: "bl00dwave"
# genre: "Synthwave / Electronic"
#
#tom_petty:
# preset: "music_videos"
# youtube:
# download_strategy: "playlist"
# playlist_id: PLoopXDarluPBnuxs4PTC55Sc_2ShAXC0i
# output_options:
# output_directory: "/tmp/Tom Petty"
# overrides:
# artist: "Tom Petty and the Heartbreakers"
#
#rammstein:
# preset: "music_videos"
# youtube:
# download_strategy: "playlist"
# playlist_id: "PLVTLbc6i-h_iuhdwUfuPDLFLXG2QQnz-x"
# output_options:
# output_directory: "/tmp/Rammstein"
# overrides:
# artist: "Rammstein"
tom_petty:
gogo_video_test:
preset: "music_videos"
youtube:
playlist_id: PLoopXDarluPBnuxs4PTC55Sc_2ShAXC0i
download_strategy: "video"
video_id: "2RHTiXvELNg"
output_options:
output_directory: "/tmp/Tom Petty"
output_directory: "/tmp/gogos"
overrides:
artist: "Tom Petty and the Heartbreakers"
rammstein:
preset: "music_videos"
youtube:
playlist_id: "PLVTLbc6i-h_iuhdwUfuPDLFLXG2QQnz-x"
output_options:
output_directory: "/tmp/Rammstein"
overrides:
artist: "Rammstein"
artist: "The Gogos"

View file

@ -18,6 +18,11 @@ class YoutubeDownloader(Downloader):
"""Returns full playlist url"""
return f"https://youtube.com/playlist?list={playlist_id}"
@classmethod
def video_url(cls, video_id: str) -> str:
"""Returns full video url"""
return f"https://youtube.com/watch?v={video_id}"
def _download_with_metadata(self, url: str) -> None:
"""
Do not get entries from the extract info, let it write to the info.json file and load
@ -30,6 +35,10 @@ class YoutubeDownloader(Downloader):
}
_ = self.extract_info(ytdl_options_overrides=ytdl_metadata_override, url=url)
def download_video(self, video_id: str) -> YoutubeVideo:
entry = self.extract_info(url=self.video_url(video_id))
return YoutubeVideo(**entry)
def download_playlist(self, playlist_id: str) -> List[YoutubeVideo]:
"""
Downloads all videos in a playlist

View file

@ -3,6 +3,9 @@ from ytdl_subscribe.subscriptions.subscription import Subscription
from ytdl_subscribe.validators.config.source_options.youtube_validators import (
YoutubePlaylistSourceValidator,
)
from ytdl_subscribe.validators.config.source_options.youtube_validators import (
YoutubeVideoSourceValidator,
)
class YoutubePlaylistSubscription(Subscription[YoutubePlaylistSourceValidator]):
@ -13,3 +16,12 @@ class YoutubePlaylistSubscription(Subscription[YoutubePlaylistSourceValidator]):
for entry in entries:
self.post_process_entry(entry)
class YoutubeVideoSubscription(Subscription[YoutubeVideoSourceValidator]):
def extract_info(self):
entry = self.get_downloader(YoutubeDownloader).download_video(
video_id=self.source_options.video_id.value
)
self.post_process_entry(entry)

View file

@ -13,6 +13,9 @@ from ytdl_subscribe.validators.config.source_options.source_validators import So
from ytdl_subscribe.validators.config.source_options.youtube_validators import (
YoutubePlaylistSourceValidator,
)
from ytdl_subscribe.validators.config.source_options.youtube_validators import (
YoutubeVideoSourceValidator,
)
class DownloadStrategyValidator(StrictDictValidator, ABC):
@ -61,4 +64,7 @@ class SoundcloudDownloadStrategyValidator(DownloadStrategyValidator):
class YoutubeDownloadStrategyValidator(DownloadStrategyValidator):
_download_strategy_to_source_mapping = {"playlist": YoutubePlaylistSourceValidator}
_download_strategy_to_source_mapping = {
"playlist": YoutubePlaylistSourceValidator,
"video": YoutubeVideoSourceValidator,
}

View file

@ -8,3 +8,11 @@ class YoutubePlaylistSourceValidator(YoutubeSourceValidator):
def __init__(self, name, value):
super().__init__(name, value)
self.playlist_id = self._validate_key("playlist_id", StringValidator)
class YoutubeVideoSourceValidator(YoutubeSourceValidator):
_required_keys = {"video_id"}
def __init__(self, name, value):
super().__init__(name, value)
self.video_id = self._validate_key("video_id", StringValidator)

View file

@ -1,6 +1,8 @@
import copy
from typing import Any
from typing import List
from typing import Optional
from typing import Type
import yaml
from mergedeep import mergedeep
@ -8,6 +10,7 @@ from mergedeep import mergedeep
from ytdl_subscribe.subscriptions.soundcloud import SoundcloudAlbumsAndSinglesSubscription
from ytdl_subscribe.subscriptions.subscription import Subscription
from ytdl_subscribe.subscriptions.youtube import YoutubePlaylistSubscription
from ytdl_subscribe.subscriptions.youtube import YoutubeVideoSubscription
from ytdl_subscribe.validators.base.strict_dict_validator import StrictDictValidator
from ytdl_subscribe.validators.base.validators import StringValidator
from ytdl_subscribe.validators.config.config_file_validator import ConfigFileValidator
@ -21,6 +24,9 @@ from ytdl_subscribe.validators.config.source_options.soundcloud_validators impor
from ytdl_subscribe.validators.config.source_options.youtube_validators import (
YoutubePlaylistSourceValidator,
)
from ytdl_subscribe.validators.config.source_options.youtube_validators import (
YoutubeVideoSourceValidator,
)
class SubscriptionValidator(StrictDictValidator):
@ -65,11 +71,15 @@ class SubscriptionValidator(StrictDictValidator):
)
def to_subscription(self) -> Subscription:
subscription_class: Optional[Type[Subscription]] = None
if isinstance(self.preset.subscription_source, SoundcloudAlbumsAndSinglesSourceValidator):
subscription_class = SoundcloudAlbumsAndSinglesSubscription
elif isinstance(self.preset.subscription_source, YoutubePlaylistSourceValidator):
subscription_class = YoutubePlaylistSubscription
else:
elif isinstance(self.preset.subscription_source, YoutubeVideoSourceValidator):
subscription_class = YoutubeVideoSubscription
if subscription_class is None:
raise ValueError("subscription source class not found")
return subscription_class(