-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path25 - Video to Audio Converter with Python.py
More file actions
148 lines (120 loc) · 3.82 KB
/
25 - Video to Audio Converter with Python.py
File metadata and controls
148 lines (120 loc) · 3.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import tkinter as tk
from tkinter import messagebox, filedialog
import subprocess
import os
import sys
import shutil
from pytube import YouTube
import pytube.extract
def find_ffmpeg():
base_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
bundled = os.path.join(
base_dir,
"ffmpeg-master-latest-win64-gpl",
"bin",
"ffmpeg.exe"
)
if os.path.isfile(bundled):
return bundled
if shutil.which("ffmpeg"):
return "ffmpeg"
return None
def download_audio():
url = url_entry.get().strip()
if not url:
messagebox.showerror("Error", "Enter a YouTube URL")
return
status_var.set("Extracting video ID...")
root.update()
try:
video_id = pytube.extract.video_id(url)
except Exception as e:
messagebox.showerror("Error", f"Invalid YouTube URL\n{e}")
return
ffmpeg = find_ffmpeg()
if not ffmpeg:
messagebox.showerror(
"Error",
"ffmpeg not found.\nInstall ffmpeg or place it in the bundled folder."
)
return
try:
status_var.set("Downloading audio with yt-dlp...")
root.update()
ytdlp_cmd = [
sys.executable, "-m", "yt_dlp",
"-x",
"--audio-format", "mp3",
"-o", f"{video_id}.%(ext)s",
url
]
subprocess.run(ytdlp_cmd, check=True)
# Find output file
downloaded_file = None
for f in os.listdir():
if f.startswith(video_id):
downloaded_file = os.path.abspath(f)
break
if not downloaded_file:
raise Exception("Download finished but file not found.")
if downloaded_file.lower().endswith(".mp3"):
status_var.set("Download completed successfully.")
messagebox.showinfo("Success", f"Saved MP3:\n{downloaded_file}")
return
except Exception:
try:
status_var.set("yt-dlp failed. Using pytube...")
root.update()
yt = YouTube(url)
stream = yt.streams.filter(only_audio=True).order_by("abr").desc().first()
if not stream:
raise Exception("No audio stream available.")
downloaded_file = stream.download(filename=video_id)
except Exception as e:
messagebox.showerror("Error", f"Download failed\n{e}")
return
status_var.set("Converting to MP3...")
root.update()
base, _ = os.path.splitext(downloaded_file)
mp3_path = base + ".mp3"
cmd = [
ffmpeg, "-y",
"-i", downloaded_file,
"-vn",
"-b:a", "192k",
"-ar", "44100",
mp3_path
]
try:
subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
os.remove(downloaded_file)
status_var.set("Conversion completed.")
messagebox.showinfo("Success", f"Saved MP3:\n{mp3_path}")
except subprocess.CalledProcessError as e:
messagebox.showerror(
"FFmpeg Error",
e.stderr.decode("utf-8", errors="ignore")
)
root = tk.Tk()
root.title("YouTube to MP3 Downloader")
root.geometry("520x220")
root.resizable(False, False)
tk.Label(root, text="YouTube URL", font=("Segoe UI", 11)).pack(pady=10)
url_entry = tk.Entry(root, width=65)
url_entry.pack(pady=5)
download_btn = tk.Button(
root,
text="Download MP3",
font=("Segoe UI", 11),
command=download_audio
)
download_btn.pack(pady=15)
status_var = tk.StringVar(value="Idle")
status_label = tk.Label(
root,
textvariable=status_var,
fg="blue",
font=("Segoe UI", 10)
)
status_label.pack(pady=5)
root.mainloop()