[유틸] 유튜브 다운로드 프로그램 만들기 공유 정보
[유틸] 유튜브 다운로드 프로그램 만들기 공유
본문
유튜브 다운로드 프로그램 만드는게 유행인듯 싶어서 관련자료 공유하고 갑니다.
ffmpeg-release-essentials.zip 파일을 다운로드 하세요..
바로링크 https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip
bin/ffmpeg.exe를 같은 폴더 복사
import tkinter as tk from tkinter import ttk, filedialog, messagebox import threading import yt_dlp import os class YouTubeDownloader: def __init__(self, root): self.root = root self.root.title("YouTube Downloader (카이루 v1.0)") self.root.geometry("700x680") self.root.resizable(False, False) style = ttk.Style() style.theme_use("clam") # clam, alt, default 등 선택 가능 style.configure("TLabel", font=("맑은 고딕", 11)) style.configure("TButton", font=("맑은 고딕", 11), padding=6) style.configure("TEntry", padding=4) # 제목 title = ttk.Label(root, text=" 카이루 유튜브 다운로드 2025 ", font=("맑은 고딕", 18, "bold"), foreground="#2c3e50") title.pack(pady=15) # URL 입력 프레임 url_frame = ttk.LabelFrame(root, text=" YouTube URL 입력 (최대 10개) ", padding=10) url_frame.pack(padx=20, pady=10, fill="x") self.url_entries = [] for i in range(10): row_frame = ttk.Frame(url_frame) row_frame.pack(fill="x", pady=2) num_label = ttk.Label(row_frame, text=f"{i+1:02d}.", width=3, anchor="center") num_label.pack(side="left") entry = ttk.Entry(row_frame, width=80) entry.pack(side="left", padx=5) self.url_entries.append(entry) # 저장 경로 선택 path_frame = ttk.Frame(root) path_frame.pack(pady=10, fill="x") ttk.Button(path_frame, text="? 저장 경로 선택", command=self.choose_directory).pack(side="left", padx=10) self.save_dir = tk.StringVar(value=os.getcwd()) ttk.Label(path_frame, textvariable=self.save_dir, foreground="#2980b9").pack(side="left") # 진행 상태 표시 progress_frame = ttk.Frame(root) progress_frame.pack(pady=20) self.progress_label = ttk.Label(progress_frame, text="대기 중...") self.progress_label.pack() self.progress_bar = ttk.Progressbar(progress_frame, length=500, mode="determinate") self.progress_bar.pack(pady=10) # 버튼 프레임 button_frame = ttk.Frame(root) button_frame.pack(pady=20) ttk.Button(button_frame, text="? MP3 다운로드", command=lambda: self.start_download("mp3")).grid(row=0, column=0, padx=15) ttk.Button(button_frame, text="? 영상(720p)", command=lambda: self.start_download("video_720")).grid(row=0, column=1, padx=15) ttk.Button(button_frame, text="? 영상(고화질)", command=lambda: self.start_download("video_hd")).grid(row=0, column=2, padx=15) def choose_directory(self): directory = filedialog.askdirectory() if directory: self.save_dir.set(directory) def start_download(self, mode): urls = [e.get().strip() for e in self.url_entries if e.get().strip()] if not urls: messagebox.showerror("에러", "최소 1개 이상의 URL을 입력하세요!") return self.progress_bar["value"] = 0 self.progress_bar["maximum"] = len(urls) self.progress_label.config(text="다운로드 준비 중...") threading.Thread(target=self._download_worker, args=(mode, urls, self.save_dir.get()), daemon=True).start() def _download_worker(self, mode, urls, save_dir): def progress_hook(d, idx, total): if d['status'] == 'downloading': percent = d.get('_percent_str', '0%').strip() self.root.after(0, lambda: self.progress_label.config( text=f"[{idx}/{total}] 다운로드 중... {percent}")) elif d['status'] == 'finished': self.root.after(0, lambda: self.progress_label.config( text=f"[{idx}/{total}] 변환 중...")) try: total = len(urls) for idx, url in enumerate(urls, start=1): if mode == "mp3": ydl_opts = { "format": "bestaudio/best", "outtmpl": os.path.join(save_dir, "%(title)s"), "postprocessors": [{ "key": "FFmpegExtractAudio", "preferredcodec": "mp3", "preferredquality": "0", }], "progress_hooks": [lambda d, i=idx: progress_hook(d, i, total)], "noplaylist": True, } elif mode == "video_720": ydl_opts = { "format": "bestvideo[height<=720]+bestaudio/best[height<=720]", "merge_output_format": "mp4", "outtmpl": os.path.join(save_dir, "%(title)s_[720p].mp4"), "progress_hooks": [lambda d, i=idx: progress_hook(d, i, total)], "noplaylist": True, } elif mode == "video_hd": ydl_opts = { "format": "bestvideo[height>=1080]+bestaudio/best", "merge_output_format": "mp4", "outtmpl": os.path.join(save_dir, "%(title)s_[1080p+].mp4"), "progress_hooks": [lambda d, i=idx: progress_hook(d, i, total)], "noplaylist": True, } with yt_dlp.YoutubeDL(ydl_opts) as ydl: ydl.download([url]) self.root.after(0, lambda val=idx: self.progress_bar.config(value=val)) self.root.after(0, lambda: self.progress_label.config(text="✅ 전체 다운로드 완료")) except Exception as e: self.root.after(0, lambda: messagebox.showerror("다운로드 실패", str(e))) if __name__ == "__main__": root = tk.Tk() app = YouTubeDownloader(root) root.mainloop() |
0
댓글 2개

실행파일이 어떤건가요?

감사하고 좋기는 한데...
이거... 불법은 아니겠죠?