Skip to main content
Code Review

Return to Answer

Corrected mistake
Source Link
#! /usr/bin/python3
from tkinter import *
from youtube_search import YoutubeSearch
import re,random, vlc,datetime, time,yt_dlp
#global vars 
ran = song_index = dur = timescale_var = 0
auto = 1
play_index=-1
volume_var= 100
soundquality = 5
soundqualities = "best"
URLlist = playlist = []
#window, player
win = Tk()
win.geometry('610x100') 
win.title("Youtube Player")
menubar = Menu(win)
instance = vlc.Instance()
player = instance.media_player_new() 
#making the search
def Search(event):
 global song_index, URLlist
 search_querie = str(SearchBox.get())
 song_index = 0
 results = YoutubeSearch(search_querie, max_results=40).to_dict()
 title=[]
 URLlist=[]
 resultcount = -1
 #the following loop is to optionally select only short songs <5min
 for v in results:
 duration = v['duration']
 if duration != 0:
 if duration.count(':') > 1 and dur == 1:
 continue
 if duration.count(':') == 1:
 m, s = duration.split(':')
 duration = int(m) * 60 + int(s)
 if duration > 300 and dur == 1:
 continue
 URLlist.append("https://www.youtube.com" + v['url_suffix'])
 resultcount+= 1
 title.append(re.sub(r"[^a-zA-Z0-9 .,:;+-=!?/()öäßü]", "", v['title']))
 btnPlay.focus()
 btnL.config(command = (lambda: TitleShift(title, -1, resultcount)))
 btnR.config(command = (lambda:TitleShift(title, 1, resultcount)))
 btnPlay.config(command = (lambda: NewSong("insert",1)))
 btnAddsong.config(command = (lambda: Addsong()))
 btnDL.place(x=505, y=2) 
 btnDL.config(command =(lambda: Download(URLlist[song_index],title[song_index])))
 title_label.config(text = title[song_index])
#moving through the songlist
def TitleShift(title,move, resultcount):
 win.focus()
 global song_index
 song_index += move
 if song_index < 0:
 song_index =resultcount
 if song_index > resultcount:
 song_index = 0
 title_label.config(text = title[song_index])
#this function keeps track of time and moves the timescale
def UpdateTime():
 length = player.get_length()
 place = player.get_time()
 if player.is_playing() == 0 and abs(place-length) < 10000 and len(playlist) > 0 and auto == 1:
 NewSong("next", 1)
 place = 0
 player.set_time(0)
 timescale.set(0)
 if player.is_playing() == 1:
 time_info =str(datetime.timedelta(seconds = round(place/1000))) + " / " + str(datetime.timedelta(seconds = round(length/1000)))
 time_label.config(text=time_info)
 timescale.set(place)
 win.after(1000,lambda:UpdateTime())
def GenerateStreamUrl(URL):
 audio = []
 ydl_opts = {}
 with yt_dlp.YoutubeDL(ydl_opts) as ydl:
 info = ydl.extract_info(URL, download=False)
 formats = info['formats']
 songtitle = info['title']
 for i,format in enumerate(formats):
 url = format['url']
 other = format['resolution']
 if other == "audio only":
 audio.append(url)
 return(audio, songtitle)
#starting the song
def NewSong(question, direction):
 win.focus() 
 #first, the play_index is updated
 global play_index
 play_index += direction
 if play_index > (len(playlist)-1):
 play_index = 0
 if question == "insert":
 playlist.insert(play_index,URLlist[song_index])
 else:
 if ran == 1 and len(playlist) > 1:
 counttemp = play_index
 while counttemp == play_index:
 play_index = random.randrange(len(playlist)-1)

#then, the song gets initialised 
  audio = []
 ydl_opts = {}
 with yt_dlp.YoutubeDL(ydl_opts) as ydl:
 info = ydl.extract_info(playlist[play_index], download=False)
  formats = info['formats']
 songtitle = info['title']
  for i,format in enumerate(formats):
 url = format['url']
  other = format['resolution']
 if other == "audio only":
 audio.appendGenerateStreamUrl(urlplaylist[play_index])
 
 if soundqualities == "best":
 stream = audio[len(audio)-1]
 else:
 qualities = len(audio)
 if soundquality > qualities:
 stream = audio[qualities]
 else:
 stream = audio[soundquality]
 #print(stream.quality, int(stream.get_filesize()/10000)/100, "mb")
 playurl = stream 
 media=instance.media_new(playurl)
 media.get_mrl()
 player.set_media(media)
 player.set_time(10000) 
 timescale.set(10000)
 btnPP.place(x=340, y=2)
 btnAddsong.place(x=170, y=62)
 btnBACK.place(x=295, y=2)
 btnBACK2.place(x=240, y=2)
 btnFWD.place(x=395, y=2)
 btnFWD2.place(x=445, y=2)
 timescale.place(x=370, y=68)
 player.play()
 btnPP.config(text="||")
 while player.is_playing() == 0:
 time.sleep(1)
 timescale.config(to = player.get_length())
 win.title(songtitle)
 return(0)
 
