본문 바로가기

파이썬 헛다리/파이썬 윈도우

[윈도우] 파이썬을 활용한 유튜브 미디어(mp4) 추출 프로그램 개발기

728x90

 

 

적당한 경로에 만들어준후

yt_mp4.py

 

import yt_dlp                          # 유튜브 영상 정보를 분석하고 다운로드하는 핵심 엔진
import tkinter as tk                   # 윈도우 창(GUI)을 만들기 위한 기본 라이브러리
from tkinter import messagebox, filedialog, ttk  # 팝업 메시지, 폴더 선택, 진행바 등 세부 도구
import os                              # 컴퓨터의 파일 경로 및 폴더 시스템을 다루는 도구
import threading                       # 다운로드 중에도 프로그램이 멈추지 않게 조수를 고용하는 기능
import sys                             # 파이썬 실행 환경의 시스템 정보를 확인하는 도구

# [함수 1] 프로그램이 실행될 때 FFmpeg 파일이 어디 있는지 찾아주는 기능
def get_ffmpeg_path():
    # .exe 파일로 만들었을 때와 .py 소스 상태일 때의 경로 차이를 해결함
    if getattr(sys, 'frozen', False):
        return os.path.dirname(sys.executable) # 실행파일(.exe)이 있는 폴더 위치 반환
    return os.path.dirname(os.path.abspath(__file__)) # 소스코드(.py)가 있는 폴더 위치 반환

# [함수 2] 사용자가 버튼을 눌렀을 때 실행되는 실제 다운로드 작업
def download_video():
    url = entry.get()                  # 입력창에 사용자가 넣은 주소를 가져옴
    selected_res = res_combo.get()     # 드롭다운 메뉴에서 선택된 화질(예: 1080p)을 가져옴
    
    # 1. 입력 검사: 주소가 비어있으면 경고를 띄우고 종료
    if not url:
        messagebox.showwarning("경고", "유튜브 URL을 입력하세요!")
        return

    # 2. 저장 위치: 어디에 저장할지 묻는 창을 띄움
    save_path = filedialog.askdirectory()
    if not save_path:                  # 폴더를 선택하지 않고 닫으면 종료
        return

    # 3. 화질 텍스트 처리: "1080p (Full HD)"에서 숫자 "1080"만 남김
    # 'p' 글자를 기준으로 앞부분만 자르고 공백을 제거함
    res_limit = selected_res.split('p')[0].strip()

    # [보조 함수] 다운로드 진행률을 실시간으로 화면에 그려주는 역할
    def progress_hook(d):
        if d['status'] == 'downloading':         # 현재 다운로드 중인 상태라면
            # 엔진이 보내주는 퍼센트 문자열(예: ' 85.5%')에서 '%'를 지움
            p = d.get('_percent_str', '0%').replace('%','')
            try:
                progress_var.set(float(p))       # 진행바(Progressbar)의 게이지를 채움
                status_label.config(text=f"다운로드 중... {p}%") # 글자로 표시
                root.update_idletasks()          # 화면을 즉시 새로고침 (안 하면 멈춰 보임)
            except:
                pass
        elif d['status'] == 'finished':          # 파일 다운로드가 끝난 상태라면
            # 고화질은 영상과 소리를 합치는 과정이 필요해서 별도 안내 문구 표시
            status_label.config(text="고화질 병합 및 저장 중... 잠시만 기다려주세요.")

    # 4. FFmpeg 위치 확인: 프로그램 옆에 있는 ffmpeg.exe 경로 확보
    ffmpeg_dir = get_ffmpeg_path()

    # 5. 엔진(yt-dlp) 설정값 정의 (리모컨 설정과 비슷함)
    ydl_opts = {
        # 선택한 화질 이하 중 최고 품질의 영상(mp4)과 소리(m4a)를 합치라는 특수 명령어
        'format': f'bestvideo[height<={res_limit}][ext=mp4]+bestaudio[ext=m4a]/best[height<={res_limit}][ext=mp4]/best',
        'noplaylist': True,               # 플레이리스트 주소여도 딱 이 영상 한 개만 받음
        'progress_hooks': [progress_hook], # 위에서 만든 진행률 표시 함수 연결
        # 저장될 파일 이름 형식: 선택한 폴더에 "영상제목.mp4"로 저장
        'outtmpl': os.path.join(save_path, '%(title)s.%(ext)s'),
        'ffmpeg_location': ffmpeg_dir,    # 합치기 작업을 수행할 엔진(ffmpeg) 위치 지정
    }

    # [실제 작업 수행부] 윈도우가 굳지 않게 백그라운드(별도 쓰레드)에서 실행
    def run_dl():
        try:
            btn.config(state="disabled")  # 작업 중에는 버튼을 못 누르게 잠금
            with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                ydl.download([url])       # 실제 유튜브 서버에서 데이터 가져오기 시작
            messagebox.showinfo("완료", f"{selected_res} 영상 다운로드가 완료되었습니다!")
            status_label.config(text="대기 중")
            progress_var.set(0)           # 작업이 끝나면 진행바 초기화
        except Exception as e:
            # 에러 발생 시 사용자에게 팝업창으로 에러 내용 알림
            messagebox.showerror("에러", f"오류 발생: {e}")
        finally:
            btn.config(state="normal")    # 성공하든 실패하든 버튼 잠금 해제

    # 조수(Thread)에게 일을 시키고 시작함
    threading.Thread(target=run_dl, daemon=True).start()

