Spaces:
Paused
Paused
Download app.py from matrixcoder/tts-api: direct link, hf CLI and curl.
- Browser
- Download file 2.71 kB
-
https://huggingface.co/spaces/matrixcoder/tts-api/resolve/main/app.py
- Command line
-
hf download hf://spaces/matrixcoder/tts-api/app.py
-
curl -L -o app.py https://huggingface.co/spaces/matrixcoder/tts-api/resolve/main/app.py
2.71 kB
| """ | |
| ESP32 TTS Server — Hugging Face Space | |
| WAV output: 22050Hz, Mono, 8-bit unsigned | |
| ESP32 DAC ke liye perfect — direct mapping, no conversion | |
| """ | |
| from flask import Flask, request, Response | |
| import os | |
| import io | |
| import hashlib | |
| from gtts import gTTS | |
| from pydub import AudioSegment | |
| from pydub.effects import normalize | |
| app = Flask(__name__) | |
| BASE_DIR = os.path.dirname(os.path.abspath(__file__)) | |
| CACHE_DIR = os.path.join(BASE_DIR, "tts_cache") | |
| os.makedirs(CACHE_DIR, exist_ok=True) | |
| def text_to_wav_bytes(text, lang): | |
| # Step 1: gTTS → MP3 in memory | |
| mp3_buf = io.BytesIO() | |
| tts = gTTS(text, lang=lang) | |
| tts.write_to_fp(mp3_buf) | |
| mp3_buf.seek(0) | |
| # Step 2: Load audio | |
| audio = AudioSegment.from_file(mp3_buf, format="mp3") | |
| # Step 3: Normalize — consistent volume | |
| audio = normalize(audio) | |
| # Step 4: Convert — 22050Hz, Mono, 8-bit unsigned | |
| # ESP32 DAC = 8-bit (0-255), 22050Hz enough for clear voice | |
| audio = audio.set_frame_rate(22050) | |
| audio = audio.set_channels(1) | |
| audio = audio.set_sample_width(1) # 8-bit unsigned (0-255) | |
| # Step 5: WAV bytes | |
| wav_buf = io.BytesIO() | |
| audio.export(wav_buf, format="wav") | |
| wav_buf.seek(0) | |
| return wav_buf.read() | |
| def get_wav(text, lang): | |
| key = hashlib.md5((text + lang).encode()).hexdigest() | |
| cache_path = os.path.join(CACHE_DIR, key + ".wav") | |
| if os.path.exists(cache_path): | |
| print(f'[Cache HIT] "{text}"') | |
| with open(cache_path, "rb") as f: | |
| return f.read() | |
| print(f'[Generating] "{text}" | {lang}') | |
| wav_data = text_to_wav_bytes(text, lang) | |
| with open(cache_path, "wb") as f: | |
| f.write(wav_data) | |
| return wav_data | |
| def tts_get(): | |
| text = request.args.get("text", "Hello").replace("+", " ") | |
| lang = request.args.get("lang", "en") | |
| try: | |
| wav_data = get_wav(text, lang) | |
| except Exception as e: | |
| print(f"[ERROR] {e}") | |
| return f"Error: {e}", 500 | |
| return Response(wav_data, mimetype="audio/wav", | |
| headers={"Content-Length": str(len(wav_data))}) | |
| def tts_post(): | |
| data = request.get_json(silent=True) or {} | |
| text = data.get("text", "Hello") | |
| lang = data.get("lang", "en") | |
| try: | |
| wav_data = get_wav(text, lang) | |
| except Exception as e: | |
| print(f"[ERROR] {e}") | |
| return f"Error: {e}", 500 | |
| return Response(wav_data, mimetype="audio/wav", | |
| headers={"Content-Length": str(len(wav_data))}) | |
| def ping(): | |
| return {"status": "ok", "server": "ESP32 TTS Server"} | |
| if __name__ == "__main__": | |
| app.run(host="0.0.0.0", port=7860, debug=False) | |