#this is to select the next song in the list
def Addsong():
 win.focus() 
 playlist.append(URLlist[song_index])
#next or previous song
def SkipSong(direction):
 win.focus()
 skip = play_index + direction
 if direction == -1 and player.get_time() > 10000:
 player.set_time(0)
 elif skip >= 0 and skip < len(playlist):
 NewSong("next", direction)
#this function is for downloading the song
def Download(song_url, song_title):
 outtmpl = song_title + '.%(ext)s'
 ydl_opts = {
 'format': 'bestaudio/best',
 'outtmpl': outtmpl,
 'postprocessors': [
 {'key': 'FFmpegExtractAudio','preferredcodec': 'mp3',
 'preferredquality': '192',
 },
 {'key': 'FFmpegMetadata'},
 ],
 }
 with yt_dlp.YoutubeDL(ydl_opts) as ydl:
 info_dict = ydl.extract_info("youtube.com" + song_url, download=True) 
#moving through the scale for time
def SetTime(timescale_var):
 place = player.get_time()
 if abs(int(timescale_var) - place) > 4000:
 player.set_time(int(timescale_var))
#this function is for moving back and forth in time of the song
def SkipTime(amount):
 win.focus()
 time_sum = player.get_time() + amount
 time_all = player.get_length()
 if time_sum < 0:
 time_sum = 0
 if time_sum>time_all:
 time_sum = time_all 
 timescale.set(time_sum)
#to pause by keypress (space)
def TogglePause1():
 if str(win.focus_get()) != str(".!entry"):
 funcPP()
 
#to pause by keypress or click
def TogglePause2():
 win.focus()
 pause = player.is_playing()
 player.set_pause(pause)
 if pause == 1:
 btnPP.config(text="|>")
 else:
 btnPP.config(text="||")
#import all songs from querie
def ImportAll():
 playlist.extend(URLlist)
#controlling the volume
def ChangeVolume(volume_var):
 player.audio_set_volume(int(volume_var))
#clear playlist
def ClearPlaylist():
 global playlist
 playlist = []
#setting sound quality
def ChangeQuality(amount):
 global soundquality, soundqualities
 if amount == "best":
 soundqualities = "best"
 else:
 soundqualities = ""
 if amount == 0:
 soundquality = 0
 elif amount == 1 or amount ==-1: 
 soundquality += amount
#toggle autoplay
def ToggleAutoplay():
 global auto
 auto = not(auto)
#toggle limit duration of song
def ToggleDurationLimit():
 global dur
 dur = not(dur)
#toggling shuffle
def ToggleShuffle():
 global ran
 ran = not(ran)
btnPP = Button(win, text = "||", command =(lambda: TogglePause2()))
btnBACK = Button(win, text = "<", command =(lambda: SkipTime(-10000)))
btnFWD = Button(win, text = ">", command =(lambda: SkipTime(10000)))
btnBACK2 = Button(win, text = "<<", command =(lambda: SkipSong(-1)))
btnFWD2 = Button(win, text = ">>", command =(lambda: SkipSong(1)))
btnDL = Button(win, text = "↓")
btnL = Button(win, text = "<-")
btnR = Button(win, text = "->")
btnPlay = Button(win, text = "OK")
btnAddsong = Button(win, text = "+")
timescale = Scale(win, from_=0, to=1000, orient=HORIZONTAL,length=200, variable = timescale_var, showvalue=0, command = SetTime)
volume_scale = Scale(win, from_=200, to=0, orient=VERTICAL,length=80, variable = volume_var, showvalue=0, command = ChangeVolume)
volume_scale.place(x=580, y=2)
volume_scale.set(100)
title_label = Label(win, text = "")
title_label.place(x=5, y=36)
time_label = Label(win, text = "")
time_label.place(x=220, y=66)
SearchBox = Entry(win, width=20) 
SearchBox.place(x=5, y=5)
SearchBox.bind('<Return>', Search)
btnL.place(x=5, y=62)
btnR.place(x=60, y=62)
btnPlay.place(x=115, y=62)
win.bind_all("<Button-1>", lambda event: event.widget.focus_set())
filemenu = Menu(win, tearoff=0)
filemenu.add_command(label="toggle shuffle", command=ToggleShuffle)
filemenu.add_command(label="toggle limit duration", command=ToggleDurationLimit)
filemenu.add_command(label="toggle autoplay", command=ToggleAutoplay)
editmenu = Menu(menubar, tearoff=0)
editmenu.add_command(label="all results to playlist", command=ImportAll)
editmenu.add_command(label="clear playlist", command=ClearPlaylist)
qualmenu = Menu(menubar, tearoff=0)
qualmenu.add_command(label="quality up", command=(lambda: ChangeQuality(1)))
qualmenu.add_command(label="quality down", command=(lambda: ChangeQuality(-1)))
qualmenu.add_command(label="best quality", command=(lambda: ChangeQuality("best")))
qualmenu.add_command(label="worst quality", command=(lambda: ChangeQuality(0)))
menubar.add_cascade(label="Quality", menu=qualmenu)
menubar.add_cascade(label="Options", menu=filemenu)
menubar.add_cascade(label="Playlists", menu=editmenu)
win.config(menu=menubar)
win.bind('<space>',lambda event:TogglePause1())
win.after(2000, lambda:UpdateTime())
SearchBox.focus()
win.mainloop()
#! /usr/bin/python3
from tkinter import *
from youtube_search import YoutubeSearch
import re,random, vlc,datetime, time,yt_dlp
#global vars 
ran = song_index = dur = timescale_var = 0
auto = 1
play_index=-1
volume_var= 100
soundquality = 5
soundqualities = "best"
URLlist = playlist = []
#window, player
win = Tk()
win.geometry('610x100') 
win.title("Youtube Player")
menubar = Menu(win)
instance = vlc.Instance()
player = instance.media_player_new() 
#making the search
def Search(event):
 global song_index, URLlist
 search_querie = str(SearchBox.get())
 song_index = 0
 results = YoutubeSearch(search_querie, max_results=40).to_dict()
 title=[]
 URLlist=[]
 resultcount = -1
 #the following loop is to optionally select only short songs <5min
 for v in results:
 duration = v['duration']
 if duration != 0:
 if duration.count(':') > 1 and dur == 1:
 continue
 if duration.count(':') == 1:
 m, s = duration.split(':')
 duration = int(m) * 60 + int(s)
 if duration > 300 and dur == 1:
 continue
 URLlist.append("https://www.youtube.com" + v['url_suffix'])
 resultcount+= 1
 title.append(re.sub(r"[^a-zA-Z0-9 .,:;+-=!?/()öäßü]", "", v['title']))
 btnPlay.focus()
 btnL.config(command = (lambda: TitleShift(title, -1, resultcount)))
 btnR.config(command = (lambda:TitleShift(title, 1, resultcount)))
 btnPlay.config(command = (lambda: NewSong("insert",1)))
 btnAddsong.config(command = (lambda: Addsong()))
 btnDL.place(x=505, y=2) 
 btnDL.config(command =(lambda: Download(URLlist[song_index],title[song_index])))
 title_label.config(text = title[song_index])
#moving through the songlist
def TitleShift(title,move, resultcount):
 win.focus()
 global song_index
 song_index += move
 if song_index < 0:
 song_index =resultcount
 if song_index > resultcount:
 song_index = 0
 title_label.config(text = title[song_index])
#this function keeps track of time and moves the timescale
def UpdateTime():
 length = player.get_length()
 place = player.get_time()
 if player.is_playing() == 0 and abs(place-length) < 10000 and len(playlist) > 0 and auto == 1:
 NewSong("next", 1)
 if player.is_playing() == 1:
 time_info =str(datetime.timedelta(seconds = round(place/1000))) + " / " + str(datetime.timedelta(seconds = round(length/1000)))
 time_label.config(text=time_info)
 timescale.set(place)
 win.after(1000,lambda:UpdateTime())
#starting the song
def NewSong(question, direction):
 win.focus() 
 #first, the play_index is updated
 global play_index
 play_index += direction
 if play_index > (len(playlist)-1):
 play_index = 0
 if question == "insert":
 playlist.insert(play_index,URLlist[song_index])
 else:
 if ran == 1 and len(playlist) > 1:
 counttemp = play_index
 while counttemp == play_index:
 play_index = random.randrange(len(playlist)-1)

#then, the song gets initialised 
  audio = []
 ydl_opts = {}
 with yt_dlp.YoutubeDL(ydl_opts) as ydl:
 info = ydl.extract_info(playlist[play_index], download=False)
  formats = info['formats']
 songtitle = info['title']
  for i,format in enumerate(formats):
 url = format['url']
  other = format['resolution']
 if other == "audio only":
 audio.append(url)
 
 if soundqualities == "best":
 stream = audio[len(audio)-1]
 else:
 qualities = len(audio)
 if soundquality > qualities:
 stream = audio[qualities]
 else:
 stream = audio[soundquality]
 #print(stream.quality, int(stream.get_filesize()/10000)/100, "mb")
 playurl = stream 
 media=instance.media_new(playurl)
 media.get_mrl()
 player.set_media(media)
 player.set_time(1000) 
 timescale.set(1000)
 btnPP.place(x=340, y=2)
 btnAddsong.place(x=170, y=62)
 btnBACK.place(x=295, y=2)
 btnBACK2.place(x=240, y=2)
 btnFWD.place(x=395, y=2)
 btnFWD2.place(x=445, y=2)
 timescale.place(x=370, y=68)
 player.play()
 btnPP.config(text="||")
 while player.is_playing() == 0:
 time.sleep(1)
 timescale.config(to = player.get_length())
 win.title(songtitle)
 return(0)
 
#this is to select the next song in the list
def Addsong():
 win.focus() 
 playlist.append(URLlist[song_index])
#next or previous song
def SkipSong(direction):
 win.focus()
 skip = play_index + direction
 if direction == -1 and player.get_time() > 10000:
 player.set_time(0)
 elif skip >= 0 and skip < len(playlist):
 NewSong("next", direction)
