ziqiangao commited on
Commit
25c18af
·
1 Parent(s): e0df6af

update app.py

Browse files
Files changed (1) hide show
  1. app.py +50 -44
app.py CHANGED
@@ -15,7 +15,6 @@ import subprocess
15
  import traceback
16
  import time
17
  import shutil
18
- import LRC
19
  import LRC2SRT
20
 
21
  path = "" # Update with your path
@@ -26,7 +25,6 @@ def safe_read(i: int, a: list):
26
  else:
27
  return a[i]
28
 
29
-
30
  def getRenderCords(ta: list, idx: int, res: int = 1024, size: tuple = (1280, 720)) -> list:
31
  i = idx - res // 2
32
  x, y = size[0] * .9 / -2, (ta[i] - 128) * (size[1] / 2000) + (size[1] * .7 / -2)
@@ -69,8 +67,6 @@ def getTitleAndArtist(mp3_file):
69
  audio = MP3(mp3_file, ID3=ID3)
70
  title = audio.get('TIT2', TIT2(encoding=3, text='')).text[0]
71
  artist = audio.get('TPE1', TPE1(encoding=3, text='')).text[0]
72
-
73
-
74
  return title, artist
75
 
76
  def getColour(img):
@@ -144,8 +140,7 @@ def render_frame(params):
144
  (linear_interpolate(width * .95 // -2, width * .95 // 2, s / len(samples_array)),
145
  height * .95 // -2)],width=width, height=height), fill='#fff', width=10 * height // 360)
146
 
147
-
148
- img.save(path+f'out/{name}/{str(n)}.png', 'PNG',)
149
 
150
  return 1 # Indicate one frame processed
151
 
@@ -169,7 +164,9 @@ def stripinvisibles(s):
169
  for i in invisible_chars:
170
  e.replace(i,"")
171
  return e
 
172
  haslyrics = False
 
173
  def main(file, name, fps=30, res: tuple=(1280,720), oscres=512, sr=11025, lyrics=None, img=None, tit=None, ast=None):
174
  p = gr.Progress()
175
  LRC2SRT.clear()
@@ -178,11 +175,10 @@ def main(file, name, fps=30, res: tuple=(1280,720), oscres=512, sr=11025, lyrics
178
  global haslyrics
179
  haslyrics = False
180
  if lyrics:
181
- p(0.5,"parsing lyrics")
182
  try:
183
- outf = open("out.srt",mode="x", encoding="UTF8")
184
  sf = stripinvisibles(open(lyrics, encoding="UTF8").read())
185
- print(sf[0])
186
  if sf[0] == '[':
187
  gr.Info("Lyrics of LRC type was detected, converting to SRT")
188
  LRC2SRT.convert_to_srt(sf)
@@ -198,30 +194,29 @@ def main(file, name, fps=30, res: tuple=(1280,720), oscres=512, sr=11025, lyrics
198
  print(traceback.format_exc())
199
  gr.Warning("Failed to parse lyrics, ensure there are no blank lines in between")
200
 
201
- os.makedirs(path+f'out/{name}/', exist_ok=True)
202
  global iii
203
  iii = 0
204
  # Load the audio file
205
- p(0.25,"loading file")
206
  audio_path = file
207
  y, sr = librosa.load(audio_path, sr=sr) # Resample to 11025 Hz
208
  y_u8 = (y * 128 + 128).astype('uint8')
209
  samples_array = y_u8.tolist()
210
- p(0.5,"extracting metadata")
211
  # Extract cover image, title, and artist
212
  cover_file = None
213
  if img:
214
  cover_file = Image.open(img)
215
  cover_img = extract_cover_image(audio_path)
216
- if cover_img == None:
217
  if img:
218
  cover_img = cover_file
219
  else:
220
  raise gr.Error("Mp3 must have a cover image, upload the image under the 'Metadata' section")
221
  elif cover_img == -1 and not (tit or ast):
222
  raise gr.Error("Mp3 is missing tags, add the info under the 'Metadata' section")
223
-
224
-
225
  title, artist = getTitleAndArtist(audio_path)
226
  if title == '' or artist == '':
227
  if not (tit or ast):
@@ -239,19 +234,17 @@ def main(file, name, fps=30, res: tuple=(1280,720), oscres=512, sr=11025, lyrics
239
 
240
  try:
241
  with Pool(cpu_count()) as pool:
242
-
243
  num_frames = len(samples_array) // (sr // fps)
244
  # Use imap to get progress updates
245
  for _ in pool.imap_unordered(render_frame, params):
246
  iii += 1 # Increment frame count for progress
247
- p((iii,num_frames),desc="Rendering Frames")
248
 
249
-
250
  except Exception as e:
251
  print('Ended in error: ' + traceback.format_exc(), iii)
252
- gr.e
253
  p = gr.Progress()
254
- p(0.5,desc="Compiling video")
255
  print('FFMPEG')
256
  if haslyrics:
257
  ffmpeg_cmd = [
@@ -272,56 +265,69 @@ def main(file, name, fps=30, res: tuple=(1280,720), oscres=512, sr=11025, lyrics
272
  ffmpeg_cmd = [
273
  "ffmpeg",
274
  '-framerate', '30',
275
- '-i', path+f'out/{name}/%d.png', # Input PNG images
276
- '-i', f'{file}', # Input MP3 audio
277
  '-c:v', 'libx264',
278
  '-r', '30',
279
  '-pix_fmt', 'yuv420p',
280
  '-c:a', 'aac',
281
  '-y',
282
- path+f'{name}.mp4' # Output MP4 filename
283
- ]
284
  subprocess.run(ffmpeg_cmd)
285
 
 
 
286
  def gradio_interface(audio_file, lyrics, output_name, fps=30, vidwidth=1280, vidheight=720, oscres=512, img=None, tit=None, ast=None):
287
  resolution = f"{vidwidth}x{vidheight}"
288
  res = tuple(map(int, resolution.split('x')))
289
- main(audio_file, output_name, fps=fps, res=res, oscres=oscres, lyrics=lyrics, img=img, tit=tit, ast=ast)
290
  time.sleep(5)
291
 
292
  shutil.rmtree("out")
293
- if haslyrics:
294
- w = "out.srt"
295
- else:
296
- w = None
297
- return f"{output_name}.mp4",
298
 
299
  with gr.Blocks() as inputs:
300
  gr.Markdown('Upload an MP3 file and configure parameters to create a visualization video.\nOptionally upload a word or line synced lyric file\nEnsure a blank line at the end to avoid conversion errors')
301
  with gr.Accordion(label="Audio Settings", open=True):
302
  gr.Markdown('#Load your mp3 and lyrics file here')
303
- gr.components.File(label="Upload your MP3 file", file_count='single', file_types=['mp3']),
304
- gr.components.File(label="(Optional) Upload Lyrics as LRC or SRT", file_count='single', file_types=['lrc','srt']),
305
 
306
  with gr.Accordion(label="Video Output Settings"):
307
  gr.Markdown('#Configure Video Output Here')
308
- gr.components.Textbox(label="Output Video Name", value='video'),
309
- gr.components.Slider(label="Frames per Second", minimum=20, maximum=60, step=1, value=30),
310
- gr.components.Slider(label="Output Video Width", minimum=100, maximum=2000, value=1280, step=2),
311
- gr.components.Slider(label="Output Video Height", minimum=100, maximum=2000, value=720, step=2)
312
- with gr.Accordion(label="Advanced Options"):
313
- gr.components.Slider(label="Number of Visualization Segments", minimum=256, maximum=2048, step=2, value=512),
314
- with gr.Accordion(label="Mp3 Metadata"):
 
 
315
  gr.Markdown('#Add Metadata here if your mp3 does not have one')
316
- gr.components.Image(label='Cover Art'),
317
- gr.components.Textbox(label='Title'),
318
- gr.components.Textbox(label='Artists')
 
 
 
 
 
 
 
 
 
319
 
320
  iface = gr.Interface(
321
  fn=gradio_interface,
322
  inputs=inputs,
323
- outputs=[gr.components.Video(label="Output"),gr.components.File(label="SRT Output")]
324
  )
325
 
326
  # Launch Gradio interface
327
- iface.launch()
 
15
  import traceback
16
  import time
17
  import shutil
 
18
  import LRC2SRT
19
 
20
  path = "" # Update with your path
 
25
  else:
26
  return a[i]
27
 
 
28
  def getRenderCords(ta: list, idx: int, res: int = 1024, size: tuple = (1280, 720)) -> list:
29
  i = idx - res // 2
30
  x, y = size[0] * .9 / -2, (ta[i] - 128) * (size[1] / 2000) + (size[1] * .7 / -2)
 
67
  audio = MP3(mp3_file, ID3=ID3)
68
  title = audio.get('TIT2', TIT2(encoding=3, text='')).text[0]
69
  artist = audio.get('TPE1', TPE1(encoding=3, text='')).text[0]
 
 
70
  return title, artist
71
 
72
  def getColour(img):
 
140
  (linear_interpolate(width * .95 // -2, width * .95 // 2, s / len(samples_array)),
141
  height * .95 // -2)],width=width, height=height), fill='#fff', width=10 * height // 360)
142
 
143
+ img.save(path+f'out/{name}/{str(n)}.png', 'PNG')
 
144
 
145
  return 1 # Indicate one frame processed
146
 
 
164
  for i in invisible_chars:
165
  e.replace(i,"")
166
  return e
167
+
168
  haslyrics = False
169
+
170
  def main(file, name, fps=30, res: tuple=(1280,720), oscres=512, sr=11025, lyrics=None, img=None, tit=None, ast=None):
171
  p = gr.Progress()
172
  LRC2SRT.clear()
 
175
  global haslyrics
176
  haslyrics = False
177
  if lyrics:
178
+ p(0.5, "parsing lyrics")
179
  try:
180
+ outf = open("out.srt", mode="x", encoding="UTF8")
181
  sf = stripinvisibles(open(lyrics, encoding="UTF8").read())
 
182
  if sf[0] == '[':
183
  gr.Info("Lyrics of LRC type was detected, converting to SRT")
184
  LRC2SRT.convert_to_srt(sf)
 
194
  print(traceback.format_exc())
195
  gr.Warning("Failed to parse lyrics, ensure there are no blank lines in between")
196
 
197
+ os.makedirs(path + f'out/{name}/', exist_ok=True)
198
  global iii
199
  iii = 0
200
  # Load the audio file
201
+ p(0.25, "loading file")
202
  audio_path = file
203
  y, sr = librosa.load(audio_path, sr=sr) # Resample to 11025 Hz
204
  y_u8 = (y * 128 + 128).astype('uint8')
205
  samples_array = y_u8.tolist()
206
+ p(0.5, "extracting metadata")
207
  # Extract cover image, title, and artist
208
  cover_file = None
209
  if img:
210
  cover_file = Image.open(img)
211
  cover_img = extract_cover_image(audio_path)
212
+ if cover_img is None:
213
  if img:
214
  cover_img = cover_file
215
  else:
216
  raise gr.Error("Mp3 must have a cover image, upload the image under the 'Metadata' section")
217
  elif cover_img == -1 and not (tit or ast):
218
  raise gr.Error("Mp3 is missing tags, add the info under the 'Metadata' section")
219
+
 
220
  title, artist = getTitleAndArtist(audio_path)
221
  if title == '' or artist == '':
222
  if not (tit or ast):
 
234
 
235
  try:
236
  with Pool(cpu_count()) as pool:
 
237
  num_frames = len(samples_array) // (sr // fps)
238
  # Use imap to get progress updates
239
  for _ in pool.imap_unordered(render_frame, params):
240
  iii += 1 # Increment frame count for progress
241
+ p((iii, num_frames), desc="Rendering Frames")
242
 
 
243
  except Exception as e:
244
  print('Ended in error: ' + traceback.format_exc(), iii)
245
+
246
  p = gr.Progress()
247
+ p(0.5, desc="Compiling video")
248
  print('FFMPEG')
249
  if haslyrics:
250
  ffmpeg_cmd = [
 
265
  ffmpeg_cmd = [
266
  "ffmpeg",
267
  '-framerate', '30',
268
+ '-i', path + f'out/{name}/%d.png', # Input PNG images
269
+ '-i', f'{file}', # Input MP3 audio
270
  '-c:v', 'libx264',
271
  '-r', '30',
272
  '-pix_fmt', 'yuv420p',
273
  '-c:a', 'aac',
274
  '-y',
275
+ path + f'{name}.mp4' # Output MP4 filename
276
+ ]
277
  subprocess.run(ffmpeg_cmd)
278
 
279
+ return f"{name}.mp4", haslyrics
280
+
281
  def gradio_interface(audio_file, lyrics, output_name, fps=30, vidwidth=1280, vidheight=720, oscres=512, img=None, tit=None, ast=None):
282
  resolution = f"{vidwidth}x{vidheight}"
283
  res = tuple(map(int, resolution.split('x')))
284
+ video_file, haslyrics = main(audio_file, output_name, fps=fps, res=res, oscres=oscres, lyrics=lyrics, img=img, tit=tit, ast=ast)
285
  time.sleep(5)
286
 
287
  shutil.rmtree("out")
288
+ srt_output = "out.srt" if haslyrics else None
289
+ return video_file, srt_output
290
+
291
+ def update_srt_output_visibility(haslyrics):
292
+ return gr.update(visible=haslyrics)
293
 
294
  with gr.Blocks() as inputs:
295
  gr.Markdown('Upload an MP3 file and configure parameters to create a visualization video.\nOptionally upload a word or line synced lyric file\nEnsure a blank line at the end to avoid conversion errors')
296
  with gr.Accordion(label="Audio Settings", open=True):
297
  gr.Markdown('#Load your mp3 and lyrics file here')
298
+ audio_file = gr.components.File(label="Upload your MP3 file", file_count='single', file_types=['mp3'])
299
+ lyrics_file = gr.components.File(label="(Optional) Upload Lyrics as LRC or SRT", file_count='single', file_types=['lrc', 'srt'])
300
 
301
  with gr.Accordion(label="Video Output Settings"):
302
  gr.Markdown('#Configure Video Output Here')
303
+ output_name = gr.components.Textbox(label="Output Video Name", value='video')
304
+ fps_slider = gr.components.Slider(label="Frames per Second", minimum=20, maximum=60, step=1, value=30)
305
+ vidwidth_slider = gr.components.Slider(label="Output Video Width", minimum=100, maximum=2000, value=1280, step=2)
306
+ vidheight_slider = gr.components.Slider(label="Output Video Height", minimum=100, maximum=2000, value=720, step=2)
307
+
308
+ with gr.Accordion(title="Advanced Options"):
309
+ oscres_slider = gr.components.Slider(label="Number of Visualization Segments", minimum=256, maximum=2048, step=2, value=512)
310
+
311
+ with gr.Accordion(title="Mp3 Metadata"):
312
  gr.Markdown('#Add Metadata here if your mp3 does not have one')
313
+ cover_img = gr.components.Image(label='Cover Art')
314
+ title_input = gr.components.Textbox(label='Title')
315
+ artist_input = gr.components.Textbox(label='Artists')
316
+
317
+ output_video = gr.components.Video(label="Output")
318
+ srt_output = gr.components.File(label="SRT Output", visible=False)
319
+
320
+ inputs.load(fn=gradio_interface,
321
+ inputs=[audio_file, lyrics_file, output_name, fps_slider, vidwidth_slider, vidheight_slider, oscres_slider, cover_img, title_input, artist_input],
322
+ outputs=[output_video, srt_output])
323
+
324
+ inputs.load(fn=update_srt_output_visibility, inputs=None, outputs=srt_output)
325
 
326
  iface = gr.Interface(
327
  fn=gradio_interface,
328
  inputs=inputs,
329
+ outputs=[output_video, srt_output]
330
  )
331
 
332
  # Launch Gradio interface
333
+ iface.launch()