Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -2,9 +2,9 @@ import os
|
|
2 |
import yt_dlp
|
3 |
import gradio as gr
|
4 |
import re
|
5 |
-
import subprocess
|
6 |
from pydub import AudioSegment
|
7 |
|
|
|
8 |
os.makedirs("downloads", exist_ok=True)
|
9 |
|
10 |
def sanitize_filename(filename):
|
@@ -18,7 +18,7 @@ def process_youtube_or_audio(url, uploaded_audio, start_time, end_time):
|
|
18 |
|
19 |
if url:
|
20 |
ydl_opts = {
|
21 |
-
'format': 'bestaudio
|
22 |
'outtmpl': 'downloads/%(title)s.%(ext)s',
|
23 |
'cookiefile': 'cookies.txt'
|
24 |
}
|
@@ -26,14 +26,23 @@ def process_youtube_or_audio(url, uploaded_audio, start_time, end_time):
|
|
26 |
info = ydl.extract_info(url, download=True)
|
27 |
filename = ydl.prepare_filename(info)
|
28 |
song_name = sanitize_filename(info['title'])
|
29 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
elif uploaded_audio is not None:
|
31 |
filename = uploaded_audio
|
32 |
song_name = sanitize_filename(os.path.splitext(os.path.basename(uploaded_audio))[0])
|
33 |
-
|
|
|
34 |
if not filename or not os.path.exists(filename):
|
|
|
35 |
return None, None
|
36 |
|
|
|
37 |
audio = AudioSegment.from_file(filename)
|
38 |
start_ms, end_ms = int(start_time * 1000), int(end_time * 1000)
|
39 |
start_ms = max(0, min(start_ms, len(audio)))
|
@@ -41,18 +50,12 @@ def process_youtube_or_audio(url, uploaded_audio, start_time, end_time):
|
|
41 |
|
42 |
trimmed_audio = audio[start_ms:end_ms]
|
43 |
|
|
|
44 |
mp3_filename = f"downloads/{song_name}.mp3"
|
45 |
trimmed_audio.export(mp3_filename, format="mp3")
|
46 |
|
47 |
-
|
48 |
-
|
49 |
-
'ffmpeg', '-y', '-i', mp3_filename, '-vn', '-acodec', 'aac', '-b:a', '192k', m4a_filename
|
50 |
-
], capture_output=True, text=True)
|
51 |
-
|
52 |
-
if result.returncode != 0 or not os.path.exists(m4a_filename):
|
53 |
-
print("FFmpeg Error:", result.stderr)
|
54 |
-
return mp3_filename, None
|
55 |
-
|
56 |
m4r_filename = f"downloads/{song_name}.m4r"
|
57 |
os.rename(m4a_filename, m4r_filename)
|
58 |
|
@@ -68,39 +71,29 @@ with gr.Blocks() as interface:
|
|
68 |
<h1 style="font-size: 2rem; text-align: center;"><i class="fas fa-music"></i> PYTR - Python YouTube Ringtones</h1>
|
69 |
<p style="text-align: center;">Enter a YouTube URL or upload an audio file to create ringtones.</p>
|
70 |
<p style="text-align: center;"><a href="https://ringtones.jessejesse.xyz">Ringtones</a> | <a href="https://github.com/sudo-self/pytr">GitHub</a></p>
|
71 |
-
|
72 |
-
<style>
|
73 |
-
#youtube-url, #uploaded-audio { width: 45%; }
|
74 |
-
#process-button { width: 100%; margin-top: 10px; background-color: #6a4cfc; color: white; border: none; border-radius: 5px; }
|
75 |
-
#mp3-download, #iphone-ringtone { width: 45%; }
|
76 |
-
#instructions { width: 100%; margin-top: 20px; }
|
77 |
-
#start-time-slider, #end-time-slider { width: 45%; }
|
78 |
-
</style>
|
79 |
""")
|
80 |
|
81 |
with gr.Row():
|
82 |
-
youtube_url = gr.Textbox(placeholder="Enter the URL here...", label="YouTube URL"
|
83 |
-
uploaded_audio = gr.File(label="Upload Audio File", type="filepath"
|
84 |
|
85 |
gr.HTML("<h3 style='text-align: center;'>Trim Audio</h3>")
|
86 |
|
87 |
with gr.Row():
|
88 |
-
start_time = gr.Slider(0, 20, value=0, label="Start Time (seconds)"
|
89 |
-
end_time = gr.Slider(1, 20, value=20, label="End Time (seconds)"
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
with gr.Row():
|
95 |
-
mp3_download = gr.File(label="Android Ringtone"
|
96 |
-
iphone_ringtone = gr.File(label="iPhone Ringtone"
|
97 |
-
|
98 |
with gr.Row():
|
99 |
instructions = gr.Textbox(
|
100 |
value="Android: move the download to the 'Ringtones' folder.\nApple: import download with 'Garage Band' and export to ringtones.",
|
101 |
label="Install Ringtones",
|
102 |
-
interactive=False
|
103 |
-
elem_id="instructions"
|
104 |
)
|
105 |
|
106 |
process_button.click(process_youtube_or_audio, inputs=[youtube_url, uploaded_audio, start_time, end_time], outputs=[mp3_download, iphone_ringtone])
|
@@ -108,3 +101,4 @@ with gr.Blocks() as interface:
|
|
108 |
interface.launch(share=True)
|
109 |
|
110 |
|
|
|
|
2 |
import yt_dlp
|
3 |
import gradio as gr
|
4 |
import re
|
|
|
5 |
from pydub import AudioSegment
|
6 |
|
7 |
+
# Ensure downloads directory exists
|
8 |
os.makedirs("downloads", exist_ok=True)
|
9 |
|
10 |
def sanitize_filename(filename):
|
|
|
18 |
|
19 |
if url:
|
20 |
ydl_opts = {
|
21 |
+
'format': 'm4a/bestaudio',
|
22 |
'outtmpl': 'downloads/%(title)s.%(ext)s',
|
23 |
'cookiefile': 'cookies.txt'
|
24 |
}
|
|
|
26 |
info = ydl.extract_info(url, download=True)
|
27 |
filename = ydl.prepare_filename(info)
|
28 |
song_name = sanitize_filename(info['title'])
|
29 |
+
|
30 |
+
# Ensure correct extension
|
31 |
+
if not filename.endswith(".m4a"):
|
32 |
+
possible_file = f"downloads/{song_name}.m4a"
|
33 |
+
if os.path.exists(possible_file):
|
34 |
+
filename = possible_file
|
35 |
+
|
36 |
elif uploaded_audio is not None:
|
37 |
filename = uploaded_audio
|
38 |
song_name = sanitize_filename(os.path.splitext(os.path.basename(uploaded_audio))[0])
|
39 |
+
|
40 |
+
# Validate file existence
|
41 |
if not filename or not os.path.exists(filename):
|
42 |
+
print(f"File {filename} not found!")
|
43 |
return None, None
|
44 |
|
45 |
+
# Process audio
|
46 |
audio = AudioSegment.from_file(filename)
|
47 |
start_ms, end_ms = int(start_time * 1000), int(end_time * 1000)
|
48 |
start_ms = max(0, min(start_ms, len(audio)))
|
|
|
50 |
|
51 |
trimmed_audio = audio[start_ms:end_ms]
|
52 |
|
53 |
+
# Save MP3
|
54 |
mp3_filename = f"downloads/{song_name}.mp3"
|
55 |
trimmed_audio.export(mp3_filename, format="mp3")
|
56 |
|
57 |
+
# Rename M4A to M4R for iPhone
|
58 |
+
m4a_filename = filename
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
m4r_filename = f"downloads/{song_name}.m4r"
|
60 |
os.rename(m4a_filename, m4r_filename)
|
61 |
|
|
|
71 |
<h1 style="font-size: 2rem; text-align: center;"><i class="fas fa-music"></i> PYTR - Python YouTube Ringtones</h1>
|
72 |
<p style="text-align: center;">Enter a YouTube URL or upload an audio file to create ringtones.</p>
|
73 |
<p style="text-align: center;"><a href="https://ringtones.jessejesse.xyz">Ringtones</a> | <a href="https://github.com/sudo-self/pytr">GitHub</a></p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
""")
|
75 |
|
76 |
with gr.Row():
|
77 |
+
youtube_url = gr.Textbox(placeholder="Enter the URL here...", label="YouTube URL")
|
78 |
+
uploaded_audio = gr.File(label="Upload Audio File", type="filepath")
|
79 |
|
80 |
gr.HTML("<h3 style='text-align: center;'>Trim Audio</h3>")
|
81 |
|
82 |
with gr.Row():
|
83 |
+
start_time = gr.Slider(0, 20, value=0, label="Start Time (seconds)")
|
84 |
+
end_time = gr.Slider(1, 20, value=20, label="End Time (seconds)")
|
85 |
+
|
86 |
+
process_button = gr.Button("Create Ringtones")
|
87 |
+
|
|
|
88 |
with gr.Row():
|
89 |
+
mp3_download = gr.File(label="Android Ringtone")
|
90 |
+
iphone_ringtone = gr.File(label="iPhone Ringtone")
|
91 |
+
|
92 |
with gr.Row():
|
93 |
instructions = gr.Textbox(
|
94 |
value="Android: move the download to the 'Ringtones' folder.\nApple: import download with 'Garage Band' and export to ringtones.",
|
95 |
label="Install Ringtones",
|
96 |
+
interactive=False
|
|
|
97 |
)
|
98 |
|
99 |
process_button.click(process_youtube_or_audio, inputs=[youtube_url, uploaded_audio, start_time, end_time], outputs=[mp3_download, iphone_ringtone])
|
|
|
101 |
interface.launch(share=True)
|
102 |
|
103 |
|
104 |
+
|