#this function is for downloading the song
def Download(song_url, song_title):
 outtmpl = song_title + '.%(ext)s'
 ydl_opts = {
 'format': 'bestaudio/best',
 'outtmpl': outtmpl,
 'postprocessors': [
 {'key': 'FFmpegExtractAudio','preferredcodec': 'mp3',
 'preferredquality': '192',
 },
 {'key': 'FFmpegMetadata'},
 ],
 }
 with yt_dlp.YoutubeDL(ydl_opts) as ydl:
 info_dict = ydl.extract_info("youtube.com" + song_url, download=True) 
#moving through the scale for time
def SetTime(timescale_var):
 place = player.get_time()
 if abs(int(timescale_var) - place) > 4000:
 player.set_time(int(timescale_var))
#this function is for moving back and forth in time of the song
def SkipTime(amount):
 win.focus()
 time_sum = player.get_time() + amount
 time_all = player.get_length()
 if time_sum < 0:
 time_sum = 0
 if time_sum>time_all:
 time_sum = time_all 
 timescale.set(time_sum)
#to pause by keypress (space)
def TogglePause1():
 if str(win.focus_get()) != str(".!entry"):
 funcPP()
 
#to pause by keypress or click
def TogglePause2():
 win.focus()
 pause = player.is_playing()
 player.set_pause(pause)
 if pause == 1:
 btnPP.config(text="|>")
 else:
 btnPP.config(text="||")
#import all songs from querie
def ImportAll():
 playlist.extend(URLlist)
#controlling the volume
def ChangeVolume(volume_var):
 player.audio_set_volume(int(volume_var))
#clear playlist
def ClearPlaylist():
 global playlist
 playlist = []
#setting sound quality
def ChangeQuality(amount):
 global soundquality, soundqualities
 if amount == "best":
 soundqualities = "best"
 else:
 soundqualities = ""
 if amount == 0:
 soundquality = 0
 elif amount == 1 or amount ==-1: 
 soundquality += amount
#toggle autoplay
def ToggleAutoplay():
 global auto
 auto = not(auto)
#toggle limit duration of song
def ToggleDurationLimit():
 global dur
 dur = not(dur)
#toggling shuffle
def ToggleShuffle():
 global ran
 ran = not(ran)
btnPP = Button(win, text = "||", command =(lambda: TogglePause2()))
btnBACK = Button(win, text = "<", command =(lambda: SkipTime(-10000)))
btnFWD = Button(win, text = ">", command =(lambda: SkipTime(10000)))
btnBACK2 = Button(win, text = "<<", command =(lambda: SkipSong(-1)))
btnFWD2 = Button(win, text = ">>", command =(lambda: SkipSong(1)))
btnDL = Button(win, text = "↓")
btnL = Button(win, text = "<-")
btnR = Button(win, text = "->")
btnPlay = Button(win, text = "OK")
btnAddsong = Button(win, text = "+")
timescale = Scale(win, from_=0, to=1000, orient=HORIZONTAL,length=200, variable = timescale_var, showvalue=0, command = SetTime)
volume_scale = Scale(win, from_=200, to=0, orient=VERTICAL,length=80, variable = volume_var, showvalue=0, command = ChangeVolume)
volume_scale.place(x=580, y=2)
volume_scale.set(100)
title_label = Label(win, text = "")
title_label.place(x=5, y=36)
time_label = Label(win, text = "")
time_label.place(x=220, y=66)
SearchBox = Entry(win, width=20) 
SearchBox.place(x=5, y=5)
SearchBox.bind('<Return>', Search)
btnL.place(x=5, y=62)
btnR.place(x=60, y=62)
btnPlay.place(x=115, y=62)
win.bind_all("<Button-1>", lambda event: event.widget.focus_set())
filemenu = Menu(win, tearoff=0)
filemenu.add_command(label="toggle shuffle", command=ToggleShuffle)
filemenu.add_command(label="toggle limit duration", command=ToggleDurationLimit)
filemenu.add_command(label="toggle autoplay", command=ToggleAutoplay)
editmenu = Menu(menubar, tearoff=0)
editmenu.add_command(label="all results to playlist", command=ImportAll)
editmenu.add_command(label="clear playlist", command=ClearPlaylist)
qualmenu = Menu(menubar, tearoff=0)
qualmenu.add_command(label="quality up", command=(lambda: ChangeQuality(1)))
qualmenu.add_command(label="quality down", command=(lambda: ChangeQuality(-1)))
qualmenu.add_command(label="best quality", command=(lambda: ChangeQuality("best")))
qualmenu.add_command(label="worst quality", command=(lambda: ChangeQuality(0)))
menubar.add_cascade(label="Quality", menu=qualmenu)
menubar.add_cascade(label="Options", menu=filemenu)
menubar.add_cascade(label="Playlists", menu=editmenu)
win.config(menu=menubar)
win.bind('<space>',lambda event:TogglePause1())
win.after(2000, lambda:UpdateTime())
SearchBox.focus()
win.mainloop()
#! /usr/bin/python3
from tkinter import *
from youtube_search import YoutubeSearch
import re,random, vlc,datetime, time,yt_dlp
#global vars 
ran = song_index = dur = timescale_var = 0
auto = 1
play_index=-1
volume_var= 100
soundquality = 5
soundqualities = "best"
URLlist = playlist = []
#window, player
win = Tk()
win.geometry('610x100') 
win.title("Youtube Player")
menubar = Menu(win)
instance = vlc.Instance()
player = instance.media_player_new() 
#making the search
def Search(event):
 global song_index, URLlist
 search_querie = str(SearchBox.get())
 song_index = 0
 results = YoutubeSearch(search_querie, max_results=40).to_dict()
 title=[]
 URLlist=[]
 resultcount = -1
 #the following loop is to optionally select only short songs <5min
 for v in results:
 duration = v['duration']
 if duration != 0:
 if duration.count(':') > 1 and dur == 1:
 continue
 if duration.count(':') == 1:
 m, s = duration.split(':')
 duration = int(m) * 60 + int(s)
 if duration > 300 and dur == 1:
 continue
 URLlist.append("https://www.youtube.com" + v['url_suffix'])
 resultcount+= 1
 title.append(re.sub(r"[^a-zA-Z0-9 .,:;+-=!?/()öäßü]", "", v['title']))
 btnPlay.focus()
 btnL.config(command = (lambda: TitleShift(title, -1, resultcount)))
 btnR.config(command = (lambda:TitleShift(title, 1, resultcount)))
 btnPlay.config(command = (lambda: NewSong("insert",1)))
 btnAddsong.config(command = (lambda: Addsong()))
 btnDL.place(x=505, y=2) 
 btnDL.config(command =(lambda: Download(URLlist[song_index],title[song_index])))
 title_label.config(text = title[song_index])
