import asyncio import mimetypes import os import tempfile import fitz # PyMuPDF import random import gradio as gr from docx import Document from content_generation import create_content, CONTENT_TYPES from openai import OpenAI from gradio_client import Client, handle_file import subprocess # Khởi tạo client OpenAI với API key từ biến môi trường client_openai = OpenAI(api_key=os.environ.get('OPENAI_API_KEY')) client_vixtts = Client("thinhlpg/vixtts-demo") def create_docx(content, output_path): """ Tạo file docx từ nội dung. """ doc = Document() doc.add_paragraph(content) doc.save(output_path) def process_pdf(file_path): """ Xử lý file PDF và trích xuất nội dung. """ doc = fitz.open(file_path) text = "" for page in doc: text += page.get_text() return text def process_docx(file_path): """ Xử lý file DOCX và trích xuất nội dung. """ doc = Document(file_path) text = "" for para in doc.paragraphs: text += para.text return text def convert_text_to_speech(text, language='vi'): """ Chuyển đổi văn bản thành giọng nói. """ result = client_vixtts.predict( prompt=text, language=language, audio_file_pth=handle_file(''), normalize_text=True, api_name="/predict" ) return result.audio_file_pth def create_video(audio_file, mc_choice, text_color, output_video="output.mp4"): """ Tạo video với người MC dẫn chương trình. """ # Chọn file video nền dựa trên lựa chọn MC background_videos = { "MC1": "mc1_background.mp4", "MC2": "mc2_background.mp4", "MC3": "mc3_background.mp4", "MC4": "mc4_background.mp4" } background_video = background_videos.get(mc_choice, "mc1_background.mp4") # Mặc định là MC1 nếu không tìm thấy # Định nghĩa văn bản trên video text_on_video = f"MC: {mc_choice}" # Định nghĩa màu sắc chữ color_map = { "Trắng": "white", "Đỏ": "red", "Xanh dương": "blue", "Xanh lá": "green", "Vàng": "yellow" } font_color = color_map.get(text_color, "white") # Mặc định là trắng nếu không tìm thấy # Lệnh ffmpeg để tạo video command = [ "ffmpeg", "-stream_loop", "-1", # Lặp lại video nền vô hạn "-i", background_video, # Video nền (tùy thuộc vào MC) "-i", audio_file, # File audio đầu vào "-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:boxcolor=black@0.5:boxborderw=5", # Văn bản trên video "-t", "45.7", # Thời lượng video "-c:v", "libx264", # Codec video "-c:a", "aac", # Codec audio "-shortest", # Dừng khi audio kết thúc "-y", # Ghi đè file nếu tồn tại output_video # File video đầu ra ] # Chạy lệnh ffmpeg subprocess.run(command, check=True) return output_video def interface(): with gr.Blocks() as app: gr.Markdown("# Ứng dụng Tạo Nội dung và Video") with gr.Tab("Tạo Nội dung"): with gr.Row(): with gr.Column(): prompt = gr.Textbox(label="Nhập yêu cầu nội dung") file_upload = gr.File(label="Tải lên file kèm theo", type="filepath") content_type = gr.Radio(label="Chọn loại nội dung", choices=CONTENT_TYPES, value=None) # Giá trị mặc định là không có gì được chọn content_button = gr.Button("Tạo Nội dung") with gr.Column(): content_output = gr.Textbox(label="Nội dung tạo ra", interactive=True) use_generated_text = gr.Checkbox(label="Sử dụng văn bản được tạo bởi LLM", value=True) manual_text_input = gr.Textbox(label="Nhập văn bản thủ công", visible=False) language = gr.Dropdown(label="Chọn ngôn ngữ", choices=["vi", "en"], value="vi") mc_choice = gr.Dropdown(label="Chọn MC", choices=["MC1", "MC2", "MC3", "MC4"], value="MC1") text_color = gr.Dropdown(label="Chọn màu chữ", choices=["Trắng", "Đỏ", "Xanh dương", "Xanh lá", "Vàng"], value="Trắng") confirm_button = gr.Button("Xác nhận nội dung") download_docx = gr.File(label="Tải xuống file DOCX", interactive=False) download_audio = gr.File(label="Tải xuống file âm thanh", interactive=False) download_video = gr.File(label="Tải xuống file video", interactive=False) status_message = gr.Label(label="Trạng thái") def toggle_manual_text(use_generated_text): return not use_generated_text def generate_content(prompt, file, content_type): try: status = "Đang xử lý..." if file and os.path.exists(file): mime_type, _ = mimetypes.guess_type(file) if mime_type == "application/pdf": file_content = process_pdf(file) prompt = f"{prompt}\n\nDưới đây là nội dung của file tài liệu:\n\n{file_content}" elif mime_type in ( "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/msword"): file_content = process_docx(file) prompt = f"{prompt}\n\nDưới đây là nội dung của file tài liệu:\n\n{file_content}" else: raise ValueError("Định dạng file không được hỗ trợ.") if not content_type: raise ValueError("Vui lòng chọn một loại nội dung") script_content = create_content(prompt, content_type, "Tiếng Việt") docx_path = "script.docx" create_docx(script_content, docx_path) status = "Đã tạo nội dung thành công!" return script_content, docx_path, True, None, status except Exception as e: status = f"Đã xảy ra lỗi: {str(e)}" return "", None, True, None, status async def confirm_content(content_output, use_generated_text, manual_text_input, language, mc_choice, text_color): if use_generated_text: text_to_convert = content_output else: text_to_convert = manual_text_input if not text_to_convert: return None, None, None, "Vui lòng cung cấp văn bản để chuyển đổi." docx_path = "script.docx" create_docx(text_to_convert, docx_path) audio_path = convert_text_to_speech(text_to_convert, language) video_path = create_video(audio_path, mc_choice, text_color) return docx_path, audio_path, video_path, "Đã xác nhận và tạo video thành công!" use_generated_text.change(toggle_manual_text, inputs=[use_generated_text], outputs=[manual_text_input.visible]) content_button.click(generate_content, inputs=[prompt, file_upload, content_type], outputs=[content_output, download_docx, use_generated_text, manual_text_input, status_message]) confirm_button.click(confirm_content, inputs=[content_output, use_generated_text, manual_text_input, language, mc_choice, text_color], outputs=[download_docx, download_audio, download_video, status_message]) return app # Khởi chạy ứng dụng if __name__ == "__main__": app = interface() app.launch(share=True)