[유틸] 유튜브 다운로드 프로그램 만들기 공유
유튜브 다운로드 프로그램 만드는게 유행인듯 싶어서 관련자료 공유하고 갑니다.
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() |

댓글 6개
실행파일이 어떤건가요?
@데코이 실행파일은 없고 파이썬으로 직접 소스 붙어 넣기 하고 실행하면 됩니다 vscode 설치하고
파이썬 설치(https://www.python.org/ ) 하면 가능합니다.
감사하고 좋기는 한데...
이거... 불법은 아니겠죠?
@휴매니아 - 개인적인 용도로, 저작권자가 명시적으로 허용한 콘텐츠를 다운로드하는 경우
- 자신이 업로드한 영상을 백업하거나 저장하는 경우
개인용도면 문제가 없다고 GTP 답변이 있네요
@카이루 감사합니다.^^

감사 합니다.
게시글 목록
| 번호 | 제목 |
|---|---|
| 1252 | |
| 1251 | |
| 1250 | |
| 1248 | |
| 1247 | |
| 1246 | |
| 1245 | |
| 1243 | |
| 1242 | |
| 1241 | |
| 1240 | |
| 1232 | |
| 1226 | |
| 1225 | |
| 1221 | |
| 1217 | |
| 1215 | |
| 1211 | |
| 1210 | |
| 1206 | |
| 1205 | |
| 1202 | |
| 1199 | |
| 1195 | |
| 1190 | |
| 1152 | |
| 1138 | |
| 1136 | |
| 1134 | |
| 1132 |
댓글 작성
댓글을 작성하시려면 로그인이 필요합니다.
로그인하기