Spaces:
Running
Running
File size: 5,805 Bytes
2c19cb5 147c80a 1c67333 147c80a 1c67333 105e5dd c846fe2 105e5dd 1c67333 105e5dd 581993c 105e5dd 1c67333 105e5dd c846fe2 410f6c0 c846fe2 105e5dd c846fe2 105e5dd 1c67333 c846fe2 105e5dd c846fe2 105e5dd a6f5db7 c846fe2 581993c 410f6c0 c846fe2 581993c 2505d33 c846fe2 105e5dd c846fe2 105e5dd c846fe2 147c80a c846fe2 1c67333 c846fe2 419ec35 105e5dd c846fe2 6542b78 410f6c0 c846fe2 6542b78 c846fe2 6542b78 105e5dd c846fe2 105e5dd 1c67333 c846fe2 |
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 |
import os
import gradio as gr
import yt_dlp
from pydub import AudioSegment
import re
import subprocess
# Ensure static directory exists for storing audio files
DOWNLOAD_DIR = "static"
os.makedirs(DOWNLOAD_DIR, exist_ok=True)
def sanitize_filename(filename):
"""Sanitize filenames to avoid special characters."""
return re.sub(r'[^a-zA-Z0-9_-]', '_', filename)
def process_youtube_or_audio(url, uploaded_audio, start_time, end_time):
try:
filename = None
song_name = None
print(f"Processing URL: {url}")
print(f"Uploaded audio: {uploaded_audio}")
print(f"Start time: {start_time}, End time: {end_time}")
# Download from YouTube if URL is provided
if url:
print("Downloading from YouTube...")
ydl_opts = {
'format': 'bestaudio/best',
'outtmpl': f'{DOWNLOAD_DIR}/%(id)s.%(ext)s',
'cookiefile': 'cookies.txt',
'noplaylist': True,
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(url, download=True)
filename = os.path.join(DOWNLOAD_DIR, f"{info['id']}.webm")
song_name = sanitize_filename(info['title'])
# Use uploaded audio if available
elif uploaded_audio:
print("Processing uploaded audio...")
filename = uploaded_audio
song_name = "uploaded_audio"
# If no valid file exists, return an error
if not filename or not os.path.exists(filename):
print(f"Error: No valid file found at {filename}")
return None, None
# Load and trim audio
audio = AudioSegment.from_file(filename)
start_time_ms = max(0, min(start_time * 1000, len(audio)))
end_time_ms = max(start_time_ms, min(end_time * 1000, len(audio)))
trimmed_audio = audio[start_time_ms:end_time_ms]
# Export trimmed audio as MP3
mp3_filename = f"{DOWNLOAD_DIR}/{song_name}.mp3"
trimmed_audio.export(mp3_filename, format="mp3")
# Convert MP3 to M4R for iPhone
m4a_filename = f"{DOWNLOAD_DIR}/{song_name}.m4a"
try:
subprocess.run([
'ffmpeg', '-i', mp3_filename, '-vn', '-acodec', 'aac', '-b:a', '192k', m4a_filename
], stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=30, check=True)
except subprocess.TimeoutExpired:
print("Error: ffmpeg took too long to process the file.")
return None, None
except subprocess.CalledProcessError as e:
print(f"ffmpeg error: {e}")
return None, None
# Rename to M4R format for iPhone ringtones
m4r_filename = f"{DOWNLOAD_DIR}/{song_name}.m4r"
if os.path.exists(m4a_filename):
os.rename(m4a_filename, m4r_filename)
print(f"Files saved: {mp3_filename}, {m4r_filename}")
return mp3_filename, m4r_filename
else:
print("Error: M4A file not created.")
return None, None
except Exception as e:
print(f"Error: {e}")
return None, None
# === GRADIO UI ===
with gr.Blocks(css="""
body { font-family: Arial, sans-serif; text-align: center; }
.light-btn { background-color: #ADD8E6; color: #333; border: 2px solid #ccc; padding: 10px 20px; font-size: 16px; cursor: pointer; }
.light-btn:hover { background-color: #87CEFA; }
""") as interface:
gr.HTML("""
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<h1><i class="fas fa-music"></i> PYTR</h1>
<p>Python YouTube Ringtones. Enter a YouTube URL or upload audio to create ringtones.</p>
<p>
<a href="https://ringtones.JesseJesse.xyz" target="_blank">Ringtones</a>
<a href="https://pub-c1de1cb456e74d6bbbee111ba9e6c757.r2.dev/iphone.png" target="_blank">iPhone xfers</a>
<a href="https://youtube.com" target="_blank">YouTube</a>
</p>
""")
with gr.Row():
with gr.Column(scale=1, min_width=250):
gr.HTML('<label><i class="fas fa-link"></i> YouTube URL</label>')
youtube_url = gr.Textbox(placeholder="Enter the URL here...", show_label=False)
with gr.Column(scale=1, min_width=250):
gr.HTML('<label><i class="fas fa-upload"></i> Upload Audio</label>')
audio_upload = gr.File(label="Upload Audio", type="filepath", show_label=False)
with gr.Row():
gr.HTML("<h3>Trim Audio (Optional)</h3>")
with gr.Row():
start_time = gr.Slider(0, 20, value=0, label="Start Time (seconds)")
end_time = gr.Slider(1, 20, value=20, label="End Time (seconds)")
with gr.Row():
process_button = gr.Button("Create Ringtones", elem_classes="light-btn")
with gr.Row():
with gr.Column(scale=1, min_width=250):
gr.HTML('<label> Android Ringtone</label>')
mp3_download = gr.File(label="Android")
android_instructions = gr.Textbox(label="Install", placeholder="Move the .mp3 file to the ringtones folder", lines=2)
with gr.Column(scale=1, min_width=250):
gr.HTML('<label> iPhone Ringtone</label>')
iphone_ringtone = gr.File(label="Apple")
iphone_instructions = gr.Textbox(label="Install", placeholder="Open GarageBand on your iPhone. Import the .m4r file and set it as a ringtone.", lines=4)
process_button.click(process_youtube_or_audio, inputs=[youtube_url, audio_upload, start_time, end_time], outputs=[mp3_download, iphone_ringtone])
# Launch with queue for stability
interface.queue().launch(share=True, server_port=7860)
|