Python Forum
The Python Tkinter Youtube Audio Downloader for Linux
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
The Python Tkinter Youtube Audio Downloader for Linux
#1
Make sure to use the img/ and downloads/ folders as shown in the Github Repository

The following packages need to be installed prior to using:

apt-get install python3-tk
apt-get install youtube-dl
apt-get install ffmpeg

#! /usr/bin/python3
from tkinter import *
from subprocess import call, Popen, PIPE, STDOUT
from os import listdir, popen, remove
from shutil import move
from time import sleep
from getpass import getuser


class TubeDream:
    def __init__(self, master):
        self.colors = {
            'white': '#FFFFFF',
            'blue': '#2B547E',
            'black': '#000000',
            'red': '#FF3346',
            'green': '#306754',
            'grey': '#E5E4E2',
        }
        self.master = master
        self.master.title("Tube Dream")
        self.master.configure(bg=self.colors['black'])
        self.master.geometry("850x640")
        self.check_wav = IntVar()
        self.check_mp3 = IntVar()
        self.check_m4a = IntVar()
        self.base_url, self.link, self.playing = '', '', ''
        self.file_type, self.f_name = '', ''
        self.imagePath = PhotoImage(file="img/froggy.png")
        self.image = Label(
            master,
            image=self.imagePath,
            borderwidth=0
        )
        self.link_label = Label(
            master,
            fg=self.colors['grey'],
            bg=self.colors['blue'],
            text="Enter your YouTube link: ",
            width=57,
            font="Helvetica 10 bold"
        )
        self.youtube_link = Text(
            master,
            fg=self.colors['blue'],
            bg=self.colors['grey'],
            width=57,
            height=1
        )
        self.file_name_label = Label(
            master,
            fg=self.colors['grey'],
            bg=self.colors['blue'],
            text="Enter a name for your file: ",
            width=57,
            font="Helvetica 10 bold"
        )
        self.file_name = Text(
            master,
            fg=self.colors['blue'],
            bg=self.colors['grey'],
            width=57,
            height=1
        )
        self.wav = Checkbutton(
            master,
            fg=self.colors['red'],
            bg=self.colors['black'],
            text='.wav',
            highlightbackground=self.colors['black'],
            variable=self.check_wav
        )
        self.mp3 = Checkbutton(
            master,
            fg=self.colors['red'],
            bg=self.colors['black'],
            text='.mp3',
            highlightbackground=self.colors['black'],
            variable=self.check_mp3
        )
        self.m4a = Checkbutton(
            master,
            fg=self.colors['red'],
            bg=self.colors['black'],
            text='.m4a',
            highlightbackground=self.colors['black'],
            variable=self.check_m4a
        )
        self.go_button = Button(
            master,
            fg=self.colors['grey'],
            bg=self.colors['green'],
            text="GO!",
            width=48,
            highlightbackground=self.colors['black'],
            command=self.go
        )
        self.clear_button = Button(
            master,
            fg=self.colors['grey'],
            bg=self.colors['green'],
            text="CLEAR",
            width=48,
            highlightbackground=self.colors['black'],
            command=self.clear
        )
        self.explorer_label1 = Label(
            master,
            fg=self.colors['grey'],
            bg=self.colors['blue'],
            width=50,
            text="Downloaded Tracks:  "
        )
        self.explorer_label2 = Label(
            master,
            fg=self.colors['grey'],
            bg=self.colors['black'],
            width=50,
            text=""
        )
        self.explorer = Listbox(
            master,
            fg=self.colors['blue'],
            bg=self.colors['grey'],
            width=100,
            height=15,
            highlightcolor=self.colors['green']
        )
        self.delete_button = Button(
            master,
            fg=self.colors['white'],
            bg=self.colors['red'],
            text="DELETE",
            width=31,
            highlightbackground=self.colors['black'],
            command=self.delete
        )
        self.stop_button = Button(
            master,
            fg=self.colors['grey'],
            bg=self.colors['green'],
            text="STOP",
            width=31,
            highlightbackground=self.colors['black'],
            command=self.stop
        )
        self.play_button = Button(
            master,
            fg=self.colors['grey'],
            bg=self.colors['green'],
            text="PLAY",
            width=31,
            highlightbackground=self.colors['black'],
            command=self.play
        )
        self.status_label = Label(
            master,
            fg=self.colors['grey'],
            bg=self.colors['black'],
            width=60,
            text="Hello " + getuser()
        )
        # begin grid placement
        self.image.grid(
            row=0,
            sticky=W+E
        )
        self.link_label.grid(
            row=1,
            sticky=W,
            padx=20,
            pady=5
        )
        self.youtube_link.grid(
            row=1,
            sticky=E,
            padx=20,
            pady=5
        )
        self.file_name_label.grid(
            row=2,
            sticky=W,
            padx=20
        )
        self.file_name.grid(
            row=2,
            sticky=E,
            padx=20
        )
        self.wav.grid(
            row=3,
            sticky=W,
            padx=100,
            pady=5
        )
        self.mp3.grid(
            row=3,
            pady=5
        )
        self.m4a.grid(
            row=3,
            sticky=E,
            padx=100,
            pady=5
        )
        self.go_button.grid(
            row=5,
            sticky=W,
            padx=20,
            pady=10
        )
        self.clear_button.grid(
            row=5,
            sticky=E,
            padx=20,
            pady=10
        )
        self.explorer_label1.grid(
            row=6,
            sticky=W,
            padx=20
        )
        self.explorer_label2.grid(
            row=6,
            sticky=E,
            padx=20
        )
        self.explorer.grid(
            row=7,
            sticky=E+W,
            padx=20
        )
        self.play_button.grid(
            row=8,
            sticky=W,
            padx=20,
            pady=20
        )
        self.stop_button.grid(
            row=8,
            pady=20
        )
        self.delete_button.grid(
            row=8,
            sticky=E,
            padx=20,
            pady=20
        )
        self.status_label.grid(
            row=13,
            sticky=E+W
        )
        self.populate_explorer()

    def finished(self):
        d = "FINISHED DOWNLOAD"
        for letter in enumerate(d):
            self.set_status_label(d[0:letter[0] + 1])
            self.status_label.update_idletasks()
            sleep(.1)

    def download(self):
        track = self.f_name + '.' + self.file_type
        cmd_list = [
            "youtube-dl", self.link, "-f",
            "bestaudio", "--extract-audio",
            "-o", track, "--audio-quality",
            "0", "--audio-format", self.file_type
        ]
        cmd = ' '.join(cmd_list)
        for std_out in popen(cmd):
            self.set_status_label(std_out)
            self.status_label.update_idletasks()
        try:
            move(self.f_name + '.' + self.file_type, "downloads/")
        except:
            self.set_status_label("ERROR DOWNLOADING")

    def get_chkbtn_status(self):
        btn_status = [
            ('wav', self.check_wav.get()),
            ('mp3', self.check_mp3.get()),
            ('m4a', self.check_m4a.get())
        ]
        choice = []
        for i in range(len(btn_status)):
            if btn_status[i][1] != 1:
                continue
            else:
                choice.append(btn_status[i])
        if not choice:
            self.set_status_label("Please choose a file type")
            return None
        elif len(choice) > 1:
            self.set_status_label("Please choose only one file type")
            return None
        else:
            return choice[0][0]

    def populate_explorer(self):
        self.explorer.delete(0, 'end')
        downloads = sorted(listdir("downloads/"))
        self.explorer.insert("end", *downloads)
        self.set_explorer_status_label(str(self.explorer.size()))

    def go(self):
        self.link = self.youtube_link.get("1.0", END).strip()
        self.f_name = self.file_name.get("1.0", END).strip()
        self.file_type = self.get_chkbtn_status()
        if not self.link or not self.f_name:
            message = "Check your URL and ensure you entered a filename..."
            self.set_status_label(message)
        else:
            if self.file_type is not None:
                current_track = self.f_name + '.' + self.file_type
                self.set_status_label('DOWNLOADING ' + current_track)
                self.status_label.update_idletasks()
                self.download()
                self.populate_explorer()
                idx = sorted(listdir("downloads/")).index(current_track)
                self.explorer.selection_clear(0, END)
                self.explorer.selection_set(idx)
                self.finished()

    def clear(self):
        self.file_name.delete("1.0", END)
        self.youtube_link.delete("1.0", END)
        self.check_wav.set(0)
        self.check_mp3.set(0)
        self.check_m4a.set(0)
        self.set_status_label("Hello " + getuser())

    def delete(self):
        try:
            track = self.explorer.get(self.explorer.curselection())
            path = "downloads/" + track
            remove(path)
            d_message = track + " DELETED"
            self.set_status_label(d_message)
        except:
            message = "Please select a track to delete"
            self.set_status_label(message)
        self.populate_explorer()

    def stop(self):
        if self.playing:
            self.set_status_label('STOPPING ' + self.playing)
            self.status_label.update_idletasks()
            psaux = []
            for line in popen("ps -aux | grep ffplay"):
                if 'ffplay' in line:
                    psaux = line.split()
                    break
            try:
                call('kill ' + psaux[1].strip(), shell=True)
            except Exception as e:
                self.set_status_label(e)

    def play(self):
        try:
            self.playing = self.explorer.get(self.explorer.curselection())
            self.set_status_label('PLAYING ' + self.playing)
            self.status_label.update_idletasks()
            ffplay = [
                "ffplay", "downloads/" + self.playing,
                "-nodisp", "-autoexit"
            ]
            Popen(ffplay, stdout=PIPE, stderr=STDOUT)
        except:
            self.set_status_label("Please select a track to play")

    def set_status_label(self, incoming_message1):
        self.status_label.config(text=incoming_message1)

    def set_explorer_status_label(self, incoming_message2):
        incoming_message2 += " Files Found"
        self.explorer_label2.config(text=incoming_message2)


if __name__ == "__main__":
    root = Tk()
    tube_dream = TubeDream(root)
    root.mainloop()
Reply


Messages In This Thread
The Python Tkinter Youtube Audio Downloader for Linux - by rootVIII - Dec-19-2018, 11:33 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  A Python library for audio and music analysis, feature extraction CMLab 0 1,891 Mar-16-2023, 03:26 AM
Last Post: CMLab
  YouTube Video Downloader BlazingWarlord 1 4,697 May-31-2021, 09:57 AM
Last Post: DeaD_EyE
  A Tkinter Widget-Templater/GUI Builder for Linux/Mac rootVIII 2 3,370 Jun-09-2020, 02:21 AM
Last Post: rootVIII
  Subtitle Downloader (Subdb and Opensubtitles) hbknjr 0 8,893 Oct-23-2017, 04:50 PM
Last Post: hbknjr

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020