This commit is contained in:
SFirouzi 2025-11-17 14:15:20 +03:30
commit 0255257a1a
10 changed files with 165 additions and 0 deletions

1
.env Normal file
View File

@ -0,0 +1 @@
TRITON_URL=192.168.130.14:3089

1
.env.example Normal file
View File

@ -0,0 +1 @@
TRITON_URL=****

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
/data
.venv
__pycache__

23
Dockerfile Normal file
View File

@ -0,0 +1,23 @@
FROM python:3.12-slim
# Set environment variables
ENV DEBIAN_FRONTEND=noninteractive \
PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1
# Copy requirements file
COPY requirements.txt /app/requirements.txt
# Install requirements
RUN pip install --no-deps git+https://git.d.aiengines.ir/bi/asr_triton_client.git@05c8f7a88d3ff41d82591b6beb41bab86d81d421
RUN pip install --no-cache-dir -r /app/requirements.txt
# Set working directory and copy app
WORKDIR /app
COPY . /app
# Expose necessary ports
EXPOSE 8000
# Command to run the script
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]

27
README.md Normal file
View File

@ -0,0 +1,27 @@
## ASR SERVICE
### A FASTAPI client for receieving audio data from font and sending audio to a Triton ASR service using SSE or WebSocket streaming. It yields real-time transcription results as JSON-like events.
## How to run
### SET ENVIRONMENT
1-create a file .env and set TRITON_URL
### 1-DEVELOPMENT
#### Run the system : Uvicorn and Fastapi
.venv/bin/uvicorn src.main:app --host 0.0.0.0 --port 8000
### 2-DEPLOYMENT
#### Docker Build
docker build -t asr_client:latest --build-arg DEBIAN_FRONTEND=noninteractive .
#### Docker Run
docker run -d --gpus all --network host --restart unless-stopped asr_client:latest
there was a problem in installing ast_client package :
pip couldnot find a versaion for perf-analyzer==2.59.1 : so i removed it

7
config/base.py Normal file
View File

@ -0,0 +1,7 @@
from dotenv import load_dotenv
import os
load_dotenv()
TRITON_URL = os.getenv("TRITON_URL")
MIN_CHUNK_SIZE = 90000

30
requirements.txt Normal file
View File

@ -0,0 +1,30 @@
fastapi==0.116.1
uvicorn==0.35.0
aiohappyeyeballs==2.6.1
aiohttp==3.13.0
aiosignal==1.4.0
async-timeout==5.0.1
attrs==25.4.0
Brotli==1.1.0
certifi==2025.10.5
frozenlist==1.8.0
gevent==25.9.1
geventhttpclient==2.3.4
greenlet==3.2.4
grpcio==1.67.1
idna==3.11
multidict==6.7.0
numpy==2.2.6
packaging==25.0
propcache==0.4.1
protobuf==5.29.5
pydub==0.25.1
python-dotenv==1.1.1
python-rapidjson==1.21
tritonclient==2.61.0
typing_extensions==4.15.0
urllib3==2.5.0
websockets==15.0.1
yarl==1.22.0
zope.event==6.0
zope.interface==8.0.1

30
src/main.py Normal file
View File

@ -0,0 +1,30 @@
from fastapi import FastAPI, WebSocket
import asyncio
from asr.service import TritonGrpcClient
import json
from config.base import TRITON_URL, MIN_CHUNK_SIZE
app = FastAPI()
client = TritonGrpcClient(TRITON_URL)
@app.websocket("/asr")
async def websocket_endpoint(ws: WebSocket):
print("Starting ASR service")
await ws.accept()
audio_buffer = bytearray()
try:
while True:
data = await ws.receive_bytes()
audio_buffer.extend(data)
async for s in client.event_stream_from_bytes(raw=bytes(audio_buffer), filename="stream.webm"):
await ws.send_text(json.dumps(s, ensure_ascii=False))
except Exception as e:
print("WebSocket error:", e)
await ws.close()

16
test/test.js Normal file
View File

@ -0,0 +1,16 @@
const ws = new WebSocket("ws://localhost:8000/asr");
ws.onmessage = (event) => {
console.log("ASR Result:", event.data);
};
async function startStreaming() {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const recorder = new MediaRecorder(stream, { mimeType: "audio/webm" });
recorder.ondataavailable = (event) => {
ws.send(event.data); // send audio chunks to backend
};
recorder.start(500); // send audio every 250 ms
}

27
test/test.py Normal file
View File

@ -0,0 +1,27 @@
import asyncio
import websockets
import json
AUDIO_FILE = "./khabar_1_5.wav" # Replace with your audio file path
WS_URL = "ws://127.0.0.1:8000/asr"
async def send_audio():
async with websockets.connect(WS_URL) as ws:
print("Connected to ASR WebSocket")
# Read the audio file in chunks
with open(AUDIO_FILE, "rb") as f:
chunk_size = 21920
while chunk := f.read(chunk_size):
await ws.send(chunk)
try:
while True:
message = await ws.recv()
data = json.loads(message)
print("Received:", data)
except websockets.exceptions.ConnectionClosed:
print("WebSocket closed by server")
# Run the async client
asyncio.run(send_audio())