Modification of the structure
This commit is contained in:
@@ -1,11 +1,10 @@
|
||||
# Local Faster-Whisper (same engine as Pipecat local STT) — no GapGPT.
|
||||
# Sizes: tiny | base | small | medium | large-v3
|
||||
# Do NOT use cloud names like whisper-1
|
||||
# On low-RAM servers prefer: base or tiny
|
||||
STT_MODEL=base
|
||||
# Local Faster-Whisper — no GapGPT.
|
||||
# Persian dictation needs at least small (base/tiny are too inaccurate).
|
||||
# medium is better if the server has RAM.
|
||||
STT_MODEL=small
|
||||
STT_DEVICE=cpu
|
||||
STT_COMPUTE_TYPE=int8
|
||||
STT_PROMPT=یادداشت و مکالمهٔ فروش به زبان فارسی. اسامی مشتریان و اصطلاحات کسبوکار را دقیق بنویس.
|
||||
STT_PROMPT=این یک یادداشت فارسی است. لطفاً این مورد را بررسی کنید.
|
||||
|
||||
STT_HOST=127.0.0.1
|
||||
STT_PORT=3040
|
||||
|
||||
+32
-12
@@ -46,20 +46,21 @@ def _require_token(header_token: str | None) -> None:
|
||||
|
||||
def _model_name() -> str:
|
||||
"""Map env / legacy cloud names to Faster-Whisper local sizes."""
|
||||
raw = (_env("STT_MODEL", "base") or "base").lower()
|
||||
raw = (_env("STT_MODEL", "small") or "small").lower()
|
||||
legacy = {
|
||||
"whisper-1": "base",
|
||||
"whisper": "base",
|
||||
"whisper-1": "small",
|
||||
"whisper": "small",
|
||||
"gpt-4o-transcribe": "small",
|
||||
"gpt-4o-mini-transcribe": "base",
|
||||
"gpt-4o-mini-transcribe": "small",
|
||||
# tiny/base are too weak for Persian dictation
|
||||
"tiny": "small",
|
||||
"tiny.en": "small",
|
||||
"base": "small",
|
||||
"base.en": "small",
|
||||
}
|
||||
if raw in legacy:
|
||||
return legacy[raw]
|
||||
allowed = {
|
||||
"tiny",
|
||||
"tiny.en",
|
||||
"base",
|
||||
"base.en",
|
||||
"small",
|
||||
"small.en",
|
||||
"medium",
|
||||
@@ -73,7 +74,7 @@ def _model_name() -> str:
|
||||
"distil-large-v3",
|
||||
"large-v3-turbo",
|
||||
}
|
||||
return raw if raw in allowed else "base"
|
||||
return raw if raw in allowed else "small"
|
||||
|
||||
|
||||
def _get_model() -> WhisperModel:
|
||||
@@ -211,19 +212,38 @@ def _ensure_16k(wav_bytes: bytes) -> np.ndarray:
|
||||
return _resample_audio(audio, rate, 16000)
|
||||
|
||||
|
||||
def _normalize(audio: np.ndarray) -> np.ndarray:
|
||||
if audio.size == 0:
|
||||
return audio
|
||||
peak = float(np.max(np.abs(audio)))
|
||||
if peak < 1e-4:
|
||||
return audio
|
||||
# Bring quiet mic levels up without clipping
|
||||
gain = min(8.0, 0.9 / peak)
|
||||
if gain <= 1.05:
|
||||
return audio
|
||||
return np.clip(audio * gain, -1.0, 1.0).astype(np.float32)
|
||||
|
||||
|
||||
def _transcribe_local(wav_bytes: bytes) -> str:
|
||||
model = _get_model()
|
||||
audio = _ensure_16k(wav_bytes)
|
||||
audio = _normalize(_ensure_16k(wav_bytes))
|
||||
initial_prompt = _env(
|
||||
"STT_PROMPT",
|
||||
"یادداشت و مکالمهٔ فروش به زبان فارسی. اسامی مشتریان و اصطلاحات کسبوکار را دقیق بنویس.",
|
||||
"این یک یادداشت فارسی است. لطفاً این مورد را بررسی کنید.",
|
||||
) or None
|
||||
|
||||
segments, _info = model.transcribe(
|
||||
audio,
|
||||
language="fa",
|
||||
task="transcribe",
|
||||
initial_prompt=initial_prompt,
|
||||
vad_filter=True,
|
||||
beam_size=5,
|
||||
best_of=5,
|
||||
temperature=0.0,
|
||||
condition_on_previous_text=False,
|
||||
vad_filter=False,
|
||||
no_speech_threshold=0.45,
|
||||
)
|
||||
parts = [seg.text.strip() for seg in segments if getattr(seg, "text", None)]
|
||||
return " ".join(p for p in parts if p).strip()
|
||||
|
||||
@@ -244,7 +244,11 @@ async function start() {
|
||||
stream = null;
|
||||
return;
|
||||
}
|
||||
try {
|
||||
ctx = new Ctor({ sampleRate: 16000 });
|
||||
} catch {
|
||||
ctx = new Ctor();
|
||||
}
|
||||
await ctx.resume();
|
||||
sampleRate = ctx.sampleRate || 16000;
|
||||
source = ctx.createMediaStreamSource(stream);
|
||||
|
||||
Reference in New Issue
Block a user