def fetch():
try:
result = subprocess.run(
, capture_output=True, text=True
)
if result.returncode != 0:
messagebox.showerror(“Error”, f”Failed to fetch formats:\n{result.stderr}”)
return
for line in result.stdout.splitlines():
parts = line.split()
if len(parts) > 3 and parts.isdigit():
format_id = parts
ext = parts
resolution = parts if len(parts) > 2 else “Unknown”
self.format_list.insert(“”, “end”, values=(format_id, ext, resolution))
self.download_button.config(state=tk.NORMAL)
except Exception as e:
messagebox.showerror(“Error”, f”An error occurred: {e}”)
def download_video(self):
selected_item = self.format_list.selection()
if not selected_item:
messagebox.showerror(“Error”, “Please select a format to download.”)
return
if not url:
messagebox.showerror(“Error”, “Please enter a valid video URL.”)
return
if not os.path.exists(save_path):
messagebox.showerror(“Error”, “The save path does not exist. Please select a valid directory.”)
return
self.download_button.config(state=tk.DISABLED)
def download():
try:
output_template = os.path.join(save_path, “%(title)s.%(ext)s”)
# Using yt-dlp with bestvideo+bestaudio to ensure video and audio are merged
result = subprocess.run(
,
capture_output=True,
text=True,
)
if result.returncode == 0:
messagebox.showinfo(“Success”, “Download complete with audio and video merged!”)
else:
messagebox.showerror(“Error”, f”Download failed:\n{result.stderr}”)
except Exception as e:
messagebox.showerror(“Error”, f”An error occurred: {e}”)
? 看看
付费内容也能下吗
码一个
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import subprocess
import threading
import os
def get_default_save_path():
return os.path.join(os.path.expanduser(“~”), “Desktop”) # 默认保存路径为桌面
class YouTubeDLApp:
def __init__(self, root):
self.root = root
self.root.title(“YouTube Video Downloader”)
# 视频 URL 输入
tk.Label(root, text=”Video URL:”).grid(row=0, column=0, padx=5, pady=5, sticky=”e”)
self.url_entry = tk.Entry(root, width=50)
self.url_entry.grid(row=0, column=1, padx=5, pady=5)
self.fetch_button = tk.Button(root, text=”Fetch Formats”, command=self.fetch_formats)
self.fetch_button.grid(row=0, column=2, padx=5, pady=5)
# 保存路径选择
tk.Label(root, text=”Save Path:”).grid(row=1, column=0, padx=5, pady=5, sticky=”e”)
self.save_path_entry = tk.Entry(root, width=50)
self.save_path_entry.grid(row=1, column=1, padx=5, pady=5)
self.save_path_entry.insert(0, get_default_save_path()) # 设置默认路径
self.browse_button = tk.Button(root, text=”Browse”, command=self.select_save_path)
self.browse_button.grid(row=1, column=2, padx=5, pady=5)
# 视频格式列表
tk.Label(root, text=”Available Formats:”).grid(row=2, column=0, padx=5, pady=5, sticky=”nw”)
self.format_list = ttk.Treeview(root, columns=(“ID”, “EXT”, “RESOLUTION”), show=”headings”, height=10)
self.format_list.grid(row=2, column=1, columnspan=2, padx=5, pady=5)
self.format_list.heading(“ID”, text=”ID”)
self.format_list.heading(“EXT”, text=”Extension”)
self.format_list.heading(“RESOLUTION”, text=”Resolution”)
self.format_list.column(“ID”, width=100)
self.format_list.column(“EXT”, width=100)
self.format_list.column(“RESOLUTION”, width=200)
# 下载按钮
self.download_button = tk.Button(root, text=”Download”, command=self.download_video, state=tk.DISABLED)
self.download_button.grid(row=3, column=1, padx=5, pady=5)
def fetch_formats(self):
url = self.url_entry.get().strip()
if not url:
messagebox.showerror(“Error”, “Please enter a valid video URL.”)
return
self.fetch_button.config(state=tk.DISABLED)
self.format_list.delete(*self.format_list.get_children())
def fetch():
try:
result = subprocess.run(
, capture_output=True, text=True
)
if result.returncode != 0:
messagebox.showerror(“Error”, f”Failed to fetch formats:\n{result.stderr}”)
return
for line in result.stdout.splitlines():
parts = line.split()
if len(parts) > 3 and parts.isdigit():
format_id = parts
ext = parts
resolution = parts if len(parts) > 2 else “Unknown”
self.format_list.insert(“”, “end”, values=(format_id, ext, resolution))
self.download_button.config(state=tk.NORMAL)
except Exception as e:
messagebox.showerror(“Error”, f”An error occurred: {e}”)
finally:
self.fetch_button.config(state=tk.NORMAL)
threading.Thread(target=fetch).start()
def select_save_path(self):
path = filedialog.askdirectory()
if path:
self.save_path_entry.delete(0, tk.END)
self.save_path_entry.insert(0, path)
def download_video(self):
selected_item = self.format_list.selection()
if not selected_item:
messagebox.showerror(“Error”, “Please select a format to download.”)
return
format_id = self.format_list.item(selected_item, “values”)
url = self.url_entry.get().strip()
save_path = self.save_path_entry.get().strip()
if not save_path:
messagebox.showerror(“Error”, “Please select a save path.”)
return
if not url:
messagebox.showerror(“Error”, “Please enter a valid video URL.”)
return
if not os.path.exists(save_path):
messagebox.showerror(“Error”, “The save path does not exist. Please select a valid directory.”)
return
self.download_button.config(state=tk.DISABLED)
def download():
try:
output_template = os.path.join(save_path, “%(title)s.%(ext)s”)
# Using yt-dlp with bestvideo+bestaudio to ensure video and audio are merged
result = subprocess.run(
,
capture_output=True,
text=True,
)
if result.returncode == 0:
messagebox.showinfo(“Success”, “Download complete with audio and video merged!”)
else:
messagebox.showerror(“Error”, f”Download failed:\n{result.stderr}”)
except Exception as e:
messagebox.showerror(“Error”, f”An error occurred: {e}”)
finally:
self.download_button.config(state=tk.NORMAL)
threading.Thread(target=download).start()
if __name__ == “__main__”:
root = tk.Tk()
app = YouTubeDLApp(root)
root.mainloop()
python3 自己cmd运行 需要FFmpeg
最开始我使用you-get 后来发现you-get 只能下载默认的视频 格式解析后无法下载 更换了yt-dlp 自己测试的 youtube和B站都能下载 其他的我没试
你要是下载付费视频我估计还需要加入账户密码才能下载 你不行就让ai给你加进去
OK我试试
我找的GitHub还要花钱的是这个https://github.com/PyJun/Mooc_Downloader
不清楚这个打包完的程序能不能被破解
这个
咸鱼有卖工具 一次性收费的
费这功夫不如直接买人下好的,大部分好点儿的课程都能找到
课程是课程 与普通视频不通用
github 找yutto 项目