File size: 4,435 Bytes
2c19cb5
105e5dd
147c80a
105e5dd
dd81a22
147c80a
105e5dd
147c80a
105e5dd
 
147c80a
105e5dd
 
ccea871
147c80a
105e5dd
147c80a
105e5dd
 
 
 
147c80a
105e5dd
 
 
 
147c80a
105e5dd
ccea871
 
 
 
 
105e5dd
 
 
147c80a
 
 
 
c79f358
147c80a
419ec35
105e5dd
419ec35
105e5dd
dd81a22
147c80a
 
 
 
 
 
ccea871
105e5dd
dd81a22
cab48b5
dd81a22
147c80a
105e5dd
 
 
 
 
7ce4a76
ccea871
cab48b5
6bc8fde
 
 
7ce4a76
 
 
 
 
 
182b08d
7ce4a76
cab48b5
e7c74c6
105e5dd
7ce4a76
 
4383f3c
6bc8fde
0809817
419ec35
182b08d
 
ccea871
182b08d
7ce4a76
ccea871
105e5dd
7ce4a76
 
ccea871
6bc8fde
 
 
 
 
7ce4a76
6bc8fde
 
ccea871
105e5dd
2c19cb5
cab48b5
c25ac20
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
import os
import yt_dlp
import gradio as gr
import re
import subprocess
from pydub import AudioSegment

os.makedirs("downloads", exist_ok=True)

def sanitize_filename(filename):
    """Sanitize filenames by replacing special characters."""
    return re.sub(r'[^a-zA-Z0-9_-]', '_', filename)

def process_youtube_or_audio(url, uploaded_audio, start_time, end_time):
    """Downloads or processes audio, trims it, and exports ringtones."""
    try:
        filename, song_name = None, None

        if url:
            ydl_opts = {
                'format': 'bestaudio/best',
                'outtmpl': 'downloads/%(title)s.%(ext)s',
                'cookiefile': 'cookies.txt'
            }
            with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                info = ydl.extract_info(url, download=True)
                filename = ydl.prepare_filename(info)
                song_name = sanitize_filename(info['title'])
        
        elif uploaded_audio is not None:
            filename = uploaded_audio
            song_name = sanitize_filename(os.path.splitext(os.path.basename(uploaded_audio))[0])
        
        if not filename or not os.path.exists(filename):
            return None, None

        audio = AudioSegment.from_file(filename)
        start_ms, end_ms = int(start_time * 1000), int(end_time * 1000)
        start_ms = max(0, min(start_ms, len(audio)))
        end_ms = max(start_ms, min(end_ms, len(audio)))

        trimmed_audio = audio[start_ms:end_ms]

        mp3_filename = f"downloads/{song_name}.mp3"
        trimmed_audio.export(mp3_filename, format="mp3")

        m4a_filename = f"downloads/{song_name}.m4a"
        result = subprocess.run([
            'ffmpeg', '-y', '-i', mp3_filename, '-vn', '-acodec', 'aac', '-b:a', '192k', m4a_filename
        ], capture_output=True, text=True)

        if result.returncode != 0 or not os.path.exists(m4a_filename):
            print("FFmpeg Error:", result.stderr)
            return mp3_filename, None

        m4r_filename = f"downloads/{song_name}.m4r"
        os.rename(m4a_filename, m4r_filename)

        return mp3_filename, m4r_filename

    except Exception as e:
        print(f"Error: {e}")
        return None, None

# Gradio Interface
with gr.Blocks() as interface:
    gr.HTML("""
        <h1 style="font-size: 2rem; text-align: center;"><i class="fas fa-music"></i>&nbsp;PYTR - Python YouTube Ringtones</h1>
        <p style="text-align: center;">Enter a YouTube URL or upload an audio file to create ringtones.</p>
        <p style="text-align: center;"><a href="https://ringtones.jessejesse.xyz">Ringtones</a> | <a href="https://github.com/sudo-self/pytr">GitHub</a></p>

        <style>
            #youtube-url, #uploaded-audio { width: 45%; }
            #process-button { width: 100%; margin-top: 10px; background-color: #6a4cfc; color: white; border: none; border-radius: 5px; }
            #mp3-download, #iphone-ringtone { width: 45%; }
            #instructions { width: 100%; margin-top: 20px; }
            #start-time-slider, #end-time-slider { width: 45%; }
        </style>
    """)

    with gr.Row():
        youtube_url = gr.Textbox(placeholder="Enter the URL here...", label="YouTube URL", elem_id="youtube-url")
        uploaded_audio = gr.File(label="Upload Audio File", type="filepath", elem_id="uploaded-audio")

    gr.HTML("<h3 style='text-align: center;'>Trim Audio</h3>")

    with gr.Row():
        start_time = gr.Slider(0, 20, value=0, label="Start Time (seconds)", elem_id="start-time-slider")
        end_time = gr.Slider(1, 20, value=20, label="End Time (seconds)", elem_id="end-time-slider")
    
    # Add a class for custom button color
    process_button = gr.Button("Create Ringtones", elem_id="process-button")
    
    with gr.Row():
        mp3_download = gr.File(label="Android Ringtone", elem_id="mp3-download")
        iphone_ringtone = gr.File(label="iPhone Ringtone", elem_id="iphone-ringtone")
    
    with gr.Row():
        instructions = gr.Textbox(
            value="Android: move the download to the 'Ringtones' folder.\nApple: import download with 'Garage Band' and export to ringtones.",
            label="Install Ringtones",
            interactive=False,
            elem_id="instructions"
        )

    process_button.click(process_youtube_or_audio, inputs=[youtube_url, uploaded_audio, start_time, end_time], outputs=[mp3_download, iphone_ringtone])

interface.launch(share=True)