抓YT音樂影片且轉成mp3 (Python)
import tkinter as tk
from tkinter import messagebox, filedialog
from pytubefix import YouTube
from pytubefix.cli import on_progress # pytubefix 提供的進度回調函數
import ssl
import os
import threading
# 解決 pytubefix 在某些環境下可能遇到的 SSL 憑證問題
ssl._create_default_https_context = ssl._create_stdlib_context
class YouTubeDownloaderApp:
def __init__(self, master):
self.master = master
master.title("YouTube MP3 下載器 (pytubefix)")
master.geometry("500x200")
master.resizable(False, False)
# 網址輸入框
self.url_label = tk.Label(master, text="YouTube 影片網址:")
self.url_label.pack(pady=(20, 5))
self.url_entry = tk.Entry(master, width=60)
self.url_entry.pack(pady=5)
# 預設一個範例網址
self.url_entry.insert(0, 'https://www.youtube.com/watch?v=R93ce4FZGbc') # 您可以替換為任何 YouTube 網址
# 下載按鈕
self.download_button = tk.Button(master, text="下載 MP3", command=self.start_download_thread)
self.download_button.pack(pady=10)
# 狀態訊息標籤
self.status_label = tk.Label(master, text="等待輸入網址...", fg="blue")
self.status_label.pack(pady=5)
def download_mp3(self, url):
"""實際執行 MP3 下載的函數"""
try:
self.status_label.config(text="正在處理網址...", fg="orange")
# 建立 YouTube 物件並設定進度回調函數
# 我們使用一個 lambda 函數來包裹 on_progress,以便在 Tkinter 中更新狀態
yt = YouTube(url, on_progress_callback=lambda stream, chunk, bytes_remaining: self.update_progress(stream, chunk, bytes_remaining))
self.status_label.config(text=f"找到影片: {yt.title},開始下載...", fg="orange")
# 選擇純音頻流(因為您提到了 MP3 音樂)
audio_stream = yt.streams.filter(only_audio=True).first()
if not audio_stream:
raise Exception("找不到可下載的音頻流。")
# 彈出視窗讓使用者選擇儲存路徑和檔案名稱
file_path = filedialog.asksaveasfilename(
defaultextension=".mp3",
initialfile=f"{yt.title}.mp3",
title="選擇儲存 MP3 的位置",
filetypes=[("MP3 files", "*.mp3")]
)
if not file_path:
self.status_label.config(text="下載已取消。", fg="red")
return
self.status_label.config(text="下載中,請稍候...", fg="blue")
# 下載音頻
audio_stream.download(output_path=os.path.dirname(file_path), filename=os.path.basename(file_path))
self.status_label.config(text=f"下載完成!", fg="green")
messagebox.showinfo("下載完成", f"'{yt.title}' 已成功下載!")
except Exception as e:
self.status_label.config(text=f"下載失敗: {e}", fg="red")
messagebox.showerror("下載錯誤", f"下載影片時發生錯誤: {e}")
finally:
self.download_button.config(state=tk.NORMAL) # 重新啟用按鈕
def update_progress(self, stream, chunk, bytes_remaining):
"""自定義的進度回調函數,用於更新 Tkinter 狀態標籤"""
total_size = stream.filesize
bytes_downloaded = total_size - bytes_remaining
percentage = (bytes_downloaded / total_size) * 100
self.status_label.config(text=f"下載中: {percentage:.2f}%...", fg="blue")
self.master.update_idletasks() # 強制更新 GUI 以顯示最新進度
def start_download_thread(self):
"""在單獨的執行緒中啟動下載,避免 GUI 凍結"""
url = self.url_entry.get()
if not url:
messagebox.showwarning("警告", "請輸入 YouTube 影片網址!")
return
self.download_button.config(state=tk.DISABLED) # 禁用按鈕防止重複點擊
self.status_label.config(text="準備下載...", fg="blue")
# 創建並啟動新執行緒
download_thread = threading.Thread(target=self.download_mp3, args=(url,))
download_thread.start()
# 啟動應用程式
if __name__ == "__main__":
root = tk.Tk()
app = YouTubeDownloaderApp(root)
root.mainloop()
//=====================================================
import tkinter as tk
from tkinter import ttk, messagebox, filedialog
from pytubefix import YouTube
import ssl
import os
import threading
# 解決 pytubefix 在某些環境下可能遇到的 SSL 憑證問題
ssl._create_default_https_context = ssl._create_stdlib_context
class YouTubeDownloaderApp:
def __init__(self, master):
self.master = master
master.title("YouTube MP3 下載器 (pytubefix)")
master.geometry("500x250")
master.resizable(False, False)
# 網址輸入框
self.url_label = tk.Label(master, text="YouTube 影片網址:")
self.url_label.pack(pady=(20, 5))
self.url_entry = tk.Entry(master, width=60)
self.url_entry.pack(pady=5)
# 預設一個範例網址
self.url_entry.insert(0, 'https://www.youtube.com/watch?v=R93ce4FZGbc')
# 下載按鈕
self.download_button = tk.Button(master, text="下載 MP3", command=self.start_download_thread)
self.download_button.pack(pady=10)
# 狀態訊息標籤
self.status_label = tk.Label(master, text="等待輸入網址...", fg="blue")
self.status_label.pack(pady=5)
# 進度條
self.progress_bar = ttk.Progressbar(
master,
orient="horizontal",
length=400,
mode="determinate"
)
self.progress_bar.pack(pady=10)
self.progress_bar['value'] = 0
def download_mp3(self, url):
"""實際執行 MP3 下載的函數"""
try:
self.status_label.config(text="正在處理網址...", fg="orange")
self.progress_bar['value'] = 0
# 建立 YouTube 物件並設定進度回調函數
yt = YouTube(url, on_progress_callback=self.update_progress)
self.status_label.config(text=f"找到影片: {yt.title},開始下載...", fg="orange")
# 選擇純音頻流
audio_stream = yt.streams.filter(only_audio=True).first()
if not audio_stream:
raise Exception("找不到可下載的音頻流。")
# 彈出視窗讓使用者選擇儲存路徑和檔案名稱
file_path = filedialog.asksaveasfilename(
defaultextension=".mp3",
initialfile=f"{yt.title}.mp3",
title="選擇儲存 MP3 的位置",
filetypes=[("MP3 files", "*.mp3")]
)
if not file_path:
self.status_label.config(text="下載已取消。", fg="red")
self.progress_bar['value'] = 0
return
self.status_label.config(text="下載中,請稍候...", fg="blue")
# 下載音頻
audio_stream.download(output_path=os.path.dirname(file_path), filename=os.path.basename(file_path))
self.status_label.config(text=f"下載完成!", fg="green")
self.progress_bar['value'] = 100
messagebox.showinfo("下載完成", f"'{yt.title}' 已成功下載!")
except Exception as e:
self.status_label.config(text=f"下載失敗: {e}", fg="red")
self.progress_bar['value'] = 0
messagebox.showerror("下載錯誤", f"下載影片時發生錯誤: {e}")
finally:
self.download_button.config(state=tk.NORMAL) # 重新啟用按鈕
def update_progress(self, stream, chunk, bytes_remaining):
"""用於更新 Tkinter 狀態標籤和進度條"""
total_size = stream.filesize
bytes_downloaded = total_size - bytes_remaining
percentage = (bytes_downloaded / total_size) * 100
# 更新進度條
self.progress_bar['value'] = percentage
# 更新狀態標籤
self.status_label.config(text=f"下載中: {percentage:.2f}%...")
self.master.update_idletasks() # 強制更新 GUI 以顯示最新進度
def start_download_thread(self):
"""在單獨的執行緒中啟動下載,避免 GUI 凍結"""
url = self.url_entry.get()
if not url:
messagebox.showwarning("警告", "請輸入 YouTube 影片網址!")
return
self.download_button.config(state=tk.DISABLED) # 禁用按鈕防止重複點擊
self.status_label.config(text="準備下載...", fg="blue")
# 創建並啟動新執行緒
download_thread = threading.Thread(target=self.download_mp3, args=(url,))
download_thread.start()
# 啟動應用程式
if __name__ == "__main__":
root = tk.Tk()
app = YouTubeDownloaderApp(root)
root.mainloop()
沒有留言:
張貼留言