#moving through the songlist
def TitleShift(title,move, resultcount):
 win.focus()
 global song_index
 song_index += move
 if song_index < 0:
 song_index =resultcount
 if song_index > resultcount:
 song_index = 0
 title_label.config(text = title[song_index])
#this function keeps track of time and moves the timescale
def UpdateTime():
 length = player.get_length()
 place = player.get_time()
 if player.is_playing() == 0 and abs(place-length) < 10000 and len(playlist) > 0 and auto == 1:
 NewSong("next", 1)
 place = 0
 player.set_time(0)
 timescale.set(0)
 if player.is_playing() == 1:
 time_info =str(datetime.timedelta(seconds = round(place/1000))) + " / " + str(datetime.timedelta(seconds = round(length/1000)))
 time_label.config(text=time_info)
 timescale.set(place)
 win.after(1000,lambda:UpdateTime())
def GenerateStreamUrl(URL):
 audio = []
 ydl_opts = {}
 with yt_dlp.YoutubeDL(ydl_opts) as ydl:
 info = ydl.extract_info(URL, download=False)
 formats = info['formats']
 songtitle = info['title']
 for i,format in enumerate(formats):
 url = format['url']
 other = format['resolution']
 if other == "audio only":
 audio.append(url)
 return(audio, songtitle)
#starting the song
def NewSong(question, direction):
 win.focus() 
 #first, the play_index is updated
 global play_index
 play_index += direction
 if play_index > (len(playlist)-1):
 play_index = 0
 if question == "insert":
 playlist.insert(play_index,URLlist[song_index])
 else:
 if ran == 1 and len(playlist) > 1:
 counttemp = play_index
 while counttemp == play_index:
 play_index = random.randrange(len(playlist)-1)
 audio, songtitle = GenerateStreamUrl(playlist[play_index])
 
 if soundqualities == "best":
 stream = audio[len(audio)-1]
 else:
 qualities = len(audio)
 if soundquality > qualities:
 stream = audio[qualities]
 else:
 stream = audio[soundquality]
 #print(stream.quality, int(stream.get_filesize()/10000)/100, "mb")
 playurl = stream 
 media=instance.media_new(playurl)
 media.get_mrl()
 player.set_media(media)
 player.set_time(0) 
 timescale.set(0)
 btnPP.place(x=340, y=2)
 btnAddsong.place(x=170, y=62)
 btnBACK.place(x=295, y=2)
 btnBACK2.place(x=240, y=2)
 btnFWD.place(x=395, y=2)
 btnFWD2.place(x=445, y=2)
 timescale.place(x=370, y=68)
 player.play()
 btnPP.config(text="||")
 while player.is_playing() == 0:
 time.sleep(1)
 timescale.config(to = player.get_length())
 win.title(songtitle)
 return(0)
 
#this is to select the next song in the list
def Addsong():
 win.focus() 
 playlist.append(URLlist[song_index])
#next or previous song
def SkipSong(direction):
 win.focus()
 skip = play_index + direction
 if direction == -1 and player.get_time() > 10000:
 player.set_time(0)
 elif skip >= 0 and skip < len(playlist):
 NewSong("next", direction)
