Spaces:
Sleeping
Sleeping
| from fastapi import FastAPI, UploadFile, File, Header, HTTPException | |
| from fastapi.responses import JSONResponse | |
| from transformers import pipeline | |
| import torch | |
| import io | |
| import soundfile as sf | |
| import os | |
| app = FastAPI() | |
| # Cấu hình Token bảo mật (Thay 'ChuyenGiaIoT2026' bằng mã bí mật của bạn) | |
| API_TOKEN = os.getenv("ESP32_SECRET_TOKEN", "ChuyenGiaIoT2026") | |
| print("Loading PhoWhisper model...") | |
| # Sử dụng pipeline của Hugging Face để load mô hình PhoWhisper-small (tối ưu cho CPU Free) | |
| stt_pipeline = pipeline( | |
| "automatic-speech-recognition", | |
| model="vinai/phowhisper-small", | |
| device="cpu" | |
| ) | |
| print("Model loaded successfully!") | |
| def read_root(): | |
| return {"message": "Hugging Face STT Server cho ESP32-S3 đang hoạt động!"} | |
| async def predict_speech( | |
| file: UploadFile = File(...), | |
| authorization: str = Header(None) | |
| ): | |
| # 1. Kiểm tra mã bảo mật Token từ ESP32 gửi lên | |
| if not authorization or authorization != f"Bearer {API_TOKEN}": | |
| raise HTTPException(status_code=401, detail="Unauthorized - Sai Token") | |
| try: | |
| # 2. Đọc file audio từ request | |
| audio_bytes = await file.read() | |
| # 3. Giải mã file WAV sang mảng numpy phù hợp với mô hình (ép về 16kHz) | |
| data, samplerate = sf.read(io.BytesIO(audio_bytes)) | |
| # Nếu audio là Stereo, chuyển về Mono bằng cách lấy trung bình cộng | |
| if len(data.shape) > 1: | |
| data = data.mean(axis=1) | |
| # 4. Đưa vào mô hình AI để nhận diện Tiếng Việt | |
| # chunk_length_s=30 giúp xử lý tốt nếu file dài | |
| result = stt_pipeline({"raw": data, "sampling_rate": samplerate}, generate_kwargs={"language": "vi"}) | |
| # 5. Trả kết quả gọn nhẹ về cho ESP32-S3 | |
| return JSONResponse(content={ | |
| "status": "success", | |
| "text": result["text"].strip() | |
| }) | |
| except Exception as e: | |
| return JSONResponse(status_code=500, content={ | |
| "status": "error", | |
| "message": str(e) | |
| }) |