Spaces:
Sleeping
Sleeping
Update app.py
Browse files
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 |
-
|
| 361 |
-
|
| 362 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 363 |
|
| 364 |
with gr.Row():
|
| 365 |
with gr.Column():
|
| 366 |
-
|
| 367 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 368 |
|
| 369 |
with gr.Column():
|
| 370 |
-
gr.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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.
|
| 390 |
-
|
| 391 |
-
|
| 392 |
-
|
| 393 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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.
|
|
|
|
| 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 415 |
|
| 416 |
with gr.Row():
|
| 417 |
with gr.Column(scale=2):
|
| 418 |
-
resumo_out = gr.Textbox(label="
|
| 419 |
with gr.Column(scale=1):
|
| 420 |
-
status_out = gr.Textbox(label="
|
| 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.
|
| 431 |
-
|
| 432 |
-
|
| 433 |
-
|
| 434 |
-
|
| 435 |
-
|
| 436 |
-
|
| 437 |
-
|
| 438 |
-
|
| 439 |
-
|
| 440 |
-
|
| 441 |
-
|
| 442 |
-
|
| 443 |
-
|
| 444 |
-
|
| 445 |
-
|
| 446 |
-
|
| 447 |
-
|
| 448 |
-
|
| 449 |
-
|
| 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__":
|