Ajout de la gestion des playlist, des vidéo n'ayant pas de jaquette et ajout du racourci clavier "entrer" dans la zone de texte pour ajouter l'URL

This commit is contained in:
Phytacode 2024-11-16 00:00:01 +01:00
parent 84bd38eb30
commit 728be287f4
2 changed files with 102 additions and 54 deletions

154
main.py
View File

@ -7,8 +7,12 @@ from PIL import Image, ImageTk
from tkinter.ttk import Progressbar from tkinter.ttk import Progressbar
import threading import threading
import queue import queue
from tkinter.messagebox import askyesno
import os
def add_url(): res_directory = 'res'
def add_url(url=False, dowload_playlist=False):
#Ajoute un classe pour intercepter les logs #Ajoute un classe pour intercepter les logs
class YTDLLogger: class YTDLLogger:
@ -16,25 +20,105 @@ def add_url():
Logger personnalisé pour capturer et afficher les messages de yt-dlp. Logger personnalisé pour capturer et afficher les messages de yt-dlp.
""" """
def debug(self, msg): def debug(self, msg):
print(msg) # Affiche les messages de debug # Affiche les messages de debug
ProgresseLabel.config(text=msg) ProgresseLabel.config(text=msg)
def warning(self, msg): def warning(self, msg):
print(f"WARNING: {msg}") # Affiche les avertissements # Affiche les avertissements
ProgresseLabel.config(text=f"WARNING: {msg}")
def error(self, msg): def error(self, msg):
print(f"ERROR: {msg}") # Affiche les erreurs # Affiche les erreurs
ProgresseLabel.config(text=f"ERROR: {msg}")
#Récuperer l'url #Ajoute une fonction pour ajouter une vidéo a la liste
def add_movies(info, is_playlist=False) :
title = info.get('title', 'Titre indisponible')
view_count = info.get('view_count', None)
subtitlte = (
info.get('artist', info.get('uploader', 'Artiste indisponible'))
+ ' · '
+ 'Nombre de vues indisponible' if view_count is None else '{:,}'.format(view_count).replace(',', ' ')
+ ' vues'
)
thumbnail_url = info.get('thumbnail')
if is_playlist :
title = '[Playlist] ' + title
subtitlte += ' · ' + str(info.get('playlist_count', 'Nombre de vidéo indisponible')) + ' vidéos'
try:
thumbnail_url = info.get('thumbnails')[0].get('url')
except TypeError :
thumbnail_url = False
# Création d'un cadre pour chaque vidéo
cadre = Frame(scrollable_frame)
cadre.pack(fill=X, padx=10, pady=5)
if thumbnail_url :
response = requests.get(thumbnail_url)
image = Image.open(BytesIO(response.content))
width, height = image.size
# Découper l'image en un carré centré
square_size = min(width, height)
left = (width - square_size) // 2
top = (height - square_size) // 2
# Calculer les coordonnées du coin inférieur droit du carré
right = left + square_size
bottom = top + square_size
# Découper l'image carrée
image = image.crop((left, top, right, bottom))
else :
image = Image.open(os.path.join(os.path.join(res_directory, "img"), 'jaquette_default.png'))
image.thumbnail((50, 50))
# Charger l'image et l'afficher
image = ImageTk.PhotoImage(image)
image_label = Label(cadre, image=image)
image_label.image = image # Préserver la référence pour éviter le garbage collection
image_label.pack(side=LEFT, padx=5)
# Ajouter les titres
texte_frame = Frame(cadre)
texte_frame.pack(side=LEFT, padx=10, fill=BOTH, expand=True)
label_texte1 = Label(texte_frame, text=title, font=("Arial", 12, "bold"))
label_texte1.pack(anchor="w")
label_texte2 = Label(texte_frame, text=subtitlte, font=("Arial", 10))
label_texte2.pack(anchor="w")
# Ajouter un bouton "Supprimer"
menu_button = Button(cadre, text="Supprimer", relief=FLAT, command=cadre.destroy)
menu_button.pack(side=RIGHT)
#Récuperer l'url si non fournie comme argument
if not url:
url = EntryURL.get() url = EntryURL.get()
if '&list=' in url :
if askyesno('Playlist', 'Attention, vous vous apretez à ajouter une playlist générer automatiquement par youtube, Pour garder uniquement la vidéo que vous regardiez, appuyer sur oui, si vous voulez télecharger la playlist, appuyer sur non.') :
url = url.split('&list=')[0]
# Effacer l'entrée URL # Effacer l'entrée URL
EntryURL.delete(0, END) EntryURL.delete(0, END)
ydl_opts = { ydl_opts = {
'quiet': True, # Supprime la sortie standard (redirigée vers le logger) 'quiet': True, # Supprime la sortie standard (redirigée vers le logger)
'logger': YTDLLogger(), # Utilise le logger personnalisé 'logger': YTDLLogger(),
'extract_flat': True, # Utilise le logger personnalisé
} }
if dowload_playlist :
ydl_opts['extract_flat'] = False
# Queue pour recuperer les donnes # Queue pour recuperer les donnes
q = queue.Queue() q = queue.Queue()
@ -57,55 +141,18 @@ def add_url():
if isinstance(info, dict): # Si l'info est un dictionnaire (métadonnées) if isinstance(info, dict): # Si l'info est un dictionnaire (métadonnées)
ProgresseLabel.config(text=f"Dowloading complet") ProgresseLabel.config(text=f"Dowloading complet")
title = info.get('title', 'Titre indisponible')
subtitlte = (
info.get('artist', info.get('uploader', 'Artiste indisponible'))
+ ' · '
+ '{:,}'.format(info.get('view_count', 'Nombre de vue indisponible')).replace(',', ' ')
+ ' vues'
)
thumbnail_url = info.get('thumbnail')
response = requests.get(thumbnail_url) if info.get('_type', None) == 'playlist' : #Si c'est une playlist
image = Image.open(BytesIO(response.content)) if dowload_playlist : # Vérifie si l'utilisateur a déja répondus a la question suivante
width, height = image.size for video in info.get('entries') :
add_movies(video)
elif askyesno('Playlist', f"L'URL que vous avez fourni est une playlist, voulez-vous l'ajouter en tant que playlist ou en plusieurs vidéos ?\nAttention, en fonction du nombre de vidéos (ici {str(info.get('playlist_count', 'Nombre de vidéo indisponible'))}), cette opération peut prendre du temps\n\n(Oui -> playliste / Non -> Vidéos)") : #Demande a l'utilisateur si on ajoute chaque vidéo séparément
add_movies(info, True)
else :
add_url(url, True)
else :
add_movies(info)
# Découper l'image en un carré centré
square_size = min(width, height)
left = (width - square_size) // 2
top = (height - square_size) // 2
# Calculer les coordonnées du coin inférieur droit du carré
right = left + square_size
bottom = top + square_size
# Découper l'image carrée
image = image.crop((left, top, right, bottom))
image.thumbnail((50, 50))
# Création d'un cadre pour chaque vidéo
cadre = Frame(scrollable_frame)
cadre.pack(fill=X, padx=10, pady=5)
# Charger l'image et l'afficher
image = ImageTk.PhotoImage(image)
image_label = Label(cadre, image=image)
image_label.image = image # Préserver la référence pour éviter le garbage collection
image_label.pack(side=LEFT, padx=5)
# Ajouter les titres
texte_frame = Frame(cadre)
texte_frame.pack(side=LEFT, padx=10, fill=BOTH, expand=True)
label_texte1 = Label(texte_frame, text=title, font=("Arial", 12, "bold"))
label_texte1.pack(anchor="w")
label_texte2 = Label(texte_frame, text=subtitlte, font=("Arial", 10))
label_texte2.pack(anchor="w")
# Ajouter un bouton "Supprimer"
menu_button = Button(cadre, text="Supprimer", relief=FLAT, command=cadre.destroy)
menu_button.pack(side=RIGHT)
else: # Si c'est une erreur else: # Si c'est une erreur
ProgresseLabel.config(text=info) ProgresseLabel.config(text=info)
@ -146,6 +193,7 @@ EntryFrame.pack(fill="x", padx=5, pady=2.5)
EntryURL = Entry(EntryFrame) EntryURL = Entry(EntryFrame)
EntryURL.pack(side=LEFT, fill="x", expand=True, padx=2.5) EntryURL.pack(side=LEFT, fill="x", expand=True, padx=2.5)
EntryURL.bind("<Return>", lambda event=None: add_url())
EntryButton = Button(EntryFrame, text="Ajouter", command=add_url) EntryButton = Button(EntryFrame, text="Ajouter", command=add_url)
EntryButton.pack(side=RIGHT, padx=3.5) EntryButton.pack(side=RIGHT, padx=3.5)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB