90 lines
3.5 KiB
Python
90 lines
3.5 KiB
Python
#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\DownloadYouTube\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)
|