| | |
| | import os |
| |
|
| | |
| | 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) |
| |
|
| | |
| | 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.") |
| |
|
| | |
| | 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) |
| |
|
| | |
| | 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) |
| |
|
| | |
| | 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() |
| |
|
| | |
| | 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}") |
| | |
| | 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 |
| |
|
| | |
| | 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}") |
| |
|
| | |
| | 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.") |
| |
|