# 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()