add format, title

This commit is contained in:
VALLONGOL 2025-09-15 11:06:17 +02:00
parent e3fbb24ef4
commit 6f0ca29327
2 changed files with 47 additions and 20 deletions

View File

@ -1,4 +1,3 @@
import logging
import traceback
from threading import Thread
@ -36,7 +35,7 @@ class Downloader:
def __init__(self):
self.progress_callback: Optional[Callable[[int], None]] = None
self.completion_callback: Optional[Callable[[Optional[str]], None]] = None
self.formats_callback: Optional[Callable[[Optional[List[VideoFormat]]], None]] = None
self.formats_callback: Optional[Callable[[Optional[Dict[str, Any]], Optional[List[VideoFormat]]], None]] = None
def _progress_hook(self, d: Dict[str, Any]):
if d["status"] == "downloading":
@ -48,16 +47,21 @@ class Downloader:
logger.info("yt-dlp finished downloading.")
def _get_formats_task(self, url: str):
"""Task to fetch video formats in a thread."""
"""Task to fetch video formats and info in a thread."""
try:
logger.info(f"Fetching formats for URL: {url}")
ydl_opts = {"noplaylist": True}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(url, download=False)
video_info = {
"title": info.get("title", "N/A"),
"uploader": info.get("uploader", "N/A"),
"duration_string": info.get("duration_string", "N/A"),
}
formats = []
for f in info.get("formats", []):
# We are interested in mp4 files that have video
if f.get("vcodec", "none") != "none" and f.get("ext") == "mp4":
note = "Progressive" if f.get("acodec", "none") != "none" else "Video Only"
formats.append(VideoFormat(
@ -68,21 +72,20 @@ class Downloader:
note=note
))
# Sort formats: progressive first, then by resolution
formats.sort(key=lambda x: (x.note != "Progressive", -int(x.resolution.replace("p", "")) if x.resolution.replace("p", "").isdigit() else 0))
logger.info(f"Found {len(formats)} suitable formats.")
if self.formats_callback:
self.formats_callback(formats)
self.formats_callback(video_info, formats)
except Exception as e:
error_message = f"Failed to fetch formats: {e}"
logger.error(error_message)
logger.debug(traceback.format_exc())
if self.formats_callback:
self.formats_callback(None) # Indicate failure
self.formats_callback(None, None) # Indicate failure
def get_video_formats(self, url: str, formats_callback: Callable[[Optional[List[VideoFormat]]], None]):
def get_video_formats(self, url: str, formats_callback: Callable[[Optional[Dict[str, Any]], Optional[List[VideoFormat]]], None]):
"""Starts the format fetching process in a new thread."""
self.formats_callback = formats_callback
thread = Thread(target=self._get_formats_task, args=(url,), daemon=True)
@ -128,4 +131,4 @@ class Downloader:
thread = Thread(
target=self._download_task, args=(url, download_path, format_id), daemon=True
)
thread.start()
thread.start()

View File

@ -1,8 +1,9 @@
import logging
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from tkinter.scrolledtext import ScrolledText
from typing import Optional, List
from typing import Optional, List, Dict, Any
from downloaderyoutube.core.core import Downloader, VideoFormat
from downloaderyoutube.utils.logger import add_tkinter_handler, get_logger
@ -35,8 +36,13 @@ class App(tk.Frame):
self.download_path: Optional[str] = None
self.available_formats: List[VideoFormat] = []
# StringVars for video info labels
self.title_var = tk.StringVar(value="Titolo: N/A")
self.uploader_var = tk.StringVar(value="Autore: N/A")
self.duration_var = tk.StringVar(value="Durata: N/A")
self.master.title("YouTube Downloader")
self.master.geometry("800x600")
self.master.geometry("800x650") # Increased height for new info panel
self.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
@ -57,6 +63,14 @@ class App(tk.Frame):
)
self.analyze_button.pack(side=tk.LEFT, padx=(5, 0))
# --- Video Info Panel ---
info_frame = ttk.LabelFrame(self, text="Informazioni Video")
info_frame.pack(fill=tk.X, pady=5, padx=2)
ttk.Label(info_frame, textvariable=self.title_var).pack(anchor="w", padx=5)
ttk.Label(info_frame, textvariable=self.uploader_var).pack(anchor="w", padx=5)
ttk.Label(info_frame, textvariable=self.duration_var).pack(anchor="w", padx=5)
# --- Path Frame ---
path_frame = ttk.Frame(self)
path_frame.pack(fill=tk.X, pady=5)
@ -120,25 +134,35 @@ class App(tk.Frame):
self.analyze_button.config(state="disabled")
self.download_button.config(state="disabled")
self.format_combobox.set("Analisi in corso...")
self.title_var.set("Titolo: Analisi in corso...")
self.uploader_var.set("Autore: Analisi in corso...")
self.duration_var.set("Durata: Analisi in corso...")
self.downloader.get_video_formats(url, self._on_formats_received)
def _on_formats_received(self, formats: Optional[List[VideoFormat]]):
# This is called from a different thread, so we schedule GUI updates
self.master.after(0, self._update_formats_combobox, formats)
def _on_formats_received(self, video_info: Optional[Dict[str, Any]], formats: Optional[List[VideoFormat]]):
self.master.after(0, self._update_ui_after_analysis, video_info, formats)
def _update_formats_combobox(self, formats: Optional[List[VideoFormat]]):
def _update_ui_after_analysis(self, video_info: Optional[Dict[str, Any]], formats: Optional[List[VideoFormat]]):
self.analyze_button.config(state="normal")
if formats:
logger.info("Successfully fetched formats. Populating combobox.")
if video_info and formats:
logger.info("Successfully fetched video info and formats.")
self.title_var.set(f"Titolo: {video_info['title']}")
self.uploader_var.set(f"Autore: {video_info['uploader']}")
self.duration_var.set(f"Durata: {video_info['duration_string']}")
self.available_formats = formats
self.format_combobox["values"] = [str(f) for f in formats]
self.format_combobox.current(0)
self.format_combobox.config(state="readonly")
self.download_button.config(state="normal")
else:
logger.error("Failed to fetch video formats.")
messagebox.showerror("Error", "Could not retrieve video formats. Check the URL and logs.")
logger.error("Failed to fetch video info or formats.")
messagebox.showerror("Error", "Could not retrieve video information. Check the URL and logs.")
self.format_combobox.set("Analisi fallita.")
self.format_combobox["values"] = []
self.title_var.set("Titolo: N/A")
self.uploader_var.set("Autore: N/A")
self.duration_var.set("Durata: N/A")
def start_download(self):
url = self.url_entry.get()
@ -180,4 +204,4 @@ class App(tk.Frame):
if error_message:
messagebox.showerror("Download Failed", error_message)
else:
messagebox.showinfo("Success", "Video downloaded successfully!")
messagebox.showinfo("Success", "Video downloaded successfully!")