0
votes

I'm trying to build youtube downloader application with GUI using python3. After learning basics of python I'm trying to build one. I'm using "pafy" and "TKinter" modules.

Following are the widgets involved in the GUI 1. One Entry field to input the URL 2. Next to it paste button 3. A media select drop down menu 4. One more drop down menu to list the media quality(depends on previous media input) 5. Finally a download button

Here is my code

from tkinter import *
from tkinter import ttk
import pafy

master = Tk()

media_option = StringVar()

audio_quality_lsit = []
audio_quality_drop_menu = StringVar()

video_quality_lsit = []
video_quality_drop_menu = StringVar()


def url():
    global data
    url = url_field.get()
    data = pafy.new(url)


def audio():
    global selected_audio
    audio_streams = data.audiostreams
    for audio_quality in audio_streams:
        audio_quality_lsit.append(audio_quality.bitrate)
    selected_audio = audio_quality_drop_menu.get()
    print("selected_audio") #Debug Statement
    Label(master, text="Audio Bitrate: ").grid(row=7, column=1)
    show_drop_menu = OptionMenu(master, audio_quality_drop_menu, *audio_quality_lsit)
    show_drop_menu.grid(row=9, column=1)



def video():
    global selected_video
    video_streams = data.streams
    for video_quality in video_streams:
        video_quality_lsit.append(video_quality.resolution)
    selected_video = video_quality_drop_menu.get()
    print("selected_video")  #Debug Statement
    Label(master, text="Video Quality: ").grid(row=7, column=1)
    show_drop_menu = OptionMenu(master, video_quality_drop_menu, *video_quality_lsit)
    show_drop_menu.grid(row=9, column=1)


def media_select(self):
    global  A_V
    A_V = media_option.get()
    if A_V == "Audio":
        audio()
    elif A_V == "Video":
        video()


def download():
    if selected_audio:
        print("Audio")  #Debug Statement
        selected_audio.download(quiet=False)
    elif selected_video:
        print("Video")  #Debug Statement
        selected_video.download(quiet=False)


Label(master, text="YouTube URL:").grid(row=0)
url_field = Entry(master)
url_field.grid(row=0, column=1)

Button(master, text='Paste URL', command=url).grid(row=0, column=4, sticky=W, pady=10)
Button(master, text='Download', command=download).grid(row=12, column=4, sticky=W, pady=10)
Label(master, text="Media Type: ").grid(row=3)

media_drop_menu = OptionMenu(master, media_option, "Audio", "Video", command=media_select)
media_drop_menu.grid(row=5, column=0)

mainloop()

I'm stuck at "download function". Am I using the function properly? Is there any problem in calling the function? And one more thing, Sorry if it is dump question. Why we have to do this,

from tkinter import *
from tkinter import ttk    

According to my understanding when we use "*", will import all the modules present in the library. Again why we have to use "from tkinter import ttk".

Please help me.

UPDATE: @JoshuaNixon Thanks for the replay. I didn't know much about "classes" So first I learnt basics of it and I made some changes.

Here is the code:

from tkinter import *
import pafy

class YouTubeDownloader:
    def __init__(self,master):
        self.master = master
        master.title("Youtube Downloader")
        self.media_option = StringVar()
        self.audio_quality_lsit = []
        self.audio_quality_drop_menu = StringVar()
        self.video_quality_lsit = []
        self.video_quality_drop_menu = StringVar()
        Label(master, text="YouTube URL:").grid(row=0)
        self.url_field = Entry(master)
        self.url_field.grid(row=0, column=1)
        Button(master, text='Paste URL', command=self.url).grid(row=0, column=4, sticky=W, pady=10)
        Button(master, text='Download', command=self.download).grid(row=12, column=4, sticky=W, pady=10)
        Label(master, text="Media Type: ").grid(row=3)
        media_drop_menu = OptionMenu(master, self.media_option, "Audio", "Video", command=self.media_select)
        media_drop_menu.grid(row=5, column=0)


    def url(self):
        global data
        url = self.url_field.get()
        data = pafy.new(url)


    def media_select(self):
        global  A_V
        A_V = self.media_option.get()
        if A_V == "Audio":
            audio()
        elif A_V == "Video":
            video()


    def audio():
        global selected_audio
        audio_streams = self.data.audiostreams
        for audio_quality in audio_streams:
            audio_quality_lsit.append(audio_quality.bitrate)
        selected_audio = audio_quality_drop_menu.get()
        print("selected_audio") #Debug Statement
        Label(master, text="Audio Bitrate: ").grid(row=7, column=1)
        show_drop_menu = OptionMenu(master, audio_quality_drop_menu, *audio_quality_lsit)
        show_drop_menu.grid(row=9, column=1)


    def video(self):
        global selected_video
        video_streams = self.data.streams
        for video_quality in video_streams:
            video_quality_lsit.append(video_quality.resolution)
        selected_video = video_quality_drop_menu.get()
        print("selected_video")  #Debug Statement
        Label(master, text="Video Quality: ").grid(row=7, column=1)
        show_drop_menu = OptionMenu(master, video_quality_drop_menu, *video_quality_lsit)
        show_drop_menu.grid(row=9, column=1)


    def download(self):
        if selected_audio:
            print("Audio")  #Debug Statement
            self.selected_audio.download(quiet=False)
        elif selected_video:
            print("Video")  #Debug Statement
            self.selected_video.download(quiet=False)



root = Tk()
my_youtube = YouTubeDownloader(root)
root.mainloop()

When I run the code, I get the GUI. After copy pasting URL field, I get error at "media_select()" saying that

"TypeError: media_select() takes 1 positional argument but 2 were given".

You suggested to make use of two classes. As I'm still beginner in this, I got little confused in the "self" argument. So I used single class.

Can you please tell me where I'm going wrong.

Thank You.

1
I typically use import tkinter as tk so i use tk.Label instead of just Label. this means i can tell apart my own objects from tkinters - Joshua Nixon
I would use OOP for this project. One for your UI and one for the downloading - Joshua Nixon

1 Answers

0
votes

All the syntax errors have been solved. Only one exception is left that I think you can solve.

When you use a class use self.* for referring,

from Tkinter import *
import pafy

class YouTubeDownloader:
    def __init__(self,master):
        self.master = master
        master.title("Youtube Downloader")
        self.media_option = StringVar()
        self.audio_quality_lsit = []
        self.audio_quality_drop_menu = StringVar()
        self.video_quality_lsit = []
        self.video_quality_drop_menu = StringVar()
        Label(master, text="YouTube URL:").grid(row=0)
        self.url_field = Entry(master)
        self.url_field.grid(row=0, column=1)
        Button(master, text='Paste URL', command=self.url).grid(row=0, column=4, sticky=W, pady=10)
        Button(master, text='Download', command=self.download).grid(row=12, column=4, sticky=W, pady=10)
        Label(master, text="Media Type: ").grid(row=3)
        media_drop_menu = OptionMenu(master, self.media_option, "Audio", "Video", command=self.media_select)
        media_drop_menu.grid(row=5, column=0)
        self.data = []

    def url(self):
        global data
        url = self.url_field.get()
        self.data = pafy.new(url)

    def media_select(self, a):
        global A_V
        A_V = self.media_option.get()
        if A_V == "Audio":
            # for functions of same class use self.function()
            self.audio()
        elif A_V == "Video":
            self.video()

    def audio(self):
        global selected_audio
        audio_streams = self.data.audiostreams
        for audio_quality in audio_streams:
            self.audio_quality_lsit.append(audio_quality.bitrate)
        selected_audio = self.audio_quality_drop_menu.get()
        print("selected_audio") #Debug Statement
        Label(self.master, text="Audio Bitrate: ").grid(row=7, column=1)
        show_drop_menu = OptionMenu(self.master, self.audio_quality_drop_menu, *self.audio_quality_lsit)
        show_drop_menu.grid(row=9, column=1)

    def video(self):
        global selected_video
        video_streams = self.data.streams
        for video_quality in video_streams:
            self.video_quality_lsit.append(video_quality.resolution)
        selected_video = self.video_quality_drop_menu.get()
        print("selected_video")  #Debug Statement
        Label(self.master, text="Video Quality: ").grid(row=7, column=1)
        show_drop_menu = OptionMenu(self.master, self.video_quality_drop_menu, *self.video_quality_lsit)
        show_drop_menu.grid(row=9, column=1)

    def download(self):
        if selected_audio:
            print("Audio")  #Debug Statement
            self.selected_audio.download(quiet=False)
        elif selected_video:
            print("Video")  #Debug Statement
            self.selected_video.download(quiet=False)

root = Tk()
my_youtube = YouTubeDownloader(root)
root.mainloop()