dd
Browse files
app.py
CHANGED
@@ -367,67 +367,185 @@ def predict(
|
|
367 |
return (None, metrics_text)
|
368 |
return ("output.wav", metrics_text)
|
369 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
370 |
# Giao diện Gradio
|
371 |
-
with gr.Blocks(analytics_enabled=False) as demo:
|
372 |
-
|
373 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
374 |
gr.Markdown(
|
375 |
"""
|
376 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
377 |
"""
|
378 |
)
|
379 |
-
with gr.Column():
|
380 |
-
pass
|
381 |
-
|
382 |
-
with gr.Row():
|
383 |
-
with gr.Column():
|
384 |
-
input_text_gr = gr.Textbox(
|
385 |
-
label="Bạn cần nội dung gì?",
|
386 |
-
info="Tôi có thể viết và thu âm luôn cho bạn",
|
387 |
-
value="Lời tự sự của AI, 150 từ",
|
388 |
-
)
|
389 |
-
language_gr = gr.Dropdown(
|
390 |
-
label="Language (Ngôn ngữ)",
|
391 |
-
choices=[
|
392 |
-
"vi", "en", "es", "fr", "de", "it", "pt", "pl", "tr", "ru", "nl", "cs", "ar", "zh-cn", "ja", "ko", "hu", "hi",
|
393 |
-
],
|
394 |
-
max_choices=1,
|
395 |
-
value="vi",
|
396 |
-
)
|
397 |
-
normalize_text = gr.Checkbox(
|
398 |
-
label="Chuẩn hóa văn bản tiếng Việt",
|
399 |
-
info="Normalize Vietnamese text",
|
400 |
-
value=True,
|
401 |
-
)
|
402 |
-
use_llm_checkbox = gr.Checkbox(
|
403 |
-
label="Sử dụng LLM để tạo nội dung",
|
404 |
-
info="Use LLM to generate content",
|
405 |
-
value=True,
|
406 |
-
)
|
407 |
-
content_type_dropdown = gr.Dropdown(
|
408 |
-
label="Loại nội dung",
|
409 |
-
choices=["triết lý sống", "Theo yêu cầu", "tin thể thao", "tin bóng đá"],
|
410 |
-
value="Theo yêu cầu",
|
411 |
-
)
|
412 |
-
ref_gr = gr.Audio(
|
413 |
-
label="Reference Audio (Giọng mẫu)",
|
414 |
-
type="filepath",
|
415 |
-
value="nam-tai-llieu.wav",
|
416 |
-
)
|
417 |
-
tts_button = gr.Button(
|
418 |
-
"Đọc 🗣️🔥",
|
419 |
-
elem_id="send-btn",
|
420 |
-
visible=True,
|
421 |
-
variant="primary",
|
422 |
-
)
|
423 |
-
video_button = gr.Button("Tạo Video 🎥", visible=True) # Nút tạo video luôn hiển thị
|
424 |
-
|
425 |
-
with gr.Column():
|
426 |
-
audio_gr = gr.Audio(label="Synthesised Audio", autoplay=True)
|
427 |
-
out_text_gr = gr.Text(label="Metrics")
|
428 |
-
video_output = gr.Video(label="Generated Video", visible=True) # Hiển thị video
|
429 |
-
video_status = gr.Text(label="Video Status")
|
430 |
|
|
|
431 |
tts_button.click(
|
432 |
predict,
|
433 |
[
|
@@ -454,6 +572,40 @@ with gr.Blocks(analytics_enabled=False) as demo:
|
|
454 |
],
|
455 |
outputs=[video_output, video_status],
|
456 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
457 |
|
458 |
-
|
459 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
367 |
return (None, metrics_text)
|
368 |
return ("output.wav", metrics_text)
|
369 |
|
370 |
+
# Hàm xử lý tin thể thao
|
371 |
+
def generate_sports_news(news_type, language, limit):
|
372 |
+
"""Tạo nội dung tin thể thao"""
|
373 |
+
try:
|
374 |
+
content = get_sports_news_content(news_type, language, limit)
|
375 |
+
return content, "Đã tạo tin thể thao thành công!"
|
376 |
+
except Exception as e:
|
377 |
+
return f"Lỗi khi tạo tin thể thao: {str(e)}", "Có lỗi xảy ra"
|
378 |
+
|
379 |
# Giao diện Gradio
|
380 |
+
with gr.Blocks(analytics_enabled=False, title="TTS & Sports News Generator", theme=gr.themes.Soft()) as demo:
|
381 |
+
gr.Markdown(
|
382 |
+
"""
|
383 |
+
# 🎙️ TTS & Sports News Generator ✨
|
384 |
+
### Tạo nội dung và chuyển đổi thành giọng nói - Powered by TDNM
|
385 |
+
"""
|
386 |
+
)
|
387 |
+
|
388 |
+
with gr.Tabs() as tabs:
|
389 |
+
# Tab 1: TTS Generator
|
390 |
+
with gr.Tab("🎙️ Tạo Giọng Nói", id="tts_tab"):
|
391 |
+
with gr.Row():
|
392 |
+
with gr.Column(scale=1):
|
393 |
+
gr.Markdown("### 📝 Nhập Nội Dung")
|
394 |
+
input_text_gr = gr.Textbox(
|
395 |
+
label="Bạn cần nội dung gì?",
|
396 |
+
info="Tôi có thể viết và thu âm luôn cho bạn",
|
397 |
+
value="Lời tự sự của AI, 150 từ",
|
398 |
+
lines=4,
|
399 |
+
placeholder="Nhập nội dung bạn muốn chuyển thành giọng nói..."
|
400 |
+
)
|
401 |
+
|
402 |
+
with gr.Row():
|
403 |
+
language_gr = gr.Dropdown(
|
404 |
+
label="🌍 Ngôn ngữ",
|
405 |
+
choices=[
|
406 |
+
"vi", "en", "es", "fr", "de", "it", "pt", "pl", "tr", "ru", "nl", "cs", "ar", "zh-cn", "ja", "ko", "hu", "hi",
|
407 |
+
],
|
408 |
+
value="vi",
|
409 |
+
)
|
410 |
+
content_type_dropdown = gr.Dropdown(
|
411 |
+
label="📋 Loại nội dung",
|
412 |
+
choices=["Theo yêu cầu", "triết lý sống", "tin thể thao", "tin bóng đá"],
|
413 |
+
value="Theo yêu cầu",
|
414 |
+
)
|
415 |
+
|
416 |
+
with gr.Row():
|
417 |
+
normalize_text = gr.Checkbox(
|
418 |
+
label="Chuẩn hóa văn bản tiếng Việt",
|
419 |
+
value=True,
|
420 |
+
)
|
421 |
+
use_llm_checkbox = gr.Checkbox(
|
422 |
+
label="Sử dụng AI tạo nội dung",
|
423 |
+
value=True,
|
424 |
+
)
|
425 |
+
|
426 |
+
ref_gr = gr.Audio(
|
427 |
+
label="🎤 Giọng mẫu (Reference Audio)",
|
428 |
+
type="filepath",
|
429 |
+
value="nam-tai-llieu.wav",
|
430 |
+
)
|
431 |
+
|
432 |
+
with gr.Row():
|
433 |
+
tts_button = gr.Button(
|
434 |
+
"🗣️ Tạo Giọng Nói",
|
435 |
+
variant="primary",
|
436 |
+
size="lg"
|
437 |
+
)
|
438 |
+
video_button = gr.Button(
|
439 |
+
"🎥 Tạo Video",
|
440 |
+
variant="secondary",
|
441 |
+
size="lg"
|
442 |
+
)
|
443 |
+
|
444 |
+
with gr.Column(scale=1):
|
445 |
+
gr.Markdown("### 🎵 Kết Quả")
|
446 |
+
audio_gr = gr.Audio(label="Audio đã tạo", autoplay=True)
|
447 |
+
out_text_gr = gr.Textbox(label="📊 Thông tin", lines=3)
|
448 |
+
video_output = gr.Video(label="Video đã tạo")
|
449 |
+
video_status = gr.Textbox(label="Trạng thái video")
|
450 |
+
|
451 |
+
# Tab 2: Sports News Generator
|
452 |
+
with gr.Tab("⚽ Tin Thể Thao", id="sports_tab"):
|
453 |
+
with gr.Row():
|
454 |
+
with gr.Column(scale=1):
|
455 |
+
gr.Markdown(
|
456 |
+
"""
|
457 |
+
### 📰 Tạo Tin Thể Thao Tự Động
|
458 |
+
Lấy tin thể thao mới nhất từ các nguồn quốc tế và tạo nội dung bằng tiếng Việt
|
459 |
+
"""
|
460 |
+
)
|
461 |
+
|
462 |
+
with gr.Row():
|
463 |
+
sports_news_type = gr.Dropdown(
|
464 |
+
label="🏆 Loại tin thể thao",
|
465 |
+
choices=["all", "football"],
|
466 |
+
value="all",
|
467 |
+
info="Chọn loại tin thể thao bạn muốn"
|
468 |
+
)
|
469 |
+
sports_language = gr.Dropdown(
|
470 |
+
label="🌍 Ngôn ngữ nguồn",
|
471 |
+
choices=["vi", "en"],
|
472 |
+
value="vi",
|
473 |
+
info="Ngôn ngữ của nguồn tin"
|
474 |
+
)
|
475 |
+
|
476 |
+
sports_limit = gr.Slider(
|
477 |
+
label="📊 Số lượng tin",
|
478 |
+
minimum=1,
|
479 |
+
maximum=10,
|
480 |
+
value=5,
|
481 |
+
step=1,
|
482 |
+
info="Số lượng tin thể thao muốn lấy"
|
483 |
+
)
|
484 |
+
|
485 |
+
with gr.Row():
|
486 |
+
generate_sports_btn = gr.Button(
|
487 |
+
"📰 Tạo Tin Thể Thao",
|
488 |
+
variant="primary",
|
489 |
+
size="lg"
|
490 |
+
)
|
491 |
+
use_sports_for_tts_btn = gr.Button(
|
492 |
+
"🎙️ Chuyển Sang TTS",
|
493 |
+
variant="secondary",
|
494 |
+
size="lg"
|
495 |
+
)
|
496 |
+
|
497 |
+
with gr.Column(scale=1):
|
498 |
+
gr.Markdown("### 📋 Nội Dung Tin Thể Thao")
|
499 |
+
sports_content_output = gr.Textbox(
|
500 |
+
label="Nội dung tin thể thao",
|
501 |
+
lines=15,
|
502 |
+
placeholder="Nội dung tin thể thao sẽ hiển thị ở đây...",
|
503 |
+
show_copy_button=True
|
504 |
+
)
|
505 |
+
sports_status = gr.Textbox(
|
506 |
+
label="Trạng thái",
|
507 |
+
lines=2
|
508 |
+
)
|
509 |
+
|
510 |
+
# Tab 3: Hướng dẫn
|
511 |
+
with gr.Tab("📖 Hướng Dẫn", id="guide_tab"):
|
512 |
gr.Markdown(
|
513 |
"""
|
514 |
+
## 🚀 Hướng Dẫn Sử Dụng
|
515 |
+
|
516 |
+
### 🎙️ Tab Tạo Giọng Nói:
|
517 |
+
1. **Nhập nội dung**: Gõ văn bản bạn muốn chuyển thành giọng nói
|
518 |
+
2. **Chọn ngôn ngữ**: Hiện tại hỗ trợ tiếng Việt và nhiều ngôn ngữ khác
|
519 |
+
3. **Chọn loại nội dung**:
|
520 |
+
- "Theo yêu cầu": Sử dụng nội dung bạn nhập
|
521 |
+
- "triết lý sống": AI tạo nội dung về triết lý
|
522 |
+
- "tin thể thao": AI tạo tin thể thao
|
523 |
+
- "tin bóng đá": AI tạo tin bóng đá
|
524 |
+
4. **Upload giọng mẫu**: Chọn file audio làm mẫu giọng nói
|
525 |
+
5. **Nhấn "Tạo Giọng Nói"**: Hệ thống sẽ tạo audio
|
526 |
+
6. **Tạo Video** (tùy chọn): Tạo video từ audio và hình ảnh
|
527 |
+
|
528 |
+
### ⚽ Tab Tin Thể Thao:
|
529 |
+
1. **Chọn loại tin**: Tất cả tin thể thao hoặc chỉ bóng đá
|
530 |
+
2. **Chọn ngôn ngữ nguồn**: Tiếng Việt hoặc tiếng Anh
|
531 |
+
3. **Chọn số lượng tin**: Từ 1-10 tin
|
532 |
+
4. **Nhấn "Tạo Tin Thể Thao"**: Lấy tin mới nhất
|
533 |
+
5. **Chuyển sang TTS**: Sử dụng nội dung tin để tạo giọng nói
|
534 |
+
|
535 |
+
### 🔧 Tính Năng Nổi Bật:
|
536 |
+
- ✅ TTS tiếng Việt chất lượng cao với viXTTS
|
537 |
+
- ✅ Tạo nội dung tự động bằng AI
|
538 |
+
- ✅ Lấy tin thể thao thời gian thực
|
539 |
+
- ✅ Tạo video từ audio và hình ảnh
|
540 |
+
- ✅ Hỗ trợ nhiều ngôn ngữ
|
541 |
+
- ✅ Giao diện thân thiện, dễ sử dụng
|
542 |
+
|
543 |
+
### 📞 Hỗ Trợ:
|
544 |
+
Nếu gặp vấn đề, vui lòng liên hệ: **https://www.tdn-m.com**
|
545 |
"""
|
546 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
547 |
|
548 |
+
# Event handlers cho tab TTS
|
549 |
tts_button.click(
|
550 |
predict,
|
551 |
[
|
|
|
572 |
],
|
573 |
outputs=[video_output, video_status],
|
574 |
)
|
575 |
+
|
576 |
+
# Event handlers cho tab tin thể thao
|
577 |
+
generate_sports_btn.click(
|
578 |
+
generate_sports_news,
|
579 |
+
inputs=[
|
580 |
+
sports_news_type,
|
581 |
+
sports_language,
|
582 |
+
sports_limit
|
583 |
+
],
|
584 |
+
outputs=[sports_content_output, sports_status]
|
585 |
+
)
|
586 |
+
|
587 |
+
# Hàm chuyển nội dung tin thể thao sang tab TTS
|
588 |
+
def transfer_sports_to_tts(sports_content):
|
589 |
+
"""Chuyển nội dung tin thể thao sang tab TTS"""
|
590 |
+
if not sports_content or sports_content.strip() == "":
|
591 |
+
return "Vui lòng tạo tin thể thao trước!", gr.update(selected="tts_tab")
|
592 |
+
return sports_content, gr.update(selected="tts_tab")
|
593 |
+
|
594 |
+
use_sports_for_tts_btn.click(
|
595 |
+
transfer_sports_to_tts,
|
596 |
+
inputs=[sports_content_output],
|
597 |
+
outputs=[input_text_gr, tabs]
|
598 |
+
)
|
599 |
|
600 |
+
# Khởi chạy ứng dụng
|
601 |
+
if __name__ == "__main__":
|
602 |
+
demo.queue()
|
603 |
+
demo.launch(
|
604 |
+
debug=True,
|
605 |
+
show_api=True,
|
606 |
+
share=True,
|
607 |
+
server_name="0.0.0.0",
|
608 |
+
server_port=7860,
|
609 |
+
favicon_path=None,
|
610 |
+
ssl_verify=False
|
611 |
+
)
|