TourGuilde / streamlit_app.py
buitu0's picture
Upload 2 files
5247d13 verified
Raw
History Blame Contribute Delete
4.71 kB
# pyrefly: ignore [missing-import]
import streamlit as st
import os
import hashlib
from manager import generate_tour_script
from tts import generate_audio
st.set_page_config(page_title="AI Audio Tour", page_icon="🎧", layout="centered")
def get_cache_key(location, interests, duration, voice_style):
data = f"{location}_{interests}_{duration}_{voice_style}".lower().encode('utf-8')
return hashlib.md5(data).hexdigest()
def main():
st.title("🎧 Hướng dẫn viên AI Audio Tour")
st.write("Khám phá các địa danh với hướng dẫn viên AI cá nhân hóa.")
# Sidebar
st.sidebar.header("Cài đặt")
api_key_input = st.sidebar.text_input("Gemini API Key", type="password", help="Lấy từ Google AI Studio")
# Save API key to session state
if api_key_input:
st.session_state["api_key"] = api_key_input
st.sidebar.success("Đã lưu API Key tạm thời.")
api_key = st.session_state.get("api_key") or os.environ.get("GEMINI_API_KEY")
voice_style = st.sidebar.selectbox("Giọng đọc", ["Nữ (Tiếng Việt)", "Nam (Tiếng Việt)", "English (Female)", "English (Male)"])
# Main content
location = st.text_input("Địa danh (Location)", placeholder="Ví dụ: Hội An, Đà Lạt, Hồ Gươm...")
interests_list = st.multiselect(
"Chủ đề quan tâm (Interests)",
options=["Lịch sử (History)", "Văn hóa (Culture)", "Ẩm thực (Culinary)", "Kiến trúc (Architecture)"],
default=["Lịch sử (History)", "Văn hóa (Culture)"]
)
interests = ", ".join(interests_list)
duration = st.slider("Thời lượng dự kiến (phút)", min_value=5, max_value=60, value=15, step=5)
if st.button("Tạo Audio Tour", type="primary"):
if not location:
st.warning("Vui lòng nhập Địa danh!")
return
if not api_key:
st.warning("Vui lòng nhập Gemini API Key ở thanh bên (Sidebar)!")
return
cache_key = get_cache_key(location, interests, duration, voice_style)
cache_dir = "cache"
os.makedirs(cache_dir, exist_ok=True)
script_file = os.path.join(cache_dir, f"{cache_key}.txt")
audio_file = os.path.join(cache_dir, f"{cache_key}.mp3")
# Check cache
if os.path.exists(script_file) and os.path.exists(audio_file):
st.success("Tải từ bộ nhớ đệm (Cache) thành công! Không tốn quota API.")
with open(script_file, "r", encoding="utf-8") as f:
final_script = f.read()
st.audio(audio_file, format="audio/mp3")
with open(audio_file, "rb") as f:
st.download_button(
label="Tải file âm thanh (.mp3)",
data=f,
file_name=f"AudioTour_{location}.mp3",
mime="audio/mp3"
)
st.markdown("### Kịch bản Tour")
with st.container(height=300):
st.write(final_script)
return
# Not in cache, generate fresh
try:
with st.spinner("Đang lên kế hoạch và thu thập thông tin từ các chuyên gia (Quá trình này có thể mất 1-2 phút)..."):
final_script = generate_tour_script(api_key, location, interests, duration)
with st.spinner("Đang chuyển đổi văn bản thành giọng nói..."):
success = generate_audio(final_script, voice_style, audio_file)
if success:
# Save script to cache
with open(script_file, "w", encoding="utf-8") as f:
f.write(final_script)
st.success("Hoàn thành! Chúc bạn có một chuyến đi vui vẻ.")
st.audio(audio_file, format="audio/mp3")
with open(audio_file, "rb") as f:
st.download_button(
label="Tải file âm thanh (.mp3)",
data=f,
file_name=f"AudioTour_{location}.mp3",
mime="audio/mp3"
)
st.markdown("### Kịch bản Tour")
with st.container(height=300):
st.write(final_script)
else:
st.error("Có lỗi xảy ra trong quá trình tạo Audio.")
except Exception as e:
st.error(f"Đã xảy ra lỗi: {e}")
if __name__ == "__main__":
main()