Last active
June 11, 2024 20:32
-
-
Save Adrian-2105/a1e407f3f4c780a60f829eac9d241881 to your computer and use it in GitHub Desktop.
YouTube Downloader - Audio, Video and Playlists - Easy to use
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
import os | |
import subprocess | |
import argparse | |
from pytube import Playlist, YouTube, Stream | |
# Used to solve pytube.exceptions.AgeRestrictedError | |
from pytube import innertube | |
innertube._default_clients["ANDROID_MUSIC"] = innertube._default_clients["ANDROID_CREATOR"] | |
EXAMPLES_OF_USE = """ | |
EXAMPLES | |
# Download a video in MP4 in the current directory | |
python YoutubeDownloader.py --video --url "https://www.youtube.com/watch?v=eYDI8b5Nn5s" | |
# Download an audio playlist in MP3 in a subfolder called 'MyPlaylist' | |
python YoutubeDownloader.py --audio --path "./MyPlaylist/" --url "https://youtube.com/playlist?list=PLZuZrScKjWOMAEEBEGTmAGtmmlg6QY7bC" | |
# Download the video by selecting the desired format | |
python YoutubeDownloader.py --select --url "https://www.youtube.com/watch?v=eYDI8b5Nn5s" | |
""" | |
# Downloads the video, pre-showing all download options | |
def download_option(url : str, path = './'): | |
video = YouTube(url) | |
video_options = video.streams.all() | |
for i in range(len(video_options)): | |
print(f'[{i}] {video_options[i]}') | |
while True: | |
num_option = int(input('Enter the number of the options you want to choose to download: ')) | |
if num_option >= 0 and num_option < len(video_options): | |
break | |
print(f'Invalidad number. Please, insert one between 0 and {len(video_options) - 1}') | |
return download_stream(video_options[num_option], path) | |
# Downloads the video in MP4 at max resolution | |
def download_video(url : str, path = './'): | |
video = YouTube(url) | |
return download_stream(video.streams.get_highest_resolution(), path) | |
# Downloads the video in MP4 (only audio) at best quality | |
def download_audio(url: str, path = './'): | |
video = YouTube(url) | |
return download_stream(video.streams.get_audio_only(), path) | |
# Downloads a created Pytube Stream | |
def download_stream(stream: Stream, path = './'): | |
# gets the filename of the first audio stream | |
filename = stream.default_filename | |
print(f'Downloading {filename} ...') | |
# downloads first audio stream | |
stream.download(path) | |
print(f'{filename} downloaded!') | |
return os.path.join(path, filename) | |
# Converts a file video (MP4) to audio (MP3) | |
def convert_video_to_audio(filename: str, remove_later = False): | |
# Checks if file exists | |
if not os.path.exists(filename): | |
print(f'{filename} cannot be located in current directory ({os.getcwd()})', file=sys.stderr) | |
return | |
# creates mp3 filename for downloaded file | |
new_filename = filename[0:filename.rfind('.')] + ".mp3" | |
print(filename, new_filename) | |
# converts mp4 audio to mp3 audio | |
print("Converting to mp3....") | |
subprocess.run(['ffmpeg', '-i', filename, new_filename]) | |
# remove original file if specified | |
if remove_later: | |
os.remove(filename) | |
if __name__ == "__main__": | |
# Arguments | |
parser = argparse.ArgumentParser() | |
parser.add_argument('-v', '--video', action='store_true', help='download the video in MP4') | |
parser.add_argument('-a', '--audio', action='store_true', help='download the video as audio in MP3') | |
parser.add_argument('-s', '--select', action='store_true', help='select the download format among all the possible options') | |
parser.add_argument('-p', '--path', default='./', help='path where to download') | |
parser.add_argument('-u', '--url', required=True, help='URL to download') | |
# No arguments and print help | |
if len(sys.argv) == 1: | |
parser.print_help() | |
print(EXAMPLES_OF_USE) | |
print('NOTE: for audio downloads, this application requieres ffmpeg') | |
print(' - On Linux: you can download it through apt-get') | |
print(' - On Windows: download the executable ffmpeg.exe and add it to the working directory (or add it to the path instead)') | |
parser.exit() | |
# Parse arguments | |
args = parser.parse_args() | |
if not args.select and not args.video and not args.audio: | |
print('No option for download selected. Use --select, --video or --audio to download') | |
exit(1) | |
# Check if URL works and if it's a single video or a playlist | |
is_video = False | |
is_playlist = False | |
try: | |
is_video = YouTube(args.url) | |
is_video = True | |
except: | |
try: | |
is_playlist = Playlist(args.url) | |
is_playlist = True | |
except: | |
print('Invalid URL!', file=sys.stderr) | |
exit(1) | |
# Executes program | |
if not is_playlist: | |
if args.select: | |
filepath = download_option(args.url, args.path) | |
else: | |
if args.audio: | |
filepath = download_audio(args.url, args.path) | |
convert_video_to_audio(filepath, remove_later=True) | |
if args.video: | |
filepath = download_video(args.url, args.path) | |
else: # is playlist | |
playlist = Playlist(args.url) | |
for video_url in playlist: | |
if args.select: | |
filepath = download_option(video_url, args.path) | |
else: | |
if args.audio: | |
filepath = download_audio(video_url, args.path) | |
convert_video_to_audio(filepath, remove_later=True) | |
if args.video: | |
filepath = download_video(video_url, args.path) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Help menu and examples