#this function is for downloading the song
def Download(song_url, song_title):
 outtmpl = song_title + '.%(ext)s'
 ydl_opts = {
 'format': 'bestaudio/best',
 'outtmpl': outtmpl,
 'postprocessors': [
 {'key': 'FFmpegExtractAudio','preferredcodec': 'mp3',
 'preferredquality': '192',
 },
 {'key': 'FFmpegMetadata'},
 ],
 }
 with yt_dlp.YoutubeDL(ydl_opts) as ydl:
 info_dict = ydl.extract_info("youtube.com" + song_url, download=True) 
#moving through the scale for time
def SetTime(timescale_var):
 place = player.get_time()
 if abs(int(timescale_var) - place) > 4000:
 player.set_time(int(timescale_var))
#this function is for moving back and forth in time of the song
def SkipTime(amount):
 win.focus()
 time_sum = player.get_time() + amount
 time_all = player.get_length()
 if time_sum < 0:
 time_sum = 0
 if time_sum>time_all:
 time_sum = time_all 
 timescale.set(time_sum)
#to pause by keypress (space)
def TogglePause1():
 if str(win.focus_get()) != str(".!entry"):
 funcPP()
 
#to pause by keypress or click
def TogglePause2():
 win.focus()
 pause = player.is_playing()
 player.set_pause(pause)
 if pause == 1:
 btnPP.config(text="|>")
 else:
 btnPP.config(text="||")
#import all songs from querie
def ImportAll():
 playlist.extend(URLlist)
#controlling the volume
def ChangeVolume(volume_var):
 player.audio_set_volume(int(volume_var))
#clear playlist
def ClearPlaylist():
 global playlist
 playlist = []
#setting sound quality
def ChangeQuality(amount):
 global soundquality, soundqualities
 if amount == "best":
 soundqualities = "best"
 else:
 soundqualities = ""
 if amount == 0:
 soundquality = 0
 elif amount == 1 or amount ==-1: 
 soundquality += amount
#toggle autoplay
def ToggleAutoplay():
 global auto
 auto = not(auto)
#toggle limit duration of song
def ToggleDurationLimit():
 global dur
 dur = not(dur)
#toggling shuffle
def ToggleShuffle():
 global ran
 ran = not(ran)
btnPP = Button(win, text = "||", command =(lambda: TogglePause2()))
btnBACK = Button(win, text = "<", command =(lambda: SkipTime(-10000)))
btnFWD = Button(win, text = ">", command =(lambda: SkipTime(10000)))
btnBACK2 = Button(win, text = "<<", command =(lambda: SkipSong(-1)))
btnFWD2 = Button(win, text = ">>", command =(lambda: SkipSong(1)))
btnDL = Button(win, text = "↓")
btnL = Button(win, text = "<-")
btnR = Button(win, text = "->")
btnPlay = Button(win, text = "OK")
btnAddsong = Button(win, text = "+")
timescale = Scale(win, from_=0, to=1000, orient=HORIZONTAL,length=200, variable = timescale_var, showvalue=0, command = SetTime)
volume_scale = Scale(win, from_=200, to=0, orient=VERTICAL,length=80, variable = volume_var, showvalue=0, command = ChangeVolume)
volume_scale.place(x=580, y=2)
volume_scale.set(100)
title_label = Label(win, text = "")
title_label.place(x=5, y=36)
time_label = Label(win, text = "")
time_label.place(x=220, y=66)
SearchBox = Entry(win, width=20) 
SearchBox.place(x=5, y=5)
SearchBox.bind('<Return>', Search)
btnL.place(x=5, y=62)
btnR.place(x=60, y=62)
btnPlay.place(x=115, y=62)
win.bind_all("<Button-1>", lambda event: event.widget.focus_set())
filemenu = Menu(win, tearoff=0)
filemenu.add_command(label="toggle shuffle", command=ToggleShuffle)
filemenu.add_command(label="toggle limit duration", command=ToggleDurationLimit)
filemenu.add_command(label="toggle autoplay", command=ToggleAutoplay)
editmenu = Menu(menubar, tearoff=0)
editmenu.add_command(label="all results to playlist", command=ImportAll)
editmenu.add_command(label="clear playlist", command=ClearPlaylist)
qualmenu = Menu(menubar, tearoff=0)
qualmenu.add_command(label="quality up", command=(lambda: ChangeQuality(1)))
qualmenu.add_command(label="quality down", command=(lambda: ChangeQuality(-1)))
qualmenu.add_command(label="best quality", command=(lambda: ChangeQuality("best")))
qualmenu.add_command(label="worst quality", command=(lambda: ChangeQuality(0)))
menubar.add_cascade(label="Quality", menu=qualmenu)
menubar.add_cascade(label="Options", menu=filemenu)
menubar.add_cascade(label="Playlists", menu=editmenu)
win.config(menu=menubar)
win.bind('<space>',lambda event:TogglePause1())
win.after(2000, lambda:UpdateTime())
SearchBox.focus()
win.mainloop()
added 91 characters in body
Source Link
Source Link

I found one major improvement to my code, which is to make it independant of pafy. Pafy is a badly functioning library, and in fact, it is only there to make using yt_dlp easier.

