sudo-soldier commited on
Commit
1c67333
·
verified ·
1 Parent(s): 05939d0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +86 -50
app.py CHANGED
@@ -1,96 +1,132 @@
1
  import os
2
- import yt_dlp
3
  import gradio as gr
4
- import re
5
  from pydub import AudioSegment
 
 
6
 
7
 
8
- os.makedirs("downloads", exist_ok=True)
 
9
 
10
  def sanitize_filename(filename):
11
- """Sanitize filenames by replacing special characters."""
12
  return re.sub(r'[^a-zA-Z0-9_-]', '_', filename)
13
 
14
- def process_youtube_or_audio(url, uploaded_audio, start_time, end_time):
15
- """Downloads or processes audio, trims it, and exports ringtones."""
16
  try:
17
- filename, song_name = None, None
 
18
 
 
19
  if url:
20
  ydl_opts = {
21
- 'format': 'm4a/bestaudio',
22
- 'outtmpl': 'downloads/%(title)s.%(ext)s',
23
- 'cookiefile': 'cookies.txt' #yt
24
  }
25
  with yt_dlp.YoutubeDL(ydl_opts) as ydl:
26
  info = ydl.extract_info(url, download=True)
27
- filename = ydl.prepare_filename(info)
28
  song_name = sanitize_filename(info['title'])
29
 
30
-
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
- else:
36
- filename = None
37
-
38
- elif uploaded_audio is not None:
39
- filename = uploaded_audio
40
- song_name = sanitize_filename(os.path.splitext(os.path.basename(uploaded_audio))[0])
41
-
42
-
43
  if not filename or not os.path.exists(filename):
44
- print(f"File not found: {filename}")
45
  return None, None
46
 
47
-
48
  audio = AudioSegment.from_file(filename)
49
- start_ms, end_ms = int(start_time * 1000), int(end_time * 1000)
50
- start_ms = max(0, min(start_ms, len(audio)))
51
- end_ms = max(start_ms, min(end_ms, len(audio)))
52
-
53
- trimmed_audio = audio[start_ms:end_ms]
54
 
55
 
 
 
 
 
 
 
 
 
 
 
 
56
  mp3_filename = f"downloads/{song_name}.mp3"
57
  trimmed_audio.export(mp3_filename, format="mp3")
58
 
59
-
 
 
 
 
 
60
  m4r_filename = f"downloads/{song_name}.m4r"
61
- trimmed_audio.export(m4r_filename, format="m4r")
62
 
63
- return mp3_filename, m4r_filename
64
 
65
  except Exception as e:
66
  print(f"Error: {e}")
67
  return None, None
68
 
69
- # Gradio UI
70
- with gr.Blocks() as interface:
71
- gr.Markdown("""
72
- # 🎵 PYTR - Python YouTube Ringtones
73
- Create custom ringtones from YouTube or uploaded audio.
74
- - **Enter a YouTube URL** to extract audio.
75
- - **Upload a file** to trim an existing audio.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  """)
77
 
78
  with gr.Row():
79
- youtube_url = gr.Textbox(placeholder="Enter YouTube URL...", label="YouTube URL")
80
- uploaded_audio = gr.File(label="Upload Audio File", type="filepath")
 
 
 
 
 
81
 
82
- gr.Markdown("## Trim Audio")
83
  with gr.Row():
84
- start_time = gr.Slider(0, 30, value=0, label="Start Time (seconds)")
85
- end_time = gr.Slider(1, 30, value=10, label="End Time (seconds)")
86
 
87
- process_button = gr.Button("Create Ringtones")
 
 
88
 
89
  with gr.Row():
90
- mp3_download = gr.File(label="Android Ringtone (MP3)")
91
- iphone_ringtone = gr.File(label="iPhone Ringtone (M4R)")
 
 
 
 
 
 
 
 
 
 
92
 
93
- process_button.click(process_youtube_or_audio, inputs=[youtube_url, uploaded_audio, start_time, end_time], outputs=[mp3_download, iphone_ringtone])
94
 
95
  interface.launch(share=True)
96
 
 
1
  import os
 
2
  import gradio as gr
3
+ import yt_dlp
4
  from pydub import AudioSegment
5
+ import re
6
+ import subprocess
7
 
8
 
9
+ if not os.path.exists("downloads"):
10
+ os.makedirs("downloads")
11
 
12
  def sanitize_filename(filename):
13
+ """Sanitize filenames to avoid special characters."""
14
  return re.sub(r'[^a-zA-Z0-9_-]', '_', filename)
15
 
16
+ def process_youtube_or_audio(url, recorded_audio, start_time, end_time):
 
17
  try:
18
+ filename = None
19
+ song_name = None
20
 
21
+
22
  if url:
23
  ydl_opts = {
24
+ 'format': 'bestaudio/best',
25
+ 'outtmpl': 'downloads/%(id)s.%(ext)s',
26
+ 'cookiefile': 'cookies.txt'
27
  }
28
  with yt_dlp.YoutubeDL(ydl_opts) as ydl:
29
  info = ydl.extract_info(url, download=True)
30
+ filename = os.path.join('downloads', f"{info['id']}.webm")
31
  song_name = sanitize_filename(info['title'])
32
 
33
+
34
+ elif recorded_audio:
35
+ filename = recorded_audio
36
+ song_name = "recorded_audio"
37
+
 
 
 
 
 
 
 
 
38
  if not filename or not os.path.exists(filename):
 
39
  return None, None
40
 
41
+
42
  audio = AudioSegment.from_file(filename)
 
 
 
 
 
43
 
44
 
45
+ start_time_ms = start_time * 1000
46
+ end_time_ms = end_time * 1000
47
+
48
+
49
+ start_time_ms = max(0, min(start_time_ms, len(audio)))
50
+ end_time_ms = max(start_time_ms, min(end_time_ms, len(audio)))
51
+
52
+
53
+ trimmed_audio = audio[start_time_ms:end_time_ms]
54
+
55
+
56
  mp3_filename = f"downloads/{song_name}.mp3"
57
  trimmed_audio.export(mp3_filename, format="mp3")
58
 
59
+
60
+ m4a_filename = f"downloads/{song_name}.m4a"
61
+ subprocess.run([
62
+ 'ffmpeg', '-i', mp3_filename, '-vn', '-acodec', 'aac', '-b:a', '192k', m4a_filename
63
+ ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
64
+
65
  m4r_filename = f"downloads/{song_name}.m4r"
66
+ os.rename(m4a_filename, m4r_filename)
67
 
68
+ return os.path.abspath(mp3_filename), os.path.abspath(m4r_filename)
69
 
70
  except Exception as e:
71
  print(f"Error: {e}")
72
  return None, None
73
 
74
+
75
+ with gr.Blocks(css="""
76
+ body { font-family: Arial, sans-serif; text-align: center; }
77
+ .light-btn {
78
+ background-color: #ADD8E6;
79
+ color: #333;
80
+ border: 2px solid #ccc;
81
+ padding: 10px 20px;
82
+ font-size: 16px;
83
+ cursor: pointer;
84
+ }
85
+ .light-btn:hover { background-color: #87CEFA; }
86
+ """) as interface:
87
+
88
+ gr.HTML("""
89
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
90
+ <h1><i class="fas fa-music"></i>&nbsp;PYTR</h1>
91
+ <p>Python YouTube Ringtones. Enter a YouTube URL or record audio to create ringtones.</p>
92
+ <p>
93
+ <a href="https://ringtones.JesseJesse.xyz" target="_blank">slim UI</a>&nbsp;&nbsp;&nbsp;
94
+ <a href="https://pub-c1de1cb456e74d6bbbee111ba9e6c757.r2.dev/iphone.png" target="_blank">iPhone xfers</a>&nbsp;&nbsp;&nbsp;
95
+ <a href="https://youtube.com" target="_blank">YouTube</a>
96
+ </p>
97
  """)
98
 
99
  with gr.Row():
100
+ with gr.Column(scale=1, min_width=250):
101
+ gr.HTML('<label><i class="fas fa-link"></i>&nbsp;YouTube URL</label>')
102
+ youtube_url = gr.Textbox(placeholder="Enter the URL here...", show_label=False)
103
+
104
+ with gr.Column(scale=1, min_width=250):
105
+ gr.HTML('<label><i class="fas fa-microphone"></i>&nbsp;Record Audio</label>')
106
+ audio_record = gr.Audio(sources=["microphone"], type="filepath", show_label=False)
107
 
 
108
  with gr.Row():
109
+ gr.HTML("<h3>Trim Audio (Optional)</h3>")
 
110
 
111
+ with gr.Row():
112
+ start_time = gr.Slider(0, 20, value=0, label="Start Time (seconds)")
113
+ end_time = gr.Slider(1, 20, value=20, label="End Time (seconds)")
114
 
115
  with gr.Row():
116
+ process_button = gr.Button("Create Ringtones", elem_classes="light-btn")
117
+
118
+ with gr.Row():
119
+ with gr.Column(scale=1, min_width=250):
120
+ gr.HTML('<label>&nbsp;Android Ringtone</label>')
121
+ mp3_download = gr.File(label="Android")
122
+ android_instructions = gr.Textbox(label="Install", placeholder="Move the .mp3 file to the ringtones folder", lines=2)
123
+
124
+ with gr.Column(scale=1, min_width=250):
125
+ gr.HTML('<label>&nbsp;iPhone Ringtone</label>')
126
+ iphone_ringtone = gr.File(label="Apple")
127
+ iphone_instructions = gr.Textbox(label="Install", placeholder="Open GarageBand on your iPhone. Create a new project with Audio Recorder. Tap on the Tracks view (≡ icon in top-left). Tap the Loop icon (top-right corner). Select 'Files', then tap 'Browse items from the Files app'. Locate your .m4r file and tap it to import into GarageBand.", lines=4)
128
 
129
+ process_button.click(process_youtube_or_audio, inputs=[youtube_url, audio_record, start_time, end_time], outputs=[mp3_download, iphone_ringtone])
130
 
131
  interface.launch(share=True)
132