leicam commited on
Commit
712dcc4
·
verified ·
1 Parent(s): 03c0164

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +253 -42
app.py CHANGED
@@ -357,17 +357,174 @@ def process_xml_and_transcript(premiere_xml_file, transcript_txt_file, use_llm,
357
  status = f"✓ Modo: {mode} | LLM disponível: {LLM_AVAILABLE} | LLM usado: {use_llm and LLM_AVAILABLE and not manual_ranges}"
358
  return resumo, out_path, status
359
 
360
- with gr.Blocks(theme=gr.themes.Soft()) as demo:
361
- gr.Markdown("# 🎬 Agente de Edição XML para Premiere (Controles Avançados)")
362
- gr.Markdown("Edite sua sequência do Premiere com controle total sobre a seleção de trechos.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
363
 
364
  with gr.Row():
365
  with gr.Column():
366
- xml_in = gr.File(label="📁 XML da sequência (FCP XML)", file_types=[".xml"])
367
- txt_in = gr.File(label="📄 Transcrição (.txt) - Opcional se usar minutagens manuais", file_types=[".txt"])
 
 
 
 
 
368
 
369
  with gr.Column():
370
- gr.Markdown("### ⚙️ Configurações")
 
 
 
 
371
  use_llm = gr.Checkbox(
372
  label="🤖 Usar LLM (Gemini) para seleção semântica",
373
  value=USE_LLM_DEFAULT and LLM_AVAILABLE,
@@ -380,17 +537,27 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
380
  )
381
 
382
  with gr.Accordion("✂️ MINUTAGENS MANUAIS (Sobrescreve tudo)", open=True):
 
 
 
 
 
 
 
383
  manual_timecodes = gr.Textbox(
384
  label="Cole aqui os timecodes exatos que você quer cortar",
385
  placeholder="Exemplo:\n00:01:23:15 - 00:02:45:10\n00:05:30:00 - 00:07:15:22\n00:10:00:05 - 00:12:30:18",
386
- lines=5,
387
- info="⚠️ Se preencher este campo, o app ignora a transcrição e todos os outros parâmetros, cortando EXATAMENTE o que você especificou"
388
  )
389
- gr.Markdown("""
390
- **Formatos aceitos:**
391
- - `hh:mm:ss:ff - hh:mm:ss:ff` (um por linha)
392
- - Pode separar por vírgula também
393
- - Exemplo: `00:01:30:00 - 00:02:00:15, 00:05:10:00 - 00:06:20:10`
 
 
 
 
394
  """)
395
 
396
  with gr.Accordion("🎯 Palavras-chave Personalizadas", open=False):
@@ -401,23 +568,35 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
401
  )
402
 
403
  with gr.Accordion("⚖️ Ajuste Fino dos Pesos de Pontuação", open=False):
404
- gr.Markdown("Ajuste a importância de cada categoria na pontuação heurística:")
 
405
  with gr.Row():
406
- weight_emotion = gr.Slider(0, 5, value=2.0, step=0.1, label="Emoção")
407
- weight_break = gr.Slider(0, 5, value=1.5, step=0.1, label="Quebra de expectativa")
408
  with gr.Row():
409
- weight_learn = gr.Slider(0, 5, value=1.2, step=0.1, label="Aprendizado")
410
- weight_viral = gr.Slider(0, 5, value=1.0, step=0.1, label="Viralização")
 
 
 
 
411
 
412
  run_btn = gr.Button("🚀 Processar e Gerar XML Editado", variant="primary", size="lg")
413
 
414
- gr.Markdown("---")
 
 
 
 
 
 
 
415
 
416
  with gr.Row():
417
  with gr.Column(scale=2):
418
- resumo_out = gr.Textbox(label="📋 Resumo dos cortes aplicados", lines=15)
419
  with gr.Column(scale=1):
420
- status_out = gr.Textbox(label="ℹ️ Status", interactive=False)
421
  file_out = gr.File(label="💾 Download do XML Editado")
422
 
423
  run_btn.click(
@@ -427,27 +606,59 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
427
  outputs=[resumo_out, file_out, status_out]
428
  )
429
 
430
- gr.Markdown("""
431
- ### 💡 Modos de uso:
432
-
433
- **🎯 MODO MANUAL (Recomendado para controle total)**
434
- - Preencha o campo "Minutagens Manuais" com seus timecodes exatos
435
- - A transcrição se torna opcional
436
- - Todos os outros parâmetros são ignorados
437
- - O corte será feito EXATAMENTE como você especificou
438
-
439
- **🤖 MODO AUTOMÁTICO**
440
- - Deixe as minutagens manuais vazias
441
- - Envie a transcrição com timecodes
442
- - Configure LLM, palavras-chave e pesos conforme desejado
443
- - O app escolhe os melhores trechos automaticamente
444
-
445
- **Exemplos de minutagens manuais:**
446
- ```
447
- 00:01:23:15 - 00:02:45:10
448
- 00:05:30:00 - 00:07:15:22
449
- 00:10:00:05 - 00:12:30:18
450
- ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
451
  """)
452
 
453
  if __name__ == "__main__":
 
357
  status = f"✓ Modo: {mode} | LLM disponível: {LLM_AVAILABLE} | LLM usado: {use_llm and LLM_AVAILABLE and not manual_ranges}"
358
  return resumo, out_path, status
359
 
360
+ css = """
361
+ /* Design Tokens */
362
+ :root {
363
+ --neon: #39FF14;
364
+ --txt: #0a0a0a;
365
+ --muted: #6b7280;
366
+ --line: #e5e7eb;
367
+ --bg: #ffffff;
368
+ }
369
+
370
+ /* Global Styles */
371
+ .gradio-container {
372
+ font-family: 'Manrope', system-ui, -apple-system, sans-serif !important;
373
+ background: linear-gradient(135deg, rgba(57,255,20,0.03) 0%, rgba(255,255,255,1) 100%);
374
+ background-attachment: fixed;
375
+ }
376
+
377
+ /* Headers */
378
+ .gradio-container h1, .gradio-container h2, .gradio-container h3 {
379
+ font-weight: 800 !important;
380
+ letter-spacing: -0.3px !important;
381
+ color: var(--txt) !important;
382
+ }
383
+
384
+ .gradio-container h1 {
385
+ font-size: clamp(28px, 5vw, 46px) !important;
386
+ margin-bottom: 8px !important;
387
+ }
388
+
389
+ .gradio-container .gr-prose p {
390
+ color: var(--muted) !important;
391
+ line-height: 1.65 !important;
392
+ font-size: 16px !important;
393
+ }
394
+
395
+ /* Buttons */
396
+ .gradio-container button.primary {
397
+ background: var(--neon) !important;
398
+ color: #000 !important;
399
+ border: none !important;
400
+ border-radius: 10px !important;
401
+ font-weight: 800 !important;
402
+ padding: 12px 20px !important;
403
+ box-shadow: 0 2px 0 rgba(0,0,0,0.12), 0 10px 30px rgba(57,255,20,0.18) !important;
404
+ transition: all 0.2s ease !important;
405
+ }
406
+
407
+ .gradio-container button.primary:hover {
408
+ transform: translateY(-1px) !important;
409
+ filter: saturate(1.03) !important;
410
+ }
411
+
412
+ .gradio-container button:not(.primary) {
413
+ background: #fff !important;
414
+ border: 1px solid var(--line) !important;
415
+ border-radius: 10px !important;
416
+ color: var(--txt) !important;
417
+ font-weight: 600 !important;
418
+ }
419
+
420
+ /* Inputs, Textareas, File uploads */
421
+ .gradio-container input, .gradio-container textarea, .gradio-container .wrap {
422
+ border: 1px solid var(--line) !important;
423
+ border-radius: 12px !important;
424
+ background: #fff !important;
425
+ transition: all 0.2s ease !important;
426
+ }
427
+
428
+ .gradio-container input:focus, .gradio-container textarea:focus {
429
+ border-color: #cbd5e1 !important;
430
+ box-shadow: 0 0 0 3px rgba(57,255,20,0.16) !important;
431
+ }
432
+
433
+ /* Cards/Panels */
434
+ .gradio-container .block {
435
+ border: 1px solid var(--line) !important;
436
+ border-radius: 16px !important;
437
+ background: #fff !important;
438
+ box-shadow: 0 2px 8px rgba(0,0,0,0.06) !important;
439
+ transition: all 0.2s ease !important;
440
+ }
441
+
442
+ .gradio-container .block:hover {
443
+ box-shadow: 0 6px 16px rgba(0,0,0,0.08) !important;
444
+ transform: translateY(-1px) !important;
445
+ }
446
+
447
+ /* Accordion */
448
+ .gradio-container .label-wrap {
449
+ font-weight: 700 !important;
450
+ color: var(--txt) !important;
451
+ }
452
+
453
+ /* Checkboxes */
454
+ .gradio-container input[type="checkbox"]:checked {
455
+ background: var(--neon) !important;
456
+ border-color: var(--neon) !important;
457
+ }
458
+
459
+ /* Sliders */
460
+ .gradio-container input[type="range"]::-webkit-slider-thumb {
461
+ background: var(--neon) !important;
462
+ }
463
+
464
+ .gradio-container input[type="range"]::-moz-range-thumb {
465
+ background: var(--neon) !important;
466
+ }
467
+
468
+ /* File upload areas */
469
+ .gradio-container .upload-container {
470
+ border: 2px dashed var(--line) !important;
471
+ border-radius: 12px !important;
472
+ background: #fafafa !important;
473
+ }
474
+
475
+ /* Badges/Tags */
476
+ .gradio-container .badge {
477
+ background: var(--neon) !important;
478
+ color: #000 !important;
479
+ font-size: 12px !important;
480
+ font-weight: 900 !important;
481
+ padding: 4px 8px !important;
482
+ border-radius: 999px !important;
483
+ }
484
+
485
+ /* Status indicators */
486
+ .gradio-container .generating {
487
+ border-color: var(--neon) !important;
488
+ }
489
+
490
+ /* Container spacing */
491
+ .gradio-container .contain {
492
+ max-width: 1120px !important;
493
+ margin: 0 auto !important;
494
+ }
495
+ """
496
+
497
+ with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
498
+ gr.HTML("""
499
+ <link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;600;700;800&display=swap" rel="stylesheet">
500
+ <div style="text-align: center; padding: 24px 0 16px;">
501
+ <div style="display: inline-flex; align-items: center; gap: 8px; margin-bottom: 12px;">
502
+ <div style="width: 12px; height: 12px; border-radius: 50%; background: #39FF14; box-shadow: 0 0 20px rgba(57,255,20,0.4);"></div>
503
+ <h1 style="margin: 0; font-weight: 800; letter-spacing: -0.4px;">Agente de Edição XML · Premiere</h1>
504
+ </div>
505
+ <p style="color: #6b7280; max-width: 720px; margin: 0 auto; line-height: 1.65;">
506
+ Edite sua sequência do Premiere com <strong>controle total</strong> sobre a seleção de trechos.
507
+ Modo manual ou automático com IA.
508
+ </p>
509
+ </div>
510
+ """)
511
 
512
  with gr.Row():
513
  with gr.Column():
514
+ gr.HTML("""<div style="background: linear-gradient(135deg, #f9fafb 0%, #fff 100%);
515
+ padding: 16px; border-radius: 16px; border: 1px solid #e5e7eb; margin-bottom: 16px;">
516
+ <div style="font-weight: 700; color: #0a0a0a; margin-bottom: 8px;">📁 Arquivos de entrada</div>
517
+ <p style="color: #6b7280; font-size: 14px; margin: 0;">Envie o XML exportado do Premiere e a transcrição</p>
518
+ </div>""")
519
+ xml_in = gr.File(label="XML da sequência (FCP XML)", file_types=[".xml"])
520
+ txt_in = gr.File(label="Transcrição (.txt) - Opcional no modo manual", file_types=[".txt"])
521
 
522
  with gr.Column():
523
+ gr.HTML("""<div style="background: linear-gradient(135deg, rgba(57,255,20,0.08) 0%, rgba(57,255,20,0.02) 100%);
524
+ padding: 16px; border-radius: 16px; border: 1px solid #e5e7eb; margin-bottom: 16px;">
525
+ <div style="font-weight: 700; color: #0a0a0a; margin-bottom: 8px;">⚙️ Configurações básicas</div>
526
+ <p style="color: #6b7280; font-size: 14px; margin: 0;">Ajuste o comportamento do processamento</p>
527
+ </div>""")
528
  use_llm = gr.Checkbox(
529
  label="🤖 Usar LLM (Gemini) para seleção semântica",
530
  value=USE_LLM_DEFAULT and LLM_AVAILABLE,
 
537
  )
538
 
539
  with gr.Accordion("✂️ MINUTAGENS MANUAIS (Sobrescreve tudo)", open=True):
540
+ gr.HTML("""<div style="background: #fffbeb; padding: 12px; border-radius: 10px; border: 1px solid #fde68a; margin-bottom: 12px;">
541
+ <strong style="color: #92400e;">⚠️ Modo de Controle Total</strong>
542
+ <p style="color: #78350f; font-size: 13px; margin: 6px 0 0;">
543
+ Se preencher este campo, o app ignora a transcrição e todos os outros parâmetros,
544
+ cortando EXATAMENTE o que você especificou.
545
+ </p>
546
+ </div>""")
547
  manual_timecodes = gr.Textbox(
548
  label="Cole aqui os timecodes exatos que você quer cortar",
549
  placeholder="Exemplo:\n00:01:23:15 - 00:02:45:10\n00:05:30:00 - 00:07:15:22\n00:10:00:05 - 00:12:30:18",
550
+ lines=5
 
551
  )
552
+ gr.HTML("""
553
+ <div style="padding: 12px; background: #f9fafb; border-radius: 10px; margin-top: 12px;">
554
+ <div style="font-weight: 600; margin-bottom: 8px; color: #0a0a0a;">Formatos aceitos:</div>
555
+ <ul style="margin: 0; padding-left: 20px; color: #6b7280; font-size: 13px;">
556
+ <li><code>hh:mm:ss:ff - hh:mm:ss:ff</code> (um por linha)</li>
557
+ <li>Pode separar por vírgula também</li>
558
+ <li>Exemplo: <code>00:01:30:00 - 00:02:00:15, 00:05:10:00 - 00:06:20:10</code></li>
559
+ </ul>
560
+ </div>
561
  """)
562
 
563
  with gr.Accordion("🎯 Palavras-chave Personalizadas", open=False):
 
568
  )
