TTS-samples / src /streamlit_app.py
Luigi's picture
clean layout
be99f64
import os
# Fix Streamlit permission issues by redirecting HOME and XDG_CONFIG_HOME to writable path
cwd = os.getcwd()
os.environ.setdefault('XDG_CONFIG_HOME', cwd)
os.environ.setdefault('HOME', cwd)
import streamlit as st
from pathlib import Path
# Determine BASE_DIR relative to this script's location
SCRIPT_DIR = Path(__file__).resolve().parent
# Assuming project structure: project_root/src/streamlit_app.py and project_root/tts_smaples
BASE_DIR = SCRIPT_DIR.parent / "tts_smaples"
@st.cache_data
def get_providers_and_voices(base_dir: Path):
"""
Scan the base_dir for subfolders (providers) and .wav files under each.
Returns a dict: { provider_name: [voice_filename1.wav, ...], ... }
"""
providers = {}
if not base_dir.is_dir():
return providers
for provider in sorted([p for p in base_dir.iterdir() if p.is_dir()]):
voices = sorted([f.name for f in provider.iterdir() if f.is_file() and f.suffix.lower() == ".wav"] )
if voices:
providers[provider.name] = voices
return providers
# Main app
def main():
# Configure page for better mobile experience
st.set_page_config(page_title="TTS 範例播放器", layout="wide")
st.title("🎵 TTS 範例播放器")
# Short introduction for non-tech users
st.markdown(
"""
**此範例示範 TTS 播放以下句子:
> 八和和牛燒肉專門店。沒有將就,只有講究!
請在側邊欄選擇 TTS 提供者與語音,然後播放範例音檔。
"""
)
providers = get_providers_and_voices(BASE_DIR)
if not providers:
st.warning(f"未找到任何 TTS 提供者資料夾 `{BASE_DIR}`,請確認資料夾存在,且包含 .wav 檔案。")
parent = BASE_DIR.parent
if parent.exists():
st.info(f"上層資料夾內容 `{parent}`: {sorted([p.name for p in parent.iterdir()])}")
return
# Sidebar for selection
st.sidebar.header("選擇 TTS 範例")
provider_list = sorted(providers.keys())
provider = st.sidebar.selectbox("提供者", options=provider_list)
voices = providers.get(provider, [])
if not voices:
st.sidebar.info(f"提供者 `{provider}` 底下沒有 .wav 檔案。")
return
voice = st.sidebar.selectbox("語音", options=voices)
# Main area shows single playback
st.markdown(f"### 播放中:**{provider} / {voice}**")
file_path = BASE_DIR / provider / voice
if file_path.is_file():
try:
audio_bytes = file_path.read_bytes()
st.audio(audio_bytes, format="audio/wav")
except Exception as e:
st.error(f"載入音訊時出錯: {e}")
else:
st.error(f"找不到檔案: `{file_path}`")
if __name__ == "__main__":
main()