add support for single youtube video
This commit is contained in:
parent
c0e31a28c3
commit
764678367f
7 changed files with 81 additions and 25 deletions
|
|
@ -27,7 +27,6 @@ presets:
|
|||
|
||||
music_videos:
|
||||
youtube:
|
||||
download_strategy: "playlist"
|
||||
ytdl_options:
|
||||
format: 'best'
|
||||
ignoreerrors: True
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
Loading…
Reference in a new issue