Deepseek ile oluşturduğum video indirici. Satır satır link veriliyor verilen linkleri mp4 ya da mp3 olarak indiriyor. İhtiyacı olan kullansın diye kodu paylaşıyorum.
Kod:
import os
import time
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from threading import Thread
import yt_dlp
from datetime import datetime
class YouTubeDownloader:
def __init__(self, master):
self.master = master
master.title("YouTube İndirici")
master.geometry("720x500")
self.setup_ui()
self.setup_ydl_options()
def setup_ui(self):
# Temel Stil
self.style = ttk.Style()
self.style.theme_use('clam')
self.style.configure("TButton", padding=6, font=('Arial', 10))
self.style.configure("TLabel", font=('Arial', 10))
# URL Giriş
url_frame = ttk.Frame(self.master)
url_frame.pack(pady=10, padx=20, fill=tk.X)
ttk.Label(url_frame, text="YouTube URL'leri (Her satıra bir URL):").pack(anchor=tk.W)
self.url_text = tk.Text(url_frame, height=8, width=80)
self.url_text.pack(pady=5)
# Ayarlar
settings_frame = ttk.Frame(self.master)
settings_frame.pack(pady=10, padx=20, fill=tk.X)
# Klasör Seçimi
ttk.Label(settings_frame, text="Kaydetme Klasörü:").grid(row=0, column=0, sticky=tk.W)
self.folder_path = tk.StringVar(value=os.path.expanduser("~/Downloads"))
ttk.Entry(settings_frame, textvariable=self.folder_path, width=50).grid(row=0, column=1, padx=5)
ttk.Button(settings_frame, text="Gözat", command=self.select_folder).grid(row=0, column=2)
# Format Seçimi
ttk.Label(settings_frame, text="İndirme Formatı:").grid(row=1, column=0, sticky=tk.W, pady=5)
self.format_var = tk.StringVar(value="video")
ttk.Radiobutton(settings_frame, text="Video (MP4)", variable=self.format_var, value="video").grid(row=1, column=1, sticky=tk.W)
ttk.Radiobutton(settings_frame, text="Sadece Ses (MP3)", variable=self.format_var, value="audio").grid(row=1, column=2, sticky=tk.W)
# İlerleme Çubuğu
self.progress = ttk.Progressbar(self.master, orient='horizontal', mode='determinate')
self.progress.pack(pady=10, padx=20, fill=tk.X)
# Durum Bilgisi
self.status_var = tk.StringVar()
ttk.Label(self.master, textvariable=self.status_var).pack(pady=5)
# Kontrol Butonları
btn_frame = ttk.Frame(self.master)
btn_frame.pack(pady=10)
ttk.Button(btn_frame, text="İndirmeyi Başlat", command=self.start_download).grid(row=0, column=0, padx=5)
ttk.Button(btn_frame, text="Temizle", command=self.clear_inputs).grid(row=0, column=1, padx=5)
def setup_ydl_options(self):
self.ydl_opts = {
'outtmpl': os.path.join(self.folder_path.get(), '%(title)s.%(ext)s'),
'progress_hooks': [self.update_progress],
'restrictfilenames': True,
'noplaylist': True,
'postprocessor_args': ['-map_metadata', '-1'] # Metadata'yı temizle
}
def select_folder(self):
folder = filedialog.askdirectory()
if folder:
self.folder_path.set(folder)
self.setup_ydl_options()
def update_progress(self, d):
if d['status'] == 'downloading':
total = d.get('total_bytes') or d.get('total_bytes_estimate')
if total:
percent = (d['downloaded_bytes'] / total) * 100
self.progress['value'] = percent
self.status_var.set(f"İndiriliyor: {os.path.basename(d['filename'])} - {percent:.1f}%")
self.master.update_idletasks()
def download_media(self, url):
try:
if self.format_var.get() == 'video':
format_selector = 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/bestvideo+bestaudio/best'
postprocessors = [{
'key': 'FFmpegVideoConvertor',
'preferedformat': 'mp4'
}]
else:
format_selector = 'bestaudio/best'
postprocessors = [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}]
opts = {
**self.ydl_opts,
'format': format_selector,
'postprocessors': postprocessors,
'merge_output_format': 'mp4'
}
with yt_dlp.YoutubeDL(opts) as ydl:
info = ydl.extract_info(url, download=True)
filename = ydl.prepare_filename(info)
self.update_file_times(filename)
return True
except Exception as e:
messagebox.showerror("Hata", f"{url}\n{str(e)}")
return False
def update_file_times(self, filename):
"""Dosya zaman damgalarını güncelleyen fonksiyon"""
try:
now = time.time()
# Değiştirme ve erişim zamanını güncelle
os.utime(filename, (now, now))
# Windows'ta oluşturma zamanını güncelle
if os.name == 'nt':
from pywin32 import win32file, win32con
handle = win32file.CreateFile(
filename,
win32con.GENERIC_WRITE,
0, None,
win32con.OPEN_EXISTING,
0, None
)
win32file.SetFileTime(handle, datetime.fromtimestamp(now), None, None)
handle.close()
except Exception as e:
print(f"Zaman güncelleme hatası: {str(e)}")
def start_download(self):
urls = [url.strip() for url in self.url_text.get("1.0", tk.END).split('\n') if url.strip()]
if not urls:
messagebox.showwarning("Uyarı", "Lütfen en az bir YouTube URL'si girin!")
return
if not os.path.exists(self.folder_path.get()):
os.makedirs(self.folder_path.get())
self.progress['value'] = 0
self.status_var.set("İndirme başlatılıyor...")
Thread(target=self.process_downloads, args=(urls,), daemon=True).start()
def process_downloads(self, urls):
success = 0
for index, url in enumerate(urls):
self.status_var.set(f"İşleniyor ({index+1}/{len(urls)})...")
if self.download_media(url):
success += 1
messagebox.showinfo("Tamamlandı", f"İndirme tamamlandı!\nBaşarılı: {success}\nBaşarısız: {len(urls)-success}")
self.progress['value'] = 100
self.status_var.set("Hazır")
def clear_inputs(self):
self.url_text.delete("1.0", tk.END)
self.progress['value'] = 0
self.status_var.set("")
if __name__ == "__main__":
root = tk.Tk()
app = YouTubeDownloader(root)
root.mainloop()