Urdu_Voiceover / app.py
EngrMuhammadBilal's picture
Update app.py
98d243e verified
# --- Fix Streamlit permission issue BEFORE importing streamlit ---
import os
# Put Streamlit state/config under /tmp (writeable on Spaces)
os.environ.setdefault("STREAMLIT_HOME", "/tmp/streamlit")
os.environ.setdefault("XDG_STATE_HOME", "/tmp")
os.environ.setdefault("XDG_CONFIG_HOME", "/tmp")
os.makedirs(os.environ["STREAMLIT_HOME"], exist_ok=True)
# Disable telemetry to avoid writes under root paths
os.environ.setdefault("STREAMLIT_BROWSER_GATHER_USAGE_STATS", "false")
from pathlib import Path
from datetime import datetime
import streamlit as st
from openai import OpenAI
st.set_page_config(page_title="Urdu TTS - OpenAI", page_icon="🔊", layout="centered")
st.title("🔊 Urdu Text → Speech (OpenAI)")
st.caption("Type Urdu text and generate natural Urdu speech with OpenAI TTS. Use a custom voice_id if your account has Voice access.")
# ---- Get API key (your secret name is Key_1). Fallback to manual entry. ----
API_KEY = os.getenv("Key_1") or st.secrets.get("Key_1")
with st.sidebar:
st.header("API")
if not API_KEY:
st.warning("Secret `Key_1` not found. Paste your key temporarily (will not be saved to repo).")
API_KEY = st.text_input("OpenAI API key (sk-...)", type="password")
if not API_KEY:
st.stop()
client = OpenAI(api_key=API_KEY)
# ---- Sidebar options ----
with st.sidebar:
st.header("Options")
builtin_voices = ["alloy", "verse", "aria", "ballad", "cove", "luna", "sage"]
use_custom = st.checkbox("Use custom OpenAI voice_id", False)
custom_voice = st.text_input("Custom voice_id", value="", help="Requires access to custom voices") if use_custom else ""
preset_voice = st.selectbox("Built-in voice", builtin_voices, index=0) if not use_custom else None
out_name = st.text_input("Output filename (no extension)", "urdu_tts")
fmt = st.selectbox("Audio format", options=["mp3", "wav"], index=0)
# ---- Input ----
default_text = "یہ ایک سادہ مثال ہے۔ یہاں اپنا متن لکھیں اور آڈیو حاصل کریں۔"
text = st.text_area("Urdu text", value=default_text, height=200, placeholder="یہاں اردو میں ٹیکسٹ لکھیں یا پیسٹ کریں…")
col1, col2 = st.columns(2)
with col1:
make_audio = st.button("🎙️ Generate", use_container_width=True)
with col2:
clear_btn = st.button("🧹 Clear", use_container_width=True)
if clear_btn:
st.session_state.pop("audio_bytes", None)
st.session_state.pop("ext", None)
st.experimental_rerun()
# ---- TTS helper ----
def synth_openai(urdu_text: str, voice: str, audio_format: str):
model = "gpt-4o-mini-tts"
ext = "mp3" if audio_format == "mp3" else "wav"
tmp_path = Path(f"/tmp/tts_{datetime.now().strftime('%H%M%S')}.{ext}")
# Stream to file to avoid loading all in memory
with client.audio.speech.with_streaming_response.create(
model=model,
voice=voice,
input=urdu_text,
format=("mp3" if audio_format == "mp3" else "wav"),
) as resp:
resp.stream_to_file(tmp_path)
data = tmp_path.read_bytes()
try:
tmp_path.unlink(missing_ok=True)
except Exception:
pass
return data, ext
# ---- Generate ----
if make_audio:
if not text.strip():
st.warning("براہ کرم اردو متن درج کریں")
else:
try:
voice_to_use = (custom_voice.strip() if use_custom else preset_voice)
if not voice_to_use:
st.warning("Please choose a built-in voice or provide a custom voice_id.")
else:
st.info("Generating Urdu speech with OpenAI TTS…")
audio_bytes, ext = synth_openai(text.strip(), voice_to_use, fmt)
st.session_state["audio_bytes"] = audio_bytes
st.session_state["ext"] = ext
st.success("آڈیو تیار ہے")
except Exception as e:
st.error(f"کچھ مسئلہ آیا: {e}")
# ---- Preview & Download ----
if "audio_bytes" in st.session_state:
ext = st.session_state.get("ext", "mp3")
st.markdown("### ▶️ Preview")
st.audio(st.session_state["audio_bytes"], format=f"audio/{'mpeg' if ext=='mp3' else 'wav'}")
fname = f"{(out_name or 'urdu_tts').strip()}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.{ext}"
st.download_button(
"⬇️ Download",
data=st.session_state["audio_bytes"],
file_name=fname,
mime=("audio/mpeg" if ext == "mp3" else "audio/wav"),
use_container_width=True,
)
st.markdown("---")
st.caption("If your secret is named `Key_1`, keep it in Settings → Variables and secrets → Secrets. "
"This app stores Streamlit state under /tmp to avoid permission issues on Spaces.")