File size: 5,881 Bytes
e62cec6
 
 
 
 
 
 
 
 
 
 
 
 
58e96a5
e62cec6
58e96a5
4fdaf10
 
 
e62cec6
 
 
 
6273f21
 
e62cec6
 
 
 
 
 
 
 
 
 
 
9973c8b
 
 
e62cec6
9973c8b
 
 
 
 
 
5997829
 
9973c8b
e62cec6
 
 
 
 
 
6273f21
e62cec6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import asyncio

try:
    asyncio.get_running_loop()
except RuntimeError:
    asyncio.run(asyncio.sleep(0))  # Ensures an event loop is created before Streamlit starts

import streamlit as st
from main import main
import os
import subprocess
from huggingface_hub import InferenceClient
import google.generativeai as genai
from dotenv import load_dotenv

load_dotenv()
# Load API Keys từ biến môi trường
HF_TOKEN = os.getenv("HF_TOKEN")  # Hugging Face API Key
GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")  # Google API Key
genai.configure(api_key=GOOGLE_API_KEY)
client = InferenceClient(provider="hf-inference", api_key=HF_TOKEN)

# Định nghĩa đường dẫn video đầu ra
OUTPUT_VIDEO_PATH = "final_output.mp4"
OUTPUT_VIDEO_FIXED_PATH = "final_output_fixed.mp4"

# Tiêu đề ứng dụng
st.set_page_config(page_title="KnowFlow", page_icon="📖")
st.markdown("<h1 style='text-align: center;'>📖 KnowFlow 🌊</h1>", unsafe_allow_html=True)
st.markdown("<h4 style='text-align: center;'>Convert documents into videos with AI-powered storytelling</h4>", unsafe_allow_html=True)

# Thông tin tác giả
st.markdown("---")
st.markdown("👨‍💻 **Author:** Nguyễn Trung Hiếu")
st.markdown("🔗 [GitHub Repository](https://github.com/hieunguyen-cyber/KnowFlow.git)")
st.markdown("---")
st.markdown("""
## 🎯 Purpose  
KnowFlow automates the process of converting lecture documents (PDF, DOCX) into narrated videos with structured explanations. It extracts text, formulas, and images, generates explanations, converts text to speech, and assembles everything into a video.  

## 🛠️ How to Use  
1️⃣ **Upload a lecture file (PDF, DOCX)**.  
2️⃣ **Select processing options** (text extraction, summarization, TTS).  
3️⃣ **Generate the video** – the system will process and compile it.  
4️⃣ **Download the final video** for review or sharing.  

🚀 Fully open-source and free to use! \n
If you find it's slow, then another person must be using the GPU. Please wait!!
""")
# Upload file PDF
uploaded_file = st.file_uploader("📂 Upload your document (PDF)", type=["pdf","docx"])

# Nếu có file, lưu vào thư mục tạm và lấy đường dẫn
file_path = None
if uploaded_file:
    file_path = f"{uploaded_file.name}"
    with open(file_path, "wb") as f:
        f.write(uploaded_file.getbuffer())  # Lưu file thực tế
number_of_images = st.slider("🖼️ Nhập số ảnh",1,10,3)
# Cấu hình đầu vào
gender = st.radio("🗣️ Select Voice Gender", options=["female", "male"])

# Nếu chọn giọng nam, vô hiệu hóa tốc độ (chỉ cho phép "normal")
if gender == "male":
    speed = st.radio("⚡ Speech Speed (Male voice supports only normal)", options=["normal"], disabled=True)
else:
    speed = st.radio("⚡ Speech Speed", options=["fast", "normal", "slow"])
analysis_level = st.radio("Analysis Level", options=["basic", "detailed"])
writting_style = st.radio("Writting Style", options  = ["academic","popular","creative","humorous"])

# Tạo thanh trượt với giá trị từ 50 đến 250, bước nhảy 50
word_lower_limit, word_upper_limit = st.slider(
    "Chọn khoảng độ dài văn bản:",
    min_value=50,
    max_value=250,
    value=(50, 250),  # Giá trị mặc định
    step=50
)

st.write(f"Giới hạn độ dài văn bản từ **{word_lower_limit}** đến **{word_upper_limit}** ký tự.")
detail_level = st.radio("📖 Detail Level of Image Description", options=["short", "detailed"])
perspective = st.radio("🔎 Perspective", options=["subjective", "neutral"])
emotion = st.text_input("🎭 Emotion", placeholder="Example: mysterious, romantic,...")
time_setting = st.text_input("⏳ Time Setting", placeholder="Example: modern, medieval,...")
art_style = st.text_input("🖌️ Image Description Style", placeholder="Example: realistic, abstract,...")
style = st.text_input("🎨 Image Style", placeholder="Example: realistic, anime,...")
color_palette = st.text_input("🌈 Color Palette", placeholder="Example: vibrant, monochrome,...")

def convert_audio_format(video_input, video_output):
    """Chuyển đổi định dạng âm thanh của video sang AAC."""
    if not os.path.exists(video_input):
        raise FileNotFoundError(f"File '{video_input}' không tồn tại!")

    command = [
        "ffmpeg", "-i", video_input,  
        "-c:v", "copy", "-c:a", "aac", "-b:a", "192k",
        "-y",  # Ghi đè nếu file output đã tồn tại
        video_output
    ]
    
    try:
        subprocess.run(command, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        print(f"✅ Chuyển đổi thành công: {video_output}")
    except subprocess.CalledProcessError as e:
        print(f"❌ Lỗi khi chuyển đổi video: {e.stderr.decode()}")

# Nút chạy pipeline
if st.button("🚀 Generate Video"):
    if file_path and os.path.exists(file_path):
        st.success("⏳ Processing started...")
        main(file_path, analysis_level, writting_style, word_lower_limit, word_upper_limit, gender, speed, number_of_images, detail_level, perspective, emotion, time_setting, art_style, style, color_palette)

        # Kiểm tra xem video đã được tạo chưa
        if os.path.exists(OUTPUT_VIDEO_PATH):
            st.success("🎉 Video generated successfully!")
            
            # Chuyển đổi định dạng âm thanh
            convert_audio_format(OUTPUT_VIDEO_PATH, OUTPUT_VIDEO_FIXED_PATH)

            # Tạo link tải về
            with open(OUTPUT_VIDEO_FIXED_PATH, "rb") as video_file:
                st.download_button(label="📥 Download Video", data=video_file, file_name="final_output_fixed.mp4", mime="video/mp4")
        else:
            st.error("⚠️ Video generation failed. Please check the logs.")
    else:
        st.error("⚠️ Please upload a valid PDF file.")