Spaces:
Sleeping
Sleeping
Download main.py from whynotasif/VocalNode: direct link, hf CLI and curl.
- Browser
- Download file 3.29 kB
-
https://huggingface.co/spaces/whynotasif/VocalNode/resolve/main/main.py
- Command line
-
hf download hf://spaces/whynotasif/VocalNode/main.py
-
curl -L -o main.py https://huggingface.co/spaces/whynotasif/VocalNode/resolve/main/main.py
3.29 kB
| import os | |
| import shutil | |
| import tempfile | |
| import speech_recognition as sr | |
| from fastapi import FastAPI, UploadFile, File, Form | |
| from pydub import AudioSegment | |
| from pathlib import Path | |
| from typing import Optional | |
| app = FastAPI(title="VocalizeAPI") | |
| # --- LINUX FFMPEG FIX --- | |
| # On some HF containers, we need to explicitly tell pydub where ffmpeg is | |
| if shutil.which("ffmpeg"): | |
| AudioSegment.converter = shutil.which("ffmpeg") | |
| def get_audio_info(file_path): | |
| """Returns size in MB and duration in seconds.""" | |
| size_mb = os.path.getsize(file_path) / (1024 * 1024) | |
| audio = AudioSegment.from_file(file_path) | |
| duration_sec = len(audio) / 1000.0 | |
| return size_mb, duration_sec | |
| async def audio_to_text( | |
| file: UploadFile = File(...), | |
| lang: Optional[str] = Form(None) | |
| ): | |
| temp_dir = tempfile.mkdtemp() | |
| # Ensure filename exists to avoid suffix errors | |
| filename = file.filename if file.filename else "input.ogg" | |
| input_ext = Path(filename).suffix.lower() or ".ogg" | |
| input_path = os.path.join(temp_dir, f"input{input_ext}") | |
| wav_path = os.path.join(temp_dir, "converted.wav") | |
| try: | |
| # 1. Save uploaded file | |
| with open(input_path, "wb") as buffer: | |
| shutil.copyfileobj(file.file, buffer) | |
| # 2. Convert to WAV (Standardized for Google) | |
| audio = AudioSegment.from_file(input_path) | |
| audio = audio.set_channels(1).set_frame_rate(16000) | |
| audio.export(wav_path, format="wav") | |
| target_path = wav_path | |
| # 3. Validate | |
| size_mb, duration = get_audio_info(target_path) | |
| if duration > 60: | |
| return {"status": False, "error": "File Rejected: It's longer than 60s.", "result": ""} | |
| elif size_mb > 10: | |
| return {"status": False, "error": "Error: File is too large (>10MB).", "result": ""} | |
| # 4. Transcribe | |
| r = sr.Recognizer() | |
| with sr.AudioFile(target_path) as source: | |
| r.adjust_for_ambient_noise(source, duration=0.5) | |
| audio_data = r.record(source) | |
| try: | |
| # Use provided lang if it exists and isn't just whitespace | |
| actual_lang = lang.strip() if (lang and lang.strip()) else None | |
| if actual_lang: | |
| text = r.recognize_google(audio_data, language=actual_lang) | |
| else: | |
| text = r.recognize_google(audio_data) | |
| return {"status": True, "error": None, "result": text} | |
| except sr.UnknownValueError: | |
| return {"status": False, "error": "I could not understand the audio (Low quality or silent).", "result": ""} | |
| except sr.RequestError: | |
| return {"status": False, "error": "API-Key Error: Google limit reached.", "result": ""} | |
| except Exception as e: | |
| print(f"Server Log Error: {e}") | |
| return {"status": False, "error": f"System Error: {str(e)}", "result": ""} | |
| finally: | |
| # 5. Cleanup | |
| shutil.rmtree(temp_dir, ignore_errors=True) | |
| if __name__ == "__main__": | |
| import uvicorn | |
| uvicorn.run(app, host="0.0.0.0", port=7860) |