Update app.py
Browse files
app.py
CHANGED
@@ -2,16 +2,18 @@ import asyncio
|
|
2 |
import mimetypes
|
3 |
import os
|
4 |
import tempfile
|
5 |
-
import glob
|
6 |
import fitz # PyMuPDF
|
7 |
import random
|
8 |
import gradio as gr
|
9 |
from docx import Document
|
10 |
from content_generation import create_content, CONTENT_TYPES
|
11 |
from openai import OpenAI
|
|
|
|
|
12 |
|
13 |
# Khởi tạo client OpenAI với API key từ biến môi trường
|
14 |
-
|
|
|
15 |
|
16 |
def create_docx(content, output_path):
|
17 |
"""
|
@@ -41,10 +43,66 @@ def process_docx(file_path):
|
|
41 |
text += para.text
|
42 |
return text
|
43 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
def interface():
|
45 |
with gr.Blocks() as app:
|
46 |
gr.Markdown("# Ứng dụng Tạo Nội dung và Video")
|
47 |
-
|
48 |
with gr.Tab("Tạo Nội dung"):
|
49 |
with gr.Row():
|
50 |
with gr.Column():
|
@@ -57,10 +115,20 @@ def interface():
|
|
57 |
|
58 |
with gr.Column():
|
59 |
content_output = gr.Textbox(label="Nội dung tạo ra", interactive=True)
|
|
|
|
|
|
|
|
|
|
|
60 |
confirm_button = gr.Button("Xác nhận nội dung")
|
61 |
download_docx = gr.File(label="Tải xuống file DOCX", interactive=False)
|
|
|
|
|
62 |
status_message = gr.Label(label="Trạng thái")
|
63 |
-
|
|
|
|
|
|
|
64 |
def generate_content(prompt, file, content_type):
|
65 |
try:
|
66 |
status = "Đang xử lý..."
|
@@ -76,32 +144,43 @@ def interface():
|
|
76 |
prompt = f"{prompt}\n\nDưới đây là nội dung của file tài liệu:\n\n{file_content}"
|
77 |
else:
|
78 |
raise ValueError("Định dạng file không được hỗ trợ.")
|
79 |
-
|
80 |
if not content_type:
|
81 |
raise ValueError("Vui lòng chọn một loại nội dung")
|
82 |
-
|
83 |
script_content = create_content(prompt, content_type, "Tiếng Việt")
|
84 |
docx_path = "script.docx"
|
85 |
create_docx(script_content, docx_path)
|
86 |
-
|
87 |
status = "Đã tạo nội dung thành công!"
|
88 |
-
return script_content, docx_path, status
|
89 |
except Exception as e:
|
90 |
status = f"Đã xảy ra lỗi: {str(e)}"
|
91 |
-
return "", None, status
|
92 |
-
|
93 |
-
async def confirm_content(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
docx_path = "script.docx"
|
95 |
-
create_docx(
|
96 |
-
|
|
|
|
|
|
|
|
|
97 |
content_button.click(generate_content,
|
98 |
inputs=[prompt, file_upload, content_type],
|
99 |
-
outputs=[content_output, download_docx, status_message])
|
100 |
-
|
|
|
|
|
|
|
|
|
101 |
return app
|
102 |
|
103 |
-
|
104 |
-
|
105 |
# Khởi chạy ứng dụng
|
106 |
if __name__ == "__main__":
|
107 |
app = interface()
|
|
|
2 |
import mimetypes
|
3 |
import os
|
4 |
import tempfile
|
|
|
5 |
import fitz # PyMuPDF
|
6 |
import random
|
7 |
import gradio as gr
|
8 |
from docx import Document
|
9 |
from content_generation import create_content, CONTENT_TYPES
|
10 |
from openai import OpenAI
|
11 |
+
from gradio_client import Client, handle_file
|
12 |
+
import subprocess
|
13 |
|
14 |
# Khởi tạo client OpenAI với API key từ biến môi trường
|
15 |
+
client_openai = OpenAI(api_key=os.environ.get('OPENAI_API_KEY'))
|
16 |
+
client_vixtts = Client("thinhlpg/vixtts-demo")
|
17 |
|
18 |
def create_docx(content, output_path):
|
19 |
"""
|
|
|
43 |
text += para.text
|
44 |
return text
|
45 |
|
46 |
+
def convert_text_to_speech(text, language='vi'):
|
47 |
+
"""
|
48 |
+
Chuyển đổi văn bản thành giọng nói.
|
49 |
+
"""
|
50 |
+
result = client_vixtts.predict(
|
51 |
+
prompt=text,
|
52 |
+
language=language,
|
53 |
+
audio_file_pth=handle_file(''),
|
54 |
+
normalize_text=True,
|
55 |
+
api_name="/predict"
|
56 |
+
)
|
57 |
+
return result.audio_file_pth
|
58 |
+
|
59 |
+
def create_video(audio_file, mc_choice, text_color, output_video="output.mp4"):
|
60 |
+
"""
|
61 |
+
Tạo video với người MC dẫn chương trình.
|
62 |
+
"""
|
63 |
+
# Chọn file video nền dựa trên lựa chọn MC
|
64 |
+
background_videos = {
|
65 |
+
"MC1": "mc1_background.mp4",
|
66 |
+
"MC2": "mc2_background.mp4",
|
67 |
+
"MC3": "mc3_background.mp4",
|
68 |
+
"MC4": "mc4_background.mp4"
|
69 |
+
}
|
70 |
+
background_video = background_videos.get(mc_choice, "mc1_background.mp4") # Mặc định là MC1 nếu không tìm thấy
|
71 |
+
|
72 |
+
# Định nghĩa văn bản trên video
|
73 |
+
text_on_video = f"MC: {mc_choice}"
|
74 |
+
|
75 |
+
# Định nghĩa màu sắc chữ
|
76 |
+
color_map = {
|
77 |
+
"Trắng": "white",
|
78 |
+
"Đỏ": "red",
|
79 |
+
"Xanh dương": "blue",
|
80 |
+
"Xanh lá": "green",
|
81 |
+
"Vàng": "yellow"
|
82 |
+
}
|
83 |
+
font_color = color_map.get(text_color, "white") # Mặc định là trắng nếu không tìm thấy
|
84 |
+
|
85 |
+
# Lệnh ffmpeg để tạo video
|
86 |
+
command = [
|
87 |
+
"ffmpeg",
|
88 |
+
"-stream_loop", "-1", # Lặp lại video nền vô hạn
|
89 |
+
"-i", background_video, # Video nền (tùy thuộc vào MC)
|
90 |
+
"-i", audio_file, # File audio đầu vào
|
91 |
+
"-vf", f"drawtext=text='{text_on_video}':fontcolor={font_color}:fontsize=50:fontfile=/path/to/font.ttf:x=(w-text_w)/2:y=10:box=1:[email protected]:boxborderw=5", # Văn bản trên video
|
92 |
+
"-t", "45.7", # Thời lượng video
|
93 |
+
"-c:v", "libx264", # Codec video
|
94 |
+
"-c:a", "aac", # Codec audio
|
95 |
+
"-shortest", # Dừng khi audio kết thúc
|
96 |
+
"-y", # Ghi đè file nếu tồn tại
|
97 |
+
output_video # File video đầu ra
|
98 |
+
]
|
99 |
+
# Chạy lệnh ffmpeg
|
100 |
+
subprocess.run(command, check=True)
|
101 |
+
return output_video
|
102 |
+
|
103 |
def interface():
|
104 |
with gr.Blocks() as app:
|
105 |
gr.Markdown("# Ứng dụng Tạo Nội dung và Video")
|
|
|
106 |
with gr.Tab("Tạo Nội dung"):
|
107 |
with gr.Row():
|
108 |
with gr.Column():
|
|
|
115 |
|
116 |
with gr.Column():
|
117 |
content_output = gr.Textbox(label="Nội dung tạo ra", interactive=True)
|
118 |
+
use_generated_text = gr.Checkbox(label="Sử dụng văn bản được tạo bởi LLM", value=True)
|
119 |
+
manual_text_input = gr.Textbox(label="Nhập văn bản thủ công", visible=False)
|
120 |
+
language = gr.Dropdown(label="Chọn ngôn ngữ", choices=["vi", "en"], value="vi")
|
121 |
+
mc_choice = gr.Dropdown(label="Chọn MC", choices=["MC1", "MC2", "MC3", "MC4"], value="MC1")
|
122 |
+
text_color = gr.Dropdown(label="Chọn màu chữ", choices=["Trắng", "Đỏ", "Xanh dương", "Xanh lá", "Vàng"], value="Trắng")
|
123 |
confirm_button = gr.Button("Xác nhận nội dung")
|
124 |
download_docx = gr.File(label="Tải xuống file DOCX", interactive=False)
|
125 |
+
download_audio = gr.File(label="Tải xuống file âm thanh", interactive=False)
|
126 |
+
download_video = gr.File(label="Tải xuống file video", interactive=False)
|
127 |
status_message = gr.Label(label="Trạng thái")
|
128 |
+
|
129 |
+
def toggle_manual_text(use_generated_text):
|
130 |
+
return not use_generated_text
|
131 |
+
|
132 |
def generate_content(prompt, file, content_type):
|
133 |
try:
|
134 |
status = "Đang xử lý..."
|
|
|
144 |
prompt = f"{prompt}\n\nDưới đây là nội dung của file tài liệu:\n\n{file_content}"
|
145 |
else:
|
146 |
raise ValueError("Định dạng file không được hỗ trợ.")
|
|
|
147 |
if not content_type:
|
148 |
raise ValueError("Vui lòng chọn một loại nội dung")
|
|
|
149 |
script_content = create_content(prompt, content_type, "Tiếng Việt")
|
150 |
docx_path = "script.docx"
|
151 |
create_docx(script_content, docx_path)
|
|
|
152 |
status = "Đã tạo nội dung thành công!"
|
153 |
+
return script_content, docx_path, True, None, status
|
154 |
except Exception as e:
|
155 |
status = f"Đã xảy ra lỗi: {str(e)}"
|
156 |
+
return "", None, True, None, status
|
157 |
+
|
158 |
+
async def confirm_content(content_output, use_generated_text, manual_text_input, language, mc_choice, text_color):
|
159 |
+
if use_generated_text:
|
160 |
+
text_to_convert = content_output
|
161 |
+
else:
|
162 |
+
text_to_convert = manual_text_input
|
163 |
+
|
164 |
+
if not text_to_convert:
|
165 |
+
return None, None, None, "Vui lòng cung cấp văn bản để chuyển đổi."
|
166 |
+
|
167 |
docx_path = "script.docx"
|
168 |
+
create_docx(text_to_convert, docx_path)
|
169 |
+
audio_path = convert_text_to_speech(text_to_convert, language)
|
170 |
+
video_path = create_video(audio_path, mc_choice, text_color)
|
171 |
+
return docx_path, audio_path, video_path, "Đã xác nhận và tạo video thành công!"
|
172 |
+
|
173 |
+
use_generated_text.change(toggle_manual_text, inputs=[use_generated_text], outputs=[manual_text_input.visible])
|
174 |
content_button.click(generate_content,
|
175 |
inputs=[prompt, file_upload, content_type],
|
176 |
+
outputs=[content_output, download_docx, use_generated_text, manual_text_input, status_message])
|
177 |
+
|
178 |
+
confirm_button.click(confirm_content,
|
179 |
+
inputs=[content_output, use_generated_text, manual_text_input, language, mc_choice, text_color],
|
180 |
+
outputs=[download_docx, download_audio, download_video, status_message])
|
181 |
+
|
182 |
return app
|
183 |
|
|
|
|
|
184 |
# Khởi chạy ứng dụng
|
185 |
if __name__ == "__main__":
|
186 |
app = interface()
|