569
 
570
  with gr.Accordion("⚖️ Ajuste Fino dos Pesos de Pontuação", open=False):
571
+ gr.HTML("""<p style="color: #6b7280; margin-bottom: 16px;">
572
+ Ajuste a importância de cada categoria na pontuação heurística (modo automático)</p>""")
573
  with gr.Row():
574
+ weight_emotion = gr.Slider(0, 5, value=2.0, step=0.1, label="😢 Emoção")
575
+ weight_break = gr.Slider(0, 5, value=1.5, step=0.1, label="💥 Quebra de expectativa")
576
  with gr.Row():
577
+ weight_learn = gr.Slider(0, 5, value=1.2, step=0.1, label="🎓 Aprendizado")
578
+ weight_viral = gr.Slider(0, 5, value=1.0, step=0.1, label="🚀 Viralização")
579
+
580
+ gr.HTML("""<div style="margin: 24px 0; text-align: center;">
581
+ <hr style="border: none; border-top: 1px solid #e5e7eb; margin: 16px 0;">
582
+ </div>""")
583
 
584
  run_btn = gr.Button("🚀 Processar e Gerar XML Editado", variant="primary", size="lg")
585
 
586
+ gr.HTML("""<div style="margin: 20px 0;">
587
+ <hr style="border: none; border-top: 1px solid #e5e7eb;">
588
+ </div>""")
589
+
590
+ gr.HTML("""<div style="text-align: center; margin-bottom: 16px;">
591
+ <div style="font-weight: 700; color: #0a0a0a; margin-bottom: 4px;">📋 Resultados</div>
592
+ <p style="color: #6b7280; font-size: 14px; margin: 0;">Resumo dos cortes e arquivo para download</p>
593
+ </div>""")
594
 