# --- 여기서부터는 화면(GUI)을 디자인하는 부분 ---
root = tk.Tk()                            # 메인 윈도우 창을 하나 만듦
root.title("유튜브 MP4 완벽 다운로더 v1.6")     # 프로그램 상단 제목
root.geometry("450x320")                  # 창의 기본 크기 설정 (가로x세로)

# 1. 주소 입력 안내 및 입력칸
tk.Label(root, text="유튜브 주소:", font=("맑은 고딕", 10)).pack(pady=5)
entry = tk.Entry(root, width=50)          # 텍스트를 입력받는 한 줄 입력칸
entry.pack(pady=5)

# 2. 화질 선택 안내 및 드롭다운 메뉴
tk.Label(root, text="원하는 화질을 선택하세요:", font=("맑은 고딕", 10)).pack(pady=10)
res_options = ["2160p (4K)", "1440p (QHD)", "1080p (Full HD)", "720p (HD)", "480p", "360p"]
res_combo = ttk.Combobox(root, values=res_options, state="readonly", width=20) # 읽기 전용 메뉴
res_combo.current(2)                      # 기본값으로 1080p 선택
res_combo.pack()

# 3. 진행 상태 바 (게이지가 차오르는 바)
progress_var = tk.DoubleVar()             # 게이지 수치를 저장하는 변수
progress_bar = ttk.Progressbar(root, variable=progress_var, maximum=100, length=350)
progress_bar.pack(pady=20)

# 4. 현재 상태를 글자로 알려주는 레이블
status_label = tk.Label(root, text="대기 중", font=("맑은 고딕", 9))
status_label.pack()

# 5. 실행 버튼 (색상과 폰트로 강조)
btn = tk.Button(root, text="선택한 화질로 다운로드", command=download_video, 
               bg="#0078D7", fg="white", font=("맑은 고딕", 10, "bold"), width=25)
btn.pack(pady=15)

root.mainloop()

 

 

ffmpeg.exe , ffprobe.exe 파일이 같은경로에 있어야 한다.

 

 

테스트 실행및 최종 exe 파일생성 과정은 파이썬 오디오 추출(mp3) 글 참조

https://huningyo.tistory.com/381

 

[윈도우] 파이썬을 활용한 유튜브 오디오 추출 프로그램 개발기

적당한 경로에 파일 생성.​downloader.py import yt_dlp # 유튜브 영상을 분석/다운로드하는 엔진import tkinter as tk # 윈도우 창을 만드는 기본 도구from tkinter import messagebox, filedialog, ttk # 메시지창, 폴더선

huningyo.tistory.com

 

 

파이썬 실행방법 cmd

python yt_mp4.py

윈도우 실행파일 만들기

pyinstaller --onefile --noconsole yt_mp4.py

exe파일

https://drive.google.com/file/d/1aVNL9atTY4LrZqNjNhOf2aqVvSuxBPG8/view?usp=sharing

728x90