본문 바로가기

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

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

728x90

 

적당한 경로에 파일 생성.

downloader.py

 

import yt_dlp                          # 유튜브 영상을 분석/다운로드하는 엔진
import tkinter as tk                   # 윈도우 창을 만드는 기본 도구
from tkinter import messagebox, filedialog, ttk  # 메시지창, 폴더선택창, 세련된 위젯(진행바 등)
import os                              # 파일 경로(저장 위치)를 다루는 도구
import threading                       # 다운로드 중에도 창이 멈추지 않게 '멀티태스킹'을 해주는 도구

def download_mp3():
    """ [다운로드 시작] 버튼을 눌렀을 때 실행되는 메인 함수 """
    url = entry.get()                  # 입력창(Entry)에 적힌 주소를 가져옴
    if not url:                        # 주소가 비어있으면 경고창 띄우고 중단
        messagebox.showwarning("경고", "유튜브 URL을 입력하세요!")
        return

    # 파일을 어디에 저장할지 묻는 창을 띄우고 선택한 경로를 save_path에 저장
    save_path = filedialog.askdirectory()
    if not save_path:                  # 취소를 눌렀으면 중단
        return

    # 다운로드 상태가 변할 때마다 호출되는 보조 함수 (진행률 표시용)
    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="변환 중... 잠시만 기다려주세요.")

    # yt-dlp 엔진에 전달할 상세 설정 값들 (중요!)
    ydl_opts = {
        'format': 'bestaudio/best',             # 최고 음질의 오디오만 가져오기
        'noplaylist': True,                     # 리스트 주소여도 딱 1곡만 받기
        'progress_hooks': [progress_hook],      # 위에 만든 상태 업데이트 함수 연결
        'postprocessors': [{                    # 다운로드 후 수행할 작업
            'key': 'FFmpegExtractAudio',        # FFmpeg를 이용해 오디오 추출
            'preferredcodec': 'mp3',            # 결과물 포맷은 mp3
            'preferredquality': '192',          # 음질 설정
        }],
        # 저장 경로와 파일명 설정 (영상 제목.mp3)
        'outtmpl': os.path.join(save_path, '%(title)s.%(ext)s'),
    }

    # 실제 다운로드를 수행하는 부분 (멀티태스킹을 위해 별도로 분리)
    def run_dl():
        try:
            btn.config(state="disabled")        # 작업 중엔 버튼 클릭 막기
            with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                ydl.download([url])             # 실제 엔진 가동!
            messagebox.showinfo("완료", "MP3 다운로드가 완료되었습니다!")
            status_label.config(text="대기 중")
            progress_var.set(0)                 # 진행 바 초기화
        except Exception as e:
            messagebox.showerror("에러", f"오류 발생: {e}")
        finally:
            btn.config(state="normal")          # 작업 끝나면 버튼 다시 활성화

    # 다운로드 함수(run_dl)를 백그라운드에서 실행 (창이 굳는 것 방지)
    threading.Thread(target=run_dl, daemon=True).start()

# --- 여기서부터는 화면(GUI)을 그리는 부분 ---
root = tk.Tk()                         # 메인 윈도우 창 생성
root.title("유튜브 MP3 다운로더 v1.2")      # 창 제목
root.geometry("450x250")               # 창 크기 (가로x세로)

# 안내 문구 레이블
tk.Label(root, text="유튜브 주소:", font=("맑은 고딕", 10)).pack(pady=10)
# 주소 입력창
entry = tk.Entry(root, width=50)
entry.pack(pady=5)

# 진행 상태 바 (0~100 사이의 값을 가짐)
progress_var = tk.DoubleVar()
progress_bar = ttk.Progressbar(root, variable=progress_var, maximum=100, length=350)
progress_bar.pack(pady=10)

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

# 다운로드 시작 버튼
btn = tk.Button(root, text="다운로드 시작", command=download_mp3, 
               bg="#cc0000", fg="white", font=("맑은 고딕", 10, "bold"), width=20)
btn.pack(pady=15)

root.mainloop() # 사용자가 창을 닫을 때까지 프로그램 무한 실행(대기)

 

 

ffmpeg.exe , ffprobe.exe 파일 같은 폴더에 있어야함.

https://ffmpeg.org/ 에서 다운

 

 

파일 실행

cmd 로 경로 이동후 파일 실행

url입력할때 v값 까지만 list값 있는경우 다른거까지 계속 다운한다. https://www.youtube.com/watch?v=l_MyUGq7pgs


정상 실행 확인후 윈도우 실행파일 만들기

pyinstaller --onefile --noconsole 파일명

성공 메시지 나오면 dist 폴더 확인

exe 파일 확인

exe파일과 , ffmpeg.exe , ffprobe.exe 파일을 같은폴더에 둔뒤 사용

 

 

728x90