'How can I fix this Python Youtube video dowloader? (On windows)

I made this youtube video downloader in Python and it isn't working. The pop up works and I'm able to enter a URL, but no video is downloaded and no completion message is given. I think it may be a problem with my program not being able to locate the project folder or some other location problem, but I can't figure out how to fix it.

Here's the code:

 # import libraries

 from tkinter import *
 from pytube import YouTube

 # create API window (?)
 # creates pop up window
 root = Tk()
 root.geometry('500x300')
 root.resizable(0,0)
 root.title("youtube dowloader")


 # code link entry
 Label(root, text = 'pretend this looks retro instead of busted', font = 'sans'
  '-serif 14 bold').pack()
 link = StringVar() # specifies variable type
 Label(root, text = "lol please paste your link here", font = 'sans-serif 15'
  ' bold').place(x=100, y=55)
 link_enter = Entry(root, width = 70, textvariable = link).place(x=30, y=85)

 # create download button
 Button(root, text = 'dowload', font = 'sans-serif 16 bold', bg = 'skyblue',
   padx =2, command = 'download').place(x=185, y=150)

 # dowload function
 def download():
     # finds the video
     url = YouTube(str(link.get()))
     # basically finds out how many streams/pixels you can get
     video = url.streams.first()

video.download()

#shows download is done
Label(root, text = 'downloaded', font = 'arial 15').place(x=100, y=120)    

root.mainloop()

And here's what the pop up looks like: pop up screenshot

I'm obviously pretty beginner so I could be missing something pretty stupid. Any help is appreciated! :)



Solution 1:[1]

command= needs function's name command=download, not string "download".

And this needs to put this function before line with command.

Document PEP 8 -- Style Guide for Python Code suggests to put all functions after imports, constants, classes - before main code - like this:

import tkinter as tk   # PEP8: `import *` is not preferred
from pytube import YouTube

# --- constants ---

# empty

# --- classes ---

# empty

# --- functions ---

def download():
    url = YouTube(link.get())
    
    video = url.streams.first()

    video.download()

    tk.Label(root, text='Downloaded').pack()    

# --- main ---

root = tk.Tk()

tk.Label(root, text="Please paste your link here").pack()

link = tk.StringVar(root)
tk.Entry(root, width=70, textvariable=link).pack()

tk.Button(root, text='Download', command=download).pack()

root.mainloop()

EDIT:

Version with displaying "progress" in label.

For tests:

  • I put url in code so I don't have to copy-paste it all time,
  • I use skip_existing=False so I don't have to delete downloaded file before next test,
  • I use get_highest_resolution() to download the bigest version because it downloads in chunks 9MB and when file is smaller then it doesn't run on_progress. (chunk size is defined in file pytube/request.py but you would have to edit this file to run code with smaller chunk)
import tkinter as tk   # PEP8: `import *` is not preferred
from pytube import YouTube

# --- functions ---

def progress_function(stream, file_handler, bytes_remaining):
    #print('stream.filesize:', stream.filesize)
    #print('bytes_remaining:', bytes_remaining)
    downloaded = stream.filesize - bytes_remaining
    progress_label['text'] = f'{downloaded}/{stream.filesize}'
    root.update()  # force `mainloop` to redraw window (because `download()` is blocking `mainloop`)
    
def complete_function(stream, file_path):
    progress_label['text'] = f'Downloaded\n{file_path}'
    
def download():
    url = YouTube(link.get(),
                  on_progress_callback=progress_function,
                  on_complete_callback=complete_function
                  )
    
    #video = url.streams.first()
    video = url.streams.get_highest_resolution()

    video.download(skip_existing=False)  # for tests `skip_existing` to reload again the same

# --- main ---

root = tk.Tk()

tk.Label(root, text="Please paste your link here").pack()

link = tk.StringVar(root)
link.set('https://www.youtube.com/watch?v=aqz-KE-bpKQ')
         
tk.Entry(root, width=70, textvariable=link).pack()

tk.Button(root, text='Download', command=download).pack()

progress_label = tk.Label(root)
progress_label.pack()    

root.mainloop()

enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1