wip
This commit is contained in:
parent
02cf8f83e7
commit
0b5d96116c
3 changed files with 291 additions and 79 deletions
|
@ -1,4 +1,4 @@
|
||||||
import yt_dlp
|
"""YouTube DownLoad."""
|
||||||
|
|
||||||
# playlists
|
# playlists
|
||||||
# …
|
# …
|
||||||
|
@ -14,7 +14,6 @@ import yt_dlp
|
||||||
# playlist / entries
|
# playlist / entries
|
||||||
# …
|
# …
|
||||||
|
|
||||||
|
|
||||||
# videos
|
# videos
|
||||||
# id
|
# id
|
||||||
# channel
|
# channel
|
||||||
|
@ -36,8 +35,80 @@ import yt_dlp
|
||||||
# thumbnails
|
# thumbnails
|
||||||
# view_count
|
# view_count
|
||||||
|
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from enum import Enum
|
||||||
|
from rwx import Object
|
||||||
|
from rwx.log import stream as log
|
||||||
|
|
||||||
|
import yt_dlp
|
||||||
|
|
||||||
|
|
||||||
|
class Action(Enum):
|
||||||
|
DOWNLOAD_VIDEO = 0
|
||||||
|
EXTRACT_PLAYLIST = 1
|
||||||
|
EXTRACT_PLAYLISTS = 2
|
||||||
|
EXTRACT_VIDEO = 3
|
||||||
|
EXTRACT_VIDEOS = 4
|
||||||
|
|
||||||
|
|
||||||
|
class Tab(Object, ABC):
|
||||||
|
"""YouTube Tab."""
|
||||||
|
|
||||||
|
URL_ROOT = "https://youtube.com"
|
||||||
|
|
||||||
|
def __init__(self, object_id: str) -> None:
|
||||||
|
"""Set object id.
|
||||||
|
|
||||||
|
:param object_id: object identifier
|
||||||
|
:type object_id: str
|
||||||
|
"""
|
||||||
|
self.object_id = object_id
|
||||||
|
log.info(self.object_id)
|
||||||
|
self.url = self.get_url()
|
||||||
|
log.info(self.url)
|
||||||
|
|
||||||
|
def get_options(self) -> dict:
|
||||||
|
"""Return options for the action.
|
||||||
|
|
||||||
|
:rtype: dict
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
"extract_flat": True,
|
||||||
|
"skip_download": True,
|
||||||
|
}
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_url(self) -> str:
|
||||||
|
"""Return URL to access for object.
|
||||||
|
|
||||||
|
:rtype: str
|
||||||
|
"""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def dl(opt: dict) -> yt_dlp.YoutubeDL:
|
||||||
|
options = {**opt, "ignoreerrors": False, "quiet": False}
|
||||||
|
log.info(options)
|
||||||
|
return yt_dlp.YoutubeDL(options)
|
||||||
|
|
||||||
|
|
||||||
|
class Playlist(Tab):
|
||||||
|
|
||||||
|
def __init__(self, playlist_id: str) -> None:
|
||||||
|
self.playlist_id = playlist_id
|
||||||
|
|
||||||
|
def get_url(self) -> str:
|
||||||
|
return f"{Tab.URL_ROOT}/playlist?list={self.playlist_id}"
|
||||||
|
|
||||||
|
|
||||||
|
class Playlists(Tab):
|
||||||
|
|
||||||
|
def __init__(self, channel_id: str) -> None:
|
||||||
|
self.channel_id = channel_id
|
||||||
|
|
||||||
|
def get_url(self) -> str:
|
||||||
|
return f"{Tab.URL_ROOT}/channel/{self.channel_id}/playlists"
|
||||||
|
|
||||||
|
|
||||||
# video
|
|
||||||
# id
|
# id
|
||||||
# title
|
# title
|
||||||
# formats
|
# formats
|
||||||
|
@ -50,93 +121,57 @@ import yt_dlp
|
||||||
# categories
|
# categories
|
||||||
# tags
|
# tags
|
||||||
# fulltitle
|
# fulltitle
|
||||||
|
class Video(Tab):
|
||||||
|
|
||||||
|
def __init__(self, video_id: str) -> None:
|
||||||
|
self.video_id = video_id
|
||||||
|
|
||||||
|
def get_url(self) -> str:
|
||||||
|
return f"{Tab.URL_ROOT}/watch?v={self.video_id}"
|
||||||
|
|
||||||
|
|
||||||
def extract_playlist(playlist_id):
|
class Videos(Tab):
|
||||||
options = {
|
|
||||||
"quiet": False,
|
|
||||||
"extract_flat": True,
|
|
||||||
"force_generic_extractor": False,
|
|
||||||
"ignoreerrors": False,
|
|
||||||
}
|
|
||||||
url = f"https://youtube.com/playlist?list={playlist_id}"
|
|
||||||
print(f"""\
|
|
||||||
{options}
|
|
||||||
|
|
||||||
{url}
|
def __init__(self, channel_id: str) -> None:
|
||||||
|
self.channel_id = channel_id
|
||||||
|
|
||||||
""")
|
def get_url(self) -> str:
|
||||||
with yt_dlp.YoutubeDL(options) as y:
|
return f"{Tab.URL_ROOT}/channel/{self.channel_id}/videos"
|
||||||
return y.extract_info(url, download=False)
|
|
||||||
|
|
||||||
|
|
||||||
def extract_playlists(channel_id):
|
def command(action: Action):
|
||||||
options = {
|
match action:
|
||||||
"quiet": False,
|
case Action.DOWNLOAD_VIDEO:
|
||||||
"extract_flat": True,
|
|
||||||
"force_generic_extractor": False,
|
|
||||||
"ignoreerrors": False,
|
|
||||||
"skip_download": True,
|
|
||||||
}
|
|
||||||
url = f"https://youtube.com/channel/{channel_id}/playlists"
|
|
||||||
print(f"""\
|
|
||||||
{options}
|
|
||||||
|
|
||||||
{url}
|
|
||||||
|
|
||||||
""")
|
|
||||||
with yt_dlp.YoutubeDL(options) as y:
|
|
||||||
return y.extract_info(url, download=False)
|
|
||||||
|
|
||||||
|
|
||||||
def download_video(video_id):
|
|
||||||
options = {
|
options = {
|
||||||
"format": "bestvideo[ext=mp4]+bestaudio[ext=mp4]",
|
"format": "bestvideo[ext=mp4]+bestaudio[ext=mp4]",
|
||||||
"outtmpl": "%(id)s.%(ext)s",
|
"outtmpl": "%(id)s.%(ext)s",
|
||||||
"writesubtitles": True,
|
"writesubtitles": True,
|
||||||
"writethumbnail": True,
|
"writethumbnail": True,
|
||||||
"ignoreerrors": False,
|
|
||||||
}
|
}
|
||||||
url = f"https://youtu.be/{video_id}"
|
log.info(options)
|
||||||
print(f"""\
|
with dl(options) as youtube:
|
||||||
{options}
|
match action:
|
||||||
|
case Action.DOWNLOAD_VIDEO:
|
||||||
{url}
|
youtube.download([url])
|
||||||
|
case _:
|
||||||
""")
|
youtube.extract_info(url, download=False)
|
||||||
with yt_dlp.YoutubeDL(options) as y:
|
|
||||||
return y.download([url])
|
|
||||||
|
|
||||||
|
|
||||||
def extract_video(video_id):
|
def download_video(video_id: str):
|
||||||
options = {
|
return command(Action.DOWNLOAD_VIDEO, video_id)
|
||||||
"quiet": False,
|
|
||||||
"ignoreerrors": False,
|
|
||||||
}
|
|
||||||
url = f"https://youtu.be/{video_id}"
|
|
||||||
print(f"""\
|
|
||||||
{options}
|
|
||||||
|
|
||||||
{url}
|
|
||||||
|
|
||||||
""")
|
|
||||||
with yt_dlp.YoutubeDL(options) as y:
|
|
||||||
return y.extract_info(url, download=False)
|
|
||||||
|
|
||||||
|
|
||||||
def extract_videos(channel_id):
|
def extract_playlist(playlist_id: str):
|
||||||
options = {
|
return command(Action.EXTRACT_PLAYLIST, playlist_id)
|
||||||
"quiet": False,
|
|
||||||
"extract_flat": True,
|
|
||||||
"force_generic_extractor": False,
|
|
||||||
"ignoreerrors": False,
|
|
||||||
}
|
|
||||||
url = f"https://youtube.com/channel/{channel_id}/videos"
|
|
||||||
print(f"""\
|
|
||||||
{options}
|
|
||||||
|
|
||||||
{url}
|
|
||||||
|
|
||||||
""")
|
def extract_playlists(channel_id: str):
|
||||||
with yt_dlp.YoutubeDL(options) as y:
|
return command(Action.EXTRACT_PLAYLISTS, channel_id)
|
||||||
return y.extract_info(url, download=False)
|
|
||||||
|
|
||||||
|
def extract_video(video_id: str):
|
||||||
|
return command(Action.EXTRACT_VIDEO, video_id)
|
||||||
|
|
||||||
|
|
||||||
|
def extract_videos(channel_id: str):
|
||||||
|
return command(Action.EXTRACT_VIDEOS, channel_id)
|
||||||
|
|
177
rwx/sw/yt_dlp/__init__.py
Normal file
177
rwx/sw/yt_dlp/__init__.py
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
"""YouTube."""
|
||||||
|
|
||||||
|
# playlists
|
||||||
|
# …
|
||||||
|
# entries
|
||||||
|
|
||||||
|
# playlists / entries
|
||||||
|
# title
|
||||||
|
# id
|
||||||
|
|
||||||
|
# playlist
|
||||||
|
# entries
|
||||||
|
|
||||||
|
# playlist / entries
|
||||||
|
# …
|
||||||
|
|
||||||
|
# videos
|
||||||
|
# id
|
||||||
|
# channel
|
||||||
|
# channel_id
|
||||||
|
# title
|
||||||
|
# channel_follower_count
|
||||||
|
# description
|
||||||
|
# tags
|
||||||
|
# thumbnails
|
||||||
|
# uploader_id
|
||||||
|
# uploader
|
||||||
|
# entries
|
||||||
|
|
||||||
|
# videos / entries
|
||||||
|
# id
|
||||||
|
# title
|
||||||
|
# description truncated
|
||||||
|
# duration
|
||||||
|
# thumbnails
|
||||||
|
# view_count
|
||||||
|
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from enum import Enum
|
||||||
|
from rwx import Object
|
||||||
|
from rwx.log import stream as log
|
||||||
|
|
||||||
|
import yt_dlp
|
||||||
|
|
||||||
|
|
||||||
|
class Action(Enum):
|
||||||
|
DOWNLOAD_VIDEO = 0
|
||||||
|
EXTRACT_PLAYLIST = 1
|
||||||
|
EXTRACT_PLAYLISTS = 2
|
||||||
|
EXTRACT_VIDEO = 3
|
||||||
|
EXTRACT_VIDEOS = 4
|
||||||
|
|
||||||
|
|
||||||
|
class Tab(Object, ABC):
|
||||||
|
"""YouTube Tab."""
|
||||||
|
|
||||||
|
URL_ROOT = "https://youtube.com"
|
||||||
|
|
||||||
|
def __init__(self, object_id: str) -> None:
|
||||||
|
"""Set object id.
|
||||||
|
|
||||||
|
:param object_id: object identifier
|
||||||
|
:type object_id: str
|
||||||
|
"""
|
||||||
|
self.object_id = object_id
|
||||||
|
log.info(self.object_id)
|
||||||
|
self.url = self.get_url()
|
||||||
|
log.info(self.url)
|
||||||
|
|
||||||
|
def get_options(self) -> dict:
|
||||||
|
"""Return options for the action.
|
||||||
|
|
||||||
|
:rtype: dict
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
"extract_flat": True,
|
||||||
|
"skip_download": True,
|
||||||
|
}
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_url(self) -> str:
|
||||||
|
"""Return URL to access for object.
|
||||||
|
|
||||||
|
:rtype: str
|
||||||
|
"""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def dl(opt: dict) -> yt_dlp.YoutubeDL:
|
||||||
|
options = {**opt, "ignoreerrors": False, "quiet": False}
|
||||||
|
log.info(options)
|
||||||
|
return yt_dlp.YoutubeDL(options)
|
||||||
|
|
||||||
|
|
||||||
|
class Playlist(Tab):
|
||||||
|
|
||||||
|
def __init__(self, playlist_id: str) -> None:
|
||||||
|
self.playlist_id = playlist_id
|
||||||
|
|
||||||
|
def get_url(self) -> str:
|
||||||
|
return f"{Tab.URL_ROOT}/playlist?list={self.playlist_id}"
|
||||||
|
|
||||||
|
|
||||||
|
class Playlists(Tab):
|
||||||
|
|
||||||
|
def __init__(self, channel_id: str) -> None:
|
||||||
|
self.channel_id = channel_id
|
||||||
|
|
||||||
|
def get_url(self) -> str:
|
||||||
|
return f"{Tab.URL_ROOT}/channel/{self.channel_id}/playlists"
|
||||||
|
|
||||||
|
|
||||||
|
# id
|
||||||
|
# title
|
||||||
|
# formats
|
||||||
|
# thumbnails
|
||||||
|
# thumbnail
|
||||||
|
# description
|
||||||
|
#
|
||||||
|
# duration
|
||||||
|
# view_count
|
||||||
|
# categories
|
||||||
|
# tags
|
||||||
|
# fulltitle
|
||||||
|
class Video(Tab):
|
||||||
|
|
||||||
|
def __init__(self, video_id: str) -> None:
|
||||||
|
self.video_id = video_id
|
||||||
|
|
||||||
|
def get_url(self) -> str:
|
||||||
|
return f"{Tab.URL_ROOT}/watch?v={self.video_id}"
|
||||||
|
|
||||||
|
|
||||||
|
class Videos(Tab):
|
||||||
|
|
||||||
|
def __init__(self, channel_id: str) -> None:
|
||||||
|
self.channel_id = channel_id
|
||||||
|
|
||||||
|
def get_url(self) -> str:
|
||||||
|
return f"{Tab.URL_ROOT}/channel/{self.channel_id}/videos"
|
||||||
|
|
||||||
|
|
||||||
|
def command(action: Action):
|
||||||
|
match action:
|
||||||
|
case Action.DOWNLOAD_VIDEO:
|
||||||
|
options = {
|
||||||
|
"format": "bestvideo[ext=mp4]+bestaudio[ext=mp4]",
|
||||||
|
"outtmpl": "%(id)s.%(ext)s",
|
||||||
|
"writesubtitles": True,
|
||||||
|
"writethumbnail": True,
|
||||||
|
}
|
||||||
|
log.info(options)
|
||||||
|
with dl(options) as youtube:
|
||||||
|
match action:
|
||||||
|
case Action.DOWNLOAD_VIDEO:
|
||||||
|
youtube.download([url])
|
||||||
|
case _:
|
||||||
|
youtube.extract_info(url, download=False)
|
||||||
|
|
||||||
|
|
||||||
|
def download_video(video_id: str):
|
||||||
|
return command(Action.DOWNLOAD_VIDEO, video_id)
|
||||||
|
|
||||||
|
|
||||||
|
def extract_playlist(playlist_id: str):
|
||||||
|
return command(Action.EXTRACT_PLAYLIST, playlist_id)
|
||||||
|
|
||||||
|
|
||||||
|
def extract_playlists(channel_id: str):
|
||||||
|
return command(Action.EXTRACT_PLAYLISTS, channel_id)
|
||||||
|
|
||||||
|
|
||||||
|
def extract_video(video_id: str):
|
||||||
|
return command(Action.EXTRACT_VIDEO, video_id)
|
||||||
|
|
||||||
|
|
||||||
|
def extract_videos(channel_id: str):
|
||||||
|
return command(Action.EXTRACT_VIDEOS, channel_id)
|
0
rwx/sw/yt_dlp/video.py
Normal file
0
rwx/sw/yt_dlp/video.py
Normal file
Loading…
Add table
Add a link
Reference in a new issue