595
  with gr.Row():
596
  with gr.Column(scale=2):
597
+ resumo_out = gr.Textbox(label="Resumo dos cortes aplicados", lines=15)
598
  with gr.Column(scale=1):
599
+ status_out = gr.Textbox(label="Status", interactive=False)
600
  file_out = gr.File(label="💾 Download do XML Editado")
601
 
602
  run_btn.click(
 
606
  outputs=[resumo_out, file_out, status_out]
607
  )
608
 
609
+ with gr.Accordion("💡 Guia de Uso", open=False):
610
+ gr.HTML("""
611
+ <div style="padding: 16px; background: #f9fafb; border-radius: 12px;">
612
+ <div style="margin-bottom: 20px;">
613
+ <div style="display: inline-block; background: #39FF14; color: #000; padding: 4px 10px;
614
+ border-radius: 999px; font-size: 12px; font-weight: 900; margin-bottom: 8px;">
615
+ MODO MANUAL
616
+ </div>
617
+ <h3 style="margin: 8px 0; font-weight: 700; color: #0a0a0a;">🎯 Controle Total</h3>
618
+ <ul style="color: #6b7280; line-height: 1.65; padding-left: 20px;">
619
+ <li>Preencha o campo "Minutagens Manuais" com seus timecodes exatos</li>
620
+ <li>A transcrição se torna opcional</li>
621
+ <li>Todos os outros parâmetros são ignorados</li>
622
+ <li>O corte será feito EXATAMENTE como você especificou</li>
623
+ </ul>
624
+ </div>
625
+
626
+ <div style="margin-bottom: 20px;">
627
+ <div style="display: inline-block; background: #dbeafe; color: #1e40af; padding: 4px 10px;
628
+ border-radius: 999px; font-size: 12px; font-weight: 900; margin-bottom: 8px;">
629
+ MODO AUTOMÁTICO
630
+ </div>
631
+ <h3 style="margin: 8px 0; font-weight: 700; color: #0a0a0a;">🤖 Seleção Inteligente</h3>
632
+ <ul style="color: #6b7280; line-height: 1.65; padding-left: 20px;">
633
+ <li>Deixe as minutagens manuais vazias</li>
634
+ <li>Envie a transcrição com timecodes</li>
635
+ <li>Configure LLM, palavras-chave e pesos conforme desejado</li>
636
+ <li>O app escolhe os melhores trechos automaticamente</li>
637
+ </ul>
638
+ </div>
639
+
640
+ <div style="background: #fff; padding: 12px; border-radius: 8px; border: 1px solid #e5e7eb;">
641
+ <div style="font-weight: 700; color: #0a0a0a; margin-bottom: 8px;">Exemplos de minutagens manuais:</div>
642
+ <code style="display: block; background: #f3f4f6; padding: 10px; border-radius: 6px;
643
+ font-size: 13px; color: #374151; font-family: monospace;">
644
+ 00:01:23:15 - 00:02:45:10<br>
645
+ 00:05:30:00 - 00:07:15:22<br>
646
+ 00:10:00:05 - 00:12:30:18
647
+ </code>
648
+ </div>
649
+ </div>
650
+ """)
651
+
652
+ gr.HTML("""
653
+ <footer style="margin-top: 40px; padding: 24px 0; border-top: 1px solid #e5e7eb; text-align: center;">
654
+ <div style="display: inline-flex; align-items: center; gap: 8px; margin-bottom: 8px;">
655
+ <div style="width: 10px; height: 10px; border-radius: 50%; background: #39FF14;"></div>
656
+ <span style="font-weight: 700; color: #0a0a0a;">Leicam · Tech</span>
657
+ </div>
658
+ <p style="color: #6b7280; font-size: 13px; margin: 0;">
659
+ Ferramentas práticas para produção de conteúdo
660
+ </p>
661
+ </footer>
662
  """)
663
 
664
  if __name__ == "__main__":