Also, I add a requirements.txt file to make install easier.

#! /usr/bin/python3
from tkinter import *
from youtube_search import YoutubeSearch
import re,random, vlc,datetime, time,yt_dlp
#global vars 
ran = song_index = dur = timescale_var = 0
auto = 1
play_index=-1
volume_var= 100
soundquality = 5
soundqualities = "best"
URLlist = playlist = []
#window, player
win = Tk()
win.geometry('610x100') 
win.title("Youtube Player")
menubar = Menu(win)
instance = vlc.Instance()
player = instance.media_player_new() 
#making the search
def Search(event):
 global song_index, URLlist
 search_querie = str(SearchBox.get())
 song_index = 0
 results = YoutubeSearch(search_querie, max_results=40).to_dict()
 title=[]
 URLlist=[]
 resultcount = -1
 #the following loop is to optionally select only short songs <5min
 for v in results:
 duration = v['duration']
 if duration != 0:
 if duration.count(':') > 1 and dur == 1:
 continue
 if duration.count(':') == 1:
 m, s = duration.split(':')
 duration = int(m) * 60 + int(s)
 if duration > 300 and dur == 1:
 continue
 URLlist.append("https://www.youtube.com" + v['url_suffix'])
 resultcount+= 1
 title.append(re.sub(r"[^a-zA-Z0-9 .,:;+-=!?/()öäßü]", "", v['title']))
 btnPlay.focus()
 btnL.config(command = (lambda: TitleShift(title, -1, resultcount)))
 btnR.config(command = (lambda:TitleShift(title, 1, resultcount)))
 btnPlay.config(command = (lambda: NewSong("insert",1)))
 btnAddsong.config(command = (lambda: Addsong()))
 btnDL.place(x=505, y=2) 
 btnDL.config(command =(lambda: Download(URLlist[song_index],title[song_index])))
 title_label.config(text = title[song_index])
#moving through the songlist
def TitleShift(title,move, resultcount):
 win.focus()
 global song_index
 song_index += move
 if song_index < 0:
 song_index =resultcount
 if song_index > resultcount:
 song_index = 0
 title_label.config(text = title[song_index])
#this function keeps track of time and moves the timescale
def UpdateTime():
 length = player.get_length()
 place = player.get_time()
 if player.is_playing() == 0 and abs(place-length) < 10000 and len(playlist) > 0 and auto == 1:
 NewSong("next", 1)
 if player.is_playing() == 1:
 time_info =str(datetime.timedelta(seconds = round(place/1000))) + " / " + str(datetime.timedelta(seconds = round(length/1000)))
 time_label.config(text=time_info)
 timescale.set(place)
 win.after(1000,lambda:UpdateTime())
#starting the song
def NewSong(question, direction):
 win.focus() 
 #first, the play_index is updated
 global play_index
 play_index += direction
 if play_index > (len(playlist)-1):
 play_index = 0
 if question == "insert":
 playlist.insert(play_index,URLlist[song_index])
 else:
 if ran == 1 and len(playlist) > 1:
 counttemp = play_index
 while counttemp == play_index:
 play_index = random.randrange(len(playlist)-1)
#then, the song gets initialised 
 audio = []
 ydl_opts = {}
 with yt_dlp.YoutubeDL(ydl_opts) as ydl:
 info = ydl.extract_info(playlist[play_index], download=False)
 formats = info['formats']
 songtitle = info['title']
 for i,format in enumerate(formats):
 url = format['url']
 other = format['resolution']
 if other == "audio only":
 audio.append(url)
 
 if soundqualities == "best":
 stream = audio[len(audio)-1]
 else:
 qualities = len(audio)
 if soundquality > qualities:
 stream = audio[qualities]
 else:
 stream = audio[soundquality]
 #print(stream.quality, int(stream.get_filesize()/10000)/100, "mb")
 playurl = stream 
 media=instance.media_new(playurl)
 media.get_mrl()
 player.set_media(media)
 player.set_time(1000) 
 timescale.set(1000)
 btnPP.place(x=340, y=2)
 btnAddsong.place(x=170, y=62)
 btnBACK.place(x=295, y=2)
 btnBACK2.place(x=240, y=2)
 btnFWD.place(x=395, y=2)
 btnFWD2.place(x=445, y=2)
 timescale.place(x=370, y=68)
 
 player.play()
 btnPP.config(text="||")
 while player.is_playing() == 0:
 time.sleep(1)
 timescale.config(to = player.get_length())
 win.title(songtitle)
 return(0)
 
#this is to select the next song in the list
def Addsong():
 win.focus() 
 playlist.append(URLlist[song_index])
#next or previous song
def SkipSong(direction):
 win.focus()
 skip = play_index + direction
 if direction == -1 and player.get_time() > 10000:
 player.set_time(0)
 elif skip >= 0 and skip < len(playlist):
 NewSong("next", direction)
#this function is for downloading the song
def Download(song_url, song_title):
 outtmpl = song_title + '.%(ext)s'
 ydl_opts = {
 'format': 'bestaudio/best',
 'outtmpl': outtmpl,
 'postprocessors': [
 {'key': 'FFmpegExtractAudio','preferredcodec': 'mp3',
 'preferredquality': '192',
 },
 {'key': 'FFmpegMetadata'},
 ],
 }
 with yt_dlp.YoutubeDL(ydl_opts) as ydl:
 info_dict = ydl.extract_info("youtube.com" + song_url, download=True) 
#moving through the scale for time
def SetTime(timescale_var):
 place = player.get_time()
 if abs(int(timescale_var) - place) > 4000:
 player.set_time(int(timescale_var))
#this function is for moving back and forth in time of the song
def SkipTime(amount):
 win.focus()
 time_sum = player.get_time() + amount
 time_all = player.get_length()
 if time_sum < 0:
 time_sum = 0
 if time_sum>time_all:
 time_sum = time_all 
 timescale.set(time_sum)
#to pause by keypress (space)
def TogglePause1():
 if str(win.focus_get()) != str(".!entry"):
 funcPP()
 
#to pause by keypress or click
def TogglePause2():
 win.focus()
 pause = player.is_playing()
 player.set_pause(pause)
 if pause == 1:
 btnPP.config(text="|>")
 else:
 btnPP.config(text="||")
#import all songs from querie
def ImportAll():
 playlist.extend(URLlist)
#controlling the volume
def ChangeVolume(volume_var):
 player.audio_set_volume(int(volume_var))
#clear playlist
def ClearPlaylist():
 global playlist
 playlist = []
#setting sound quality
def ChangeQuality(amount):
 global soundquality, soundqualities
 if amount == "best":
 soundqualities = "best"
 else:
 soundqualities = ""
 if amount == 0:
 soundquality = 0
 elif amount == 1 or amount ==-1: 
 soundquality += amount
#toggle autoplay
def ToggleAutoplay():
 global auto
 auto = not(auto)
#toggle limit duration of song
def ToggleDurationLimit():
 global dur
 dur = not(dur)
#toggling shuffle
def ToggleShuffle():
 global ran
 ran = not(ran)
btnPP = Button(win, text = "||", command =(lambda: TogglePause2()))
btnBACK = Button(win, text = "<", command =(lambda: SkipTime(-10000)))
btnFWD = Button(win, text = ">", command =(lambda: SkipTime(10000)))
btnBACK2 = Button(win, text = "<<", command =(lambda: SkipSong(-1)))
btnFWD2 = Button(win, text = ">>", command =(lambda: SkipSong(1)))
btnDL = Button(win, text = "↓")
btnL = Button(win, text = "<-")
btnR = Button(win, text = "->")
btnPlay = Button(win, text = "OK")
btnAddsong = Button(win, text = "+")
timescale = Scale(win, from_=0, to=1000, orient=HORIZONTAL,length=200, variable = timescale_var, showvalue=0, command = SetTime)
volume_scale = Scale(win, from_=200, to=0, orient=VERTICAL,length=80, variable = volume_var, showvalue=0, command = ChangeVolume)
volume_scale.place(x=580, y=2)
volume_scale.set(100)
title_label = Label(win, text = "")
title_label.place(x=5, y=36)
time_label = Label(win, text = "")
time_label.place(x=220, y=66)
SearchBox = Entry(win, width=20) 
SearchBox.place(x=5, y=5)
SearchBox.bind('<Return>', Search)
btnL.place(x=5, y=62)
btnR.place(x=60, y=62)
btnPlay.place(x=115, y=62)
win.bind_all("<Button-1>", lambda event: event.widget.focus_set())
filemenu = Menu(win, tearoff=0)
filemenu.add_command(label="toggle shuffle", command=ToggleShuffle)
filemenu.add_command(label="toggle limit duration", command=ToggleDurationLimit)
filemenu.add_command(label="toggle autoplay", command=ToggleAutoplay)
editmenu = Menu(menubar, tearoff=0)
editmenu.add_command(label="all results to playlist", command=ImportAll)
editmenu.add_command(label="clear playlist", command=ClearPlaylist)
qualmenu = Menu(menubar, tearoff=0)
qualmenu.add_command(label="quality up", command=(lambda: ChangeQuality(1)))
qualmenu.add_command(label="quality down", command=(lambda: ChangeQuality(-1)))
qualmenu.add_command(label="best quality", command=(lambda: ChangeQuality("best")))
qualmenu.add_command(label="worst quality", command=(lambda: ChangeQuality(0)))
menubar.add_cascade(label="Quality", menu=qualmenu)
menubar.add_cascade(label="Options", menu=filemenu)
menubar.add_cascade(label="Playlists", menu=editmenu)
win.config(menu=menubar)
win.bind('<space>',lambda event:TogglePause1())
win.after(2000, lambda:UpdateTime())
SearchBox.focus()
win.mainloop()

Requirements:

python_vlc==3.0.7110
youtube_search==2.1.2
yt_dlp==2022年11月11日
lang-py

AltStyle によって変換されたページ (->オリジナル) /