Search code examples
pythonpython-3.xcx-freezeyoutube-dl

youtube-dl to exe doesn't work


this is the code

from tkinter import *
from tkinter import ttk
from tkinter import messagebox
from tkinter import filedialog
import youtube_dl
import os



class f(object):
    def __init__(self, finestra):
        self.finestra = finestra
        self.top = ttk.Frame(self.finestra, padding="10 10 10 10")
        self.top.grid(column=5, row=5)
        self.top.columnconfigure(1, weight=1)
        self.top.rowconfigure(1, weight=1)

        self.finestra.bind("<Return>",self.esegui_query)

        self.link = StringVar()
        self.esito = StringVar()
        self.bitrate = StringVar()
        self.esito.set("In Attesa")

        ttk.Label(self.top, text="Link:").grid(column=0,row=0)
        ttk.Entry(self.top, textvariable=self.link).grid(column=1,row=0)
        ttk.Button(self.top, text="Scarica", command=self.esegui_query).grid(column=2,row=0)

        ttk.Label(self.top, text="Bitrate:").grid(column=0,row=1)
        r1 = Radiobutton(self.top, text="192", variable=self.bitrate, value="192", cursor="dot")
        r1.grid(column=1,row=1)
        r2 = Radiobutton(self.top, text="320", variable=self.bitrate, value="320", cursor="dot")
        r2.grid(column=2,row=1)
        r1.select()
        ttk.Label(self.top, textvariable=self.esito).grid(column=3,row=1)

    def esegui_query(self,*argv):
        link = self.link.get()
        bitrate=self.bitrate.get()
        ydl_opts = {
        #'format': 'bestaudio/best',
        'postprocessors': [{
            'key': 'FFmpegExtractAudio',
            'preferredcodec': 'mp3',
            'preferredquality': bitrate,
                        }],
                    }
        self.esito.set("Downloading...")
        try:
            with youtube_dl.YoutubeDL(ydl_opts) as ydl:
                ydl.download([link])
            self.esito.set("Encoding...")
            for file in (os.listdir('.')):
                if file.endswith('.mp3') or file.endswith('.m4a') or file.endswith('.mp4'):
                    file2 = file[::-1][16:][::-1]
                    break
            self.esito.set("Download Completato")
        except Exception as e:
            self.esito.set("ERRORE")
            messagebox.showwarning("ERRORE",e)



finestra = Tk()
finestra.title("Download Youtube")
f = f(finestra)
finestra.mainloop()

This code works in my IDLE python 3.6 x86, but not if i convert it in .exe with cx_Freeze

this is the code of setup.py to convert

from cx_Freeze import setup, Executable
import os,sys
os.environ['TCL_LIBRARY'] = r'C:\Program Files (x86)\Python36-32\tcl\tcl8.6'
os.environ['TK_LIBRARY'] = r'C:\Program Files (x86)\Python36-32\tcl\tk8.6'

#includes = ["youtube_dl","tkinter","os"]
include_files = [r'C:\Program Files (x86)\Python36-32\DLLs\tcl86t.dll',\
             r'C:\Program Files (x86)\Python36-32\DLLs\tk86t.dll']

base = 'Win32GUI' if sys.platform == 'win32' else None


executables = [Executable("youtube.py", base=base)]

packages = ["youtube_dl","tkinter","os"]
options = {
    'build_exe': {

        #'packages':packages,
        #'includes':includes,
        'include_files':include_files,
    },

}

setup(
    name = "youtube",
    options = options,
    version = "1.0",
    description = 'download from youtube',
    executables = executables
)

The executable return to me this error: " 'NoneType' object has no attribute 'write' " and this happens when the code execute this line:

with youtube_dl.YoutubeDL(ydl_opts) as ydl:
    ydl.download([link])  <-----

I think is because youtube_dl first download a mp4 version of song and after doing the conversion. It first download and write in to the folder the song in mp4 version and i think there's the problem, convert it in mp3 and remove the mp4 version.

I think the error is in that line because have inserts some messagebox like this:

try:
    with youtube_dl.YoutubeDL(ydl_opts) as ydl:
        messagebox.showwarning("ERRORE",'1') <--- this is showed
        ydl.download([link])
        messagebox.showwarning("ERRORE",'2') <--- this is not showed
    self.esito.set("Encoding...")
    for file in (os.listdir('.')):
        if file.endswith('.mp3') or file.endswith('.m4a') or file.endswith('.mp4'):
            file2 = file[::-1][16:][::-1]
            break
    self.esito.set("Download Completato")
except Exception as e:
    self.esito.set("ERRORE")
    messagebox.showwarning("ERRORE",e)

and when i execute the .exe, the script starts but after i click to download a song the script show me just

messagebox.showwarning("ERRORE",'1')

and the error

'NoneType' object has no attribute 'write'

so he seems stop itself in that line

ydl.download([link])

Solution

  • I solved download youtube-dl.exe for windows and using it do download songs

    cmd = [d+r'\bin\youtube-dl.exe', '-x', '--audio-format=mp3', 
           r'-o'+d+'\download\%(title)s.%(ext)s',
           '--audio-quality=%s' % (bitrate),
           '%s' % (link)
          ] 
    
    subprocess.call(cmd, shell=mshell)