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>&nbsp;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>&nbsp;&nbsp;&nbsp;
            <a href="https://pub-c1de1cb456e74d6bbbee111ba9e6c757.r2.dev/iphone.png" target="_blank">iPhone xfers</a>&nbsp;&nbsp;&nbsp;
            <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>&nbsp;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>&nbsp;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>&nbsp;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>&nbsp;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)