Reputation: 11
I started a project a day ago where you can choose to download any Youtube video using the pytube library, problem is that it does not support mp3 files, so I tried using moviepy and it was not successful.
Here's my code,
def download_video():
link = url.get()
yt = YouTube(link)
if audio_download.get() == 1:
t=yt.streams.filter(only_audio=True)
t[0].download(dir)
mp4_file = (dir + yt.title + '.mp4')
mp3_file = (dir + yt.title + '.mp3')
video = VideoFileClip(mp4_file)
audioclip = video.audio
audioclip.write_audiofile(mp3_file)
video.close()
audioclip.close()
And here is the project error,
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\kelvi\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1892, in __call__
return self.func(*args)
File "c:\Users\kelvi\Documents\Code\youtubedownloader.py", line 28, in download_video
video = VideoFileClip(mp4_file)
File "C:\Users\kelvi\AppData\Local\Programs\Python\Python39\lib\site-packages\moviepy\video\io\VideoFileClip.py", line 88, in __init__
self.reader = FFMPEG_VideoReader(filename, pix_fmt=pix_fmt,
File "C:\Users\kelvi\AppData\Local\Programs\Python\Python39\lib\site-packages\moviepy\video\io\ffmpeg_reader.py", line 35, in __init__
infos = ffmpeg_parse_infos(filename, print_infos, check_duration,
File "C:\Users\kelvi\AppData\Local\Programs\Python\Python39\lib\site-packages\moviepy\video\io\ffmpeg_reader.py", line 270, in ffmpeg_parse_infos
raise IOError(("MoviePy error: the file %s could not be found!\n"
OSError: MoviePy error: the file C:/Users/kelvi/Documents/Video/Alicia Keys - If I Ain't Got You (Official Video).mp4 could not be found!
Please check that you entered the correct path.
Here is the full code
from tkinter import *
from tkinter import filedialog
from pytube import YouTube
import time
from moviepy.editor import *
# Setup
root = Tk()
root.title("Youtube Downloader")
root.resizable(0,0)
audio_download = IntVar()
root.iconbitmap("logo.ico")
with open("directory.txt", 'r') as File:
dir = File.read()
File.close()
# Functions
def download_video():
link = url.get()
yt = YouTube(link)
if audio_download.get() == 1:
t=yt.streams.filter(only_audio=True)
t[0].download(dir)
mp4_file = (dir + yt.title + '.mp4')
mp3_file = (dir + yt.title + '.mp3')
video = VideoFileClip(mp4_file)
audioclip = video.audio
audioclip.write_audiofile(mp3_file)
video.close()
audioclip.close()
else:
t=yt.streams.get_highest_resolution()
t.download(dir)
def browse_file():
global dir
dir = filedialog.askdirectory()
with open("directory.txt", 'w') as File:
File.write(dir + '/')
File.close()
# Layout
header = Label(root,text="Youtube Downloader", font="Arial 28 bold",)
header.grid(row=0,column=0)
url = Entry(root, width=60)
url.grid(row=1,column=0)
audio_only = Checkbutton(root, text="Audio Only?", variable=audio_download, onvalue=1, offvalue=0)
audio_only.grid(row=1, column=1)
browse = Button(root,text="Browse", width=10,command=browse_file)
browse.grid(row=2, column=1)
button = Button(root, text="Download", width=30,command=download_video)
button.grid(row=2,column=0)
root.mainloop()
Upvotes: 0
Views: 511
Reputation: 619
Problem: yt.title is not equal to the saved filename because pytube uses function safe_filename() on the video title before saving. In your case safe_filename() deleted apostrophe ' from the filename.
Solution
add
from pytube.helpers import safe_filename
change
yt.streams.filter(only_audio=True)
mp4_file = (dir + yt.title + '.mp4')
mp3_file = (dir + yt.title + '.mp3')
to
yt.streams.filter()
mp4_file = (r"{}{}{}".format(dir, safe_filename(yt.title), '.mp4'))
mp3_file = (r"{}{}{}".format(dir, safe_filename(yt.title), '.mp3'))
or just download mp4 without audio and rename it to mp3
import os
inside if you should have something like
t = yt.streams.filter(only_audio=True)
t[0].download(dir)
mp4_file = (r"{}{}{}".format(dir, safe_filename(yt.title), '.mp4'))
mp3_file = (r"{}{}{}".format(dir, safe_filename(yt.title), '.mp3'))
os.rename(mp4_file, mp3_file)
Upvotes: 1