From ee35c124f292cfb12c7681520cc3fd4037a6f29a Mon Sep 17 00:00:00 2001 From: Sean Date: Tue, 3 Feb 2026 19:30:08 -0500 Subject: [PATCH] Initial Commit --- .gitignore | 3 ++ DownloadYouTube.py | 89 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 .gitignore create mode 100644 DownloadYouTube.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..963ce3b --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +downloads/ +.venv/ +LIST.txt diff --git a/DownloadYouTube.py b/DownloadYouTube.py new file mode 100644 index 0000000..594ced5 --- /dev/null +++ b/DownloadYouTube.py @@ -0,0 +1,89 @@ +#pip install git+https://github.com/JuanBindez/pytubefix.git +# This works as of 02/01/2026 +# This application accepts the name of a file the contents of which contain URL links to YouTube Videos. +# An example of a line in such file might be https://www.youtube.com/watch?v=OmbWAsQaxzA&list=RDwCBfk8ZCMOU&index=12 +# The program can download the video and also audio only +# Since I am most interested in the audio that is what I have adopted below. +# NOTE: The Video section below works and is left as an example to further develop as needed +# Also. The files are downloaded from youtube in m4a format. I invoke ffmpeg to convert to mp3 +# https://github.com/JuanBindez/pytubefix + +# Activate thge environment +#.venv/scripts/activate + +from pytubefix import YouTube +import os +import traceback +import subprocess + +ffmpeg_pathfile="c:\\download\\ffmpeg\\bin\\ffmpeg" +download_folder = "./downloads" +pathInputFileName = "C:\Python\PyTube\LIST.txt" + +class YouTubeDownloader: + def __init__(self, pathUrlList): + self.pathUrlList=pathUrlList + self.urlList=[] + + def downloadMedia(self, audioOnly): + self.readFile(self.pathUrlList) + if None is self.urlList: + return + for item in self.urlList: + self.getItem(item,audioOnly) + + + def getItem(self, url, audioOnly): + try: + # Create a YouTube object + yt = YouTube(url) + if audioOnly: + audio_stream = yt.streams.get_audio_only() + # If you need more control, you could use filter(only_audio=True).first() to get the first available audio stream + if audio_stream: + print(f"Downloading audio: {yt.title} in {audio_stream.mime_type} format...") + # 4. Download the file. The file is usually downloaded in m4a. + out_file = audio_stream.download(output_path=download_folder) # Download to the downloads folder + base, ext = os.path.splitext(out_file) + # we convert the m4a into mp3 + mp3file = base + '.mp3' + processname = ffmpeg_pathfile+" -y -i \""+out_file+"\" -ab 320k -map_metadata 0 -id3v2_version 3 \""+mp3file+"\"" + subprocess.run(processname, check=True) + os.remove(out_file) + print(f"Successfully downloaded and saved as: {os.path.basename(mp3file)}") + else: + print("No audio-only streams found.") + return + + # Optional: Print the video title to confirm it's working + print(f"Downloading video: {yt.title}") + + # Get the highest resolution progressive stream (contains both video and audio) + # The get_highest_resolution() method simplifies this process + video_stream = yt.streams.get_highest_resolution() + + video_stream.download() + + print("Download completed successfully!") + + except Exception as e: + print(f"Error downloading {url}") + print(f"Exception was : {e}") + + def readFile(self,pathFileName): + try: + with open(pathFileName,"r",encoding='utf-8') as inputStream: + for line in inputStream: + if None != line and 0!=len(line): + strippedLine = line.strip() + if 0!= len(strippedLine): + self.urlList.append(strippedLine) + inputStream.close() + print(f"Read {len(self.urlList)} itemns from {pathFileName}") + except: + print(traceback.format_exc()) + return(None) + + +youTubeDownloader = YouTubeDownloader(pathInputFileName) +youTubeDownloader.downloadMedia(True)