RO-Rtechs commited on
Commit
5aa1367
·
verified ·
1 Parent(s): 627a592

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +66 -75
app.py CHANGED
@@ -226,6 +226,16 @@ async def process_video(video_url, segments, combine, audio_only, progress=gr.Pr
226
  return
227
 
228
  output_dir = Path('output')
 
 
 
 
 
 
 
 
 
 
229
  output_dir.mkdir(exist_ok=True)
230
 
231
  try:
@@ -247,16 +257,18 @@ async def process_video(video_url, segments, combine, audio_only, progress=gr.Pr
247
  video_output = output_dir / f"{sanitize_title(video_title)}_video_segment_{i+1}.mp4"
248
  async for output in download_segment_async(video_url, start_time, end_time, str(video_output)):
249
  progress((i / total_segments) * 0.8 + (1 / total_segments) * 0.4, f"Downloading video segment {i+1}/{total_segments}: {output}")
250
- if not video_output.exists():
 
 
251
  raise FileNotFoundError(f"Video segment file not found: {video_output}")
252
- video_segments.append(str(video_output))
253
 
254
  audio_output = output_dir / f"{sanitize_title(video_title)}_audio_segment_{i+1}.m4a"
255
  async for output in download_segment_async(audio_url or video_url, start_time, end_time, str(audio_output)):
256
  progress((i / total_segments) * 0.8 + (1 / total_segments) * 0.8, f"Downloading audio segment {i+1}/{total_segments}: {output}")
257
- if not audio_output.exists():
 
 
258
  raise FileNotFoundError(f"Audio segment file not found: {audio_output}")
259
- audio_segments.append(str(audio_output))
260
 
261
  except Exception as e:
262
  yield (i / total_segments) * 100, f"Error downloading segment {i+1}: {str(e)}", None
@@ -271,16 +283,10 @@ async def process_video(video_url, segments, combine, audio_only, progress=gr.Pr
271
  output_path = output_dir / f"{sanitize_title(video_title)}_combined.mp4"
272
 
273
  output_path = await combine_segments_async(video_segments if not audio_only else [], audio_segments, str(output_path))
274
- if Path(output_path).exists():
275
- yield 100, f"Segments combined and saved as {output_path}", output_path
276
- else:
277
- raise FileNotFoundError(f"Combined output file not found: {output_path}")
278
  else:
279
  output_path = audio_segments[0] if audio_only else video_segments[0]
280
- if Path(output_path).exists():
281
- yield 100, "All segments downloaded successfully", output_path
282
- else:
283
- raise FileNotFoundError(f"Output file not found: {output_path}")
284
 
285
  except Exception as e:
286
  yield 100, f"Error: {str(e)}", None
@@ -320,95 +326,80 @@ def get_video_qualities(video_url):
320
  utils.colab_check = lambda: True
321
 
322
  custom_css = """
323
- :root {
324
- --primary-hue: 210;
325
- --secondary-hue: 160;
326
- --neutral-hue: 0;
327
- --primary-color: hsl(var(--primary-hue), 70%, 55%);
328
- --secondary-color: hsl(var(--secondary-hue), 70%, 55%);
329
- --neutral-color: hsl(var(--neutral-hue), 0%, 95%);
330
- --text-color: hsl(var(--neutral-hue), 0%, 20%);
331
- --border-radius: 8px;
332
  }
333
- body { font-family: 'Inter', sans-serif; margin: 0; padding: 0; height: 100vh; overflow: hidden; }
334
- #component-0 { height: 100vh; overflow-y: auto; padding: 1rem; box-sizing: border-box; }
335
- .container { max-width: 1200px; margin: 0 auto; display: flex; flex-direction: column; height: 100%; }
336
- .header { text-align: center; margin-bottom: 1rem; }
337
- .main-content { display: flex; flex-wrap: wrap; gap: 1rem; flex-grow: 1; overflow-y: auto; }
338
- .input-section, .segment-controls, .options-section, .output-section {
339
- background-color: var(--neutral-color);
340
- border-radius: var(--border-radius);
341
- padding: 1rem;
342
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
 
 
 
 
 
 
 
 
 
343
  flex: 1 1 300px;
 
344
  }
345
- .segment-input, .time-input, .button-row {
 
 
 
346
  display: flex;
347
  flex-wrap: wrap;
348
  gap: 0.5rem;
349
  align-items: center;
350
  }
351
- .time-input { width: 60px !important; text-align: center; }
352
- .time-label, .separator { font-weight: bold; color: var(--primary-color); margin-bottom: 0.5rem; }
353
- .button-row { justify-content: space-between; }
354
  @media (max-width: 768px) {
355
- .main-content { flex-direction: column; }
356
- .input-section, .segment-controls, .options-section, .output-section { flex: 1 1 100%; }
 
 
 
 
357
  }
358
- .url-input { flex-grow: 1; }
359
- .quality-dropdown { width: 100px !important; }
360
  """
361
 
362
- with gr.Blocks(
363
- title="YouTube Segment Downloader",
364
- theme=gr.themes.Soft(
365
- primary_hue="blue",
366
- secondary_hue="green",
367
- neutral_hue="gray"
368
- ).set(
369
- body_text_color="*neutral_800",
370
- background_fill_primary="*neutral_50",
371
- button_primary_background_fill="*primary_500",
372
- button_primary_background_fill_hover="*primary_600",
373
- button_secondary_background_fill="*secondary_500",
374
- button_secondary_background_fill_hover="*secondary_600",
375
- ),
376
- css=custom_css
377
- ) as iface:
378
  with gr.Column(elem_classes="container"):
379
  gr.Markdown("# 🎬 YouTube Segment Downloader", elem_classes="header")
380
 
381
  with gr.Row(elem_classes="main-content"):
382
  with gr.Column(elem_classes="input-section"):
383
- with gr.Row():
384
- video_url = gr.Textbox(
385
- label="YouTube URL",
386
- placeholder="Paste URL here",
387
- elem_classes="url-input"
388
- )
389
- quality = gr.Dropdown(
390
- label="Quality",
391
- choices=[],
392
- interactive=True,
393
- elem_classes="quality-dropdown",
394
- visible=False
395
- )
396
  url_status = gr.Markdown(visible=False)
397
 
398
- with gr.Column(elem_classes="segment-controls"):
399
- gr.Markdown("### Add Segments", elem_classes="time-label")
400
  with gr.Row(elem_classes="segment-input"):
401
  start_hours = gr.Number(label="Start HH", minimum=0, maximum=23, step=1, value=0, elem_classes="time-input")
402
  start_minutes = gr.Number(label="MM", minimum=0, maximum=59, step=1, value=0, elem_classes="time-input")
403
  start_seconds = gr.Number(label="SS", minimum=0, maximum=59, step=1, value=0, elem_classes="time-input")
404
 
405
- gr.Markdown("to", elem_classes="separator")
406
 
407
  end_hours = gr.Number(label="End HH", minimum=0, maximum=23, step=1, value=0, elem_classes="time-input")
408
  end_minutes = gr.Number(label="MM", minimum=0, maximum=59, step=1, value=0, elem_classes="time-input")
409
- end_seconds = gr.Number(label="SS", minimum=0, maximum=59, step=1, value=0, elem_classes="time_input")
410
 
411
- add_btn = gr.Button("Add Segment", variant="primary")
412
 
413
  segments = gr.Dataframe(
414
  headers=["Segment"],
@@ -423,10 +414,10 @@ with gr.Blocks(
423
  combine = gr.Checkbox(label="Combine segments", value=True)
424
  audio_only = gr.Checkbox(label="Audio only", value=False)
425
  remove_index = gr.Number(label="Remove segment", minimum=0, step=1, value=0)
426
- remove_btn = gr.Button("Remove", variant="secondary")
427
  old_index = gr.Number(label="Move from", minimum=0, step=1, value=0)
428
  new_index = gr.Number(label="to", minimum=0, step=1, value=0)
429
- move_btn = gr.Button("Move", variant="secondary")
430
 
431
  submit_btn = gr.Button("🚀 Download", variant="primary")
432
 
 
226
  return
227
 
228
  output_dir = Path('output')
229
+
230
+ # Clean up the output directory
231
+ if output_dir.exists():
232
+ try:
233
+ shutil.rmtree(output_dir)
234
+ yield 0, "Cleaned up existing output directory", None
235
+ except Exception as e:
236
+ yield 0, f"Error cleaning up output directory: {str(e)}", None
237
+ return
238
+
239
  output_dir.mkdir(exist_ok=True)
240
 
241
  try:
 
257
  video_output = output_dir / f"{sanitize_title(video_title)}_video_segment_{i+1}.mp4"
258
  async for output in download_segment_async(video_url, start_time, end_time, str(video_output)):
259
  progress((i / total_segments) * 0.8 + (1 / total_segments) * 0.4, f"Downloading video segment {i+1}/{total_segments}: {output}")
260
+ if video_output.exists():
261
+ video_segments.append(str(video_output))
262
+ else:
263
  raise FileNotFoundError(f"Video segment file not found: {video_output}")
 
264
 
265
  audio_output = output_dir / f"{sanitize_title(video_title)}_audio_segment_{i+1}.m4a"
266
  async for output in download_segment_async(audio_url or video_url, start_time, end_time, str(audio_output)):
267
  progress((i / total_segments) * 0.8 + (1 / total_segments) * 0.8, f"Downloading audio segment {i+1}/{total_segments}: {output}")
268
+ if audio_output.exists():
269
+ audio_segments.append(str(audio_output))
270
+ else:
271
  raise FileNotFoundError(f"Audio segment file not found: {audio_output}")
 
272
 
273
  except Exception as e:
274
  yield (i / total_segments) * 100, f"Error downloading segment {i+1}: {str(e)}", None
 
283
  output_path = output_dir / f"{sanitize_title(video_title)}_combined.mp4"
284
 
285
  output_path = await combine_segments_async(video_segments if not audio_only else [], audio_segments, str(output_path))
286
+ yield 100, f"Segments combined and saved as {output_path}", output_path
 
 
 
287
  else:
288
  output_path = audio_segments[0] if audio_only else video_segments[0]
289
+ yield 100, "All segments downloaded successfully", output_path
 
 
 
290
 
291
  except Exception as e:
292
  yield 100, f"Error: {str(e)}", None
 
326
  utils.colab_check = lambda: True
327
 
328
  custom_css = """
329
+ #component-0 {
330
+ max-width: 100%;
331
+ margin: 0 auto;
332
+ padding: 10px;
333
+ box-sizing: border-box;
 
 
 
 
334
  }
335
+ .container {
336
+ display: flex;
337
+ flex-direction: column;
338
+ height: calc(100vh - 100px);
339
+ max-width: 1200px;
340
+ margin: 0 auto;
341
+ }
342
+ .header {
343
+ text-align: center;
344
+ margin-bottom: 1rem;
345
+ }
346
+ .main-content {
347
+ display: flex;
348
+ flex-wrap: wrap;
349
+ gap: 1rem;
350
+ overflow-y: auto;
351
+ flex: 1;
352
+ }
353
+ .input-section, .options-section {
354
  flex: 1 1 300px;
355
+ min-width: 300px;
356
  }
357
+ .output-section {
358
+ flex-basis: 100%;
359
+ }
360
+ .segment-input {
361
  display: flex;
362
  flex-wrap: wrap;
363
  gap: 0.5rem;
364
  align-items: center;
365
  }
366
+ .time-input {
367
+ width: 60px !important;
368
+ }
369
  @media (max-width: 768px) {
370
+ .main-content {
371
+ flex-direction: column;
372
+ }
373
+ .input-section, .options-section {
374
+ flex-basis: 100%;
375
+ }
376
  }
 
 
377
  """
378
 
379
+ with gr.Blocks(css=custom_css) as iface:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
380
  with gr.Column(elem_classes="container"):
381
  gr.Markdown("# 🎬 YouTube Segment Downloader", elem_classes="header")
382
 
383
  with gr.Row(elem_classes="main-content"):
384
  with gr.Column(elem_classes="input-section"):
385
+ video_url = gr.Textbox(label="YouTube URL", placeholder="Paste URL here")
386
+ quality = gr.Dropdown(label="Quality", choices=[], interactive=True)
 
 
 
 
 
 
 
 
 
 
 
387
  url_status = gr.Markdown(visible=False)
388
 
389
+ with gr.Column():
390
+ gr.Markdown("### Add Segments")
391
  with gr.Row(elem_classes="segment-input"):
392
  start_hours = gr.Number(label="Start HH", minimum=0, maximum=23, step=1, value=0, elem_classes="time-input")
393
  start_minutes = gr.Number(label="MM", minimum=0, maximum=59, step=1, value=0, elem_classes="time-input")
394
  start_seconds = gr.Number(label="SS", minimum=0, maximum=59, step=1, value=0, elem_classes="time-input")
395
 
396
+ gr.Markdown("to")
397
 
398
  end_hours = gr.Number(label="End HH", minimum=0, maximum=23, step=1, value=0, elem_classes="time-input")
399
  end_minutes = gr.Number(label="MM", minimum=0, maximum=59, step=1, value=0, elem_classes="time-input")
400
+ end_seconds = gr.Number(label="SS", minimum=0, maximum=59, step=1, value=0, elem_classes="time-input")
401
 
402
+ add_btn = gr.Button("Add Segment")
403
 
404
  segments = gr.Dataframe(
405
  headers=["Segment"],
 
414
  combine = gr.Checkbox(label="Combine segments", value=True)
415
  audio_only = gr.Checkbox(label="Audio only", value=False)
416
  remove_index = gr.Number(label="Remove segment", minimum=0, step=1, value=0)
417
+ remove_btn = gr.Button("Remove")
418
  old_index = gr.Number(label="Move from", minimum=0, step=1, value=0)
419
  new_index = gr.Number(label="to", minimum=0, step=1, value=0)
420
+ move_btn = gr.Button("Move")
421
 
422
  submit_btn = gr.Button("🚀 Download", variant="primary")
423