Add Groq transcription support

This commit is contained in:
Muzaffer Emre
2026-07-31 18:48:21 +03:00
parent da3dc3c908
commit dd73735617
7 changed files with 145 additions and 41 deletions
+11 -8
View File
@@ -1,4 +1,4 @@
"""OpenAI and OpenRouter calls, stdlib only.
"""OpenAI-compatible transcription and OpenRouter calls, stdlib only.
Transcription runs on either provider: OpenRouter mirrors OpenAI's
/audio/transcriptions endpoint field for field, so one multipart request serves
@@ -20,6 +20,7 @@ APP_URL = "https://github.com/yusufipk/dikte"
USER_AGENT = f"dikte/1.0 (+{APP_URL})"
OPENAI_URL = "https://api.openai.com/v1"
OPENROUTER_URL = "https://openrouter.ai/api/v1"
GROQ_URL = "https://api.groq.com/openai/v1"
# Where a transcription request goes; built by config.Config.transcribe_target().
# `service` is the name the user sees in an error, `provider` the one the code
@@ -27,8 +28,10 @@ OPENROUTER_URL = "https://openrouter.ai/api/v1"
Target = collections.namedtuple("Target", "provider service api_key base_url model")
def timestamp_model(provider):
"""Only whisper-1 returns segment times, and OpenRouter namespaces the id."""
def timestamp_model(provider, selected=""):
"""Return a timestamp-capable model id for the selected provider."""
if provider == "groq":
return selected or "whisper-large-v3-turbo"
return "openai/whisper-1" if provider == "openrouter" else "whisper-1"
@@ -126,7 +129,7 @@ def _transcribe_request(target, wav_path, language, prompt, response_format,
fields.append(("language", language))
# OpenRouter takes the hint field and throws it away, so spare it the bytes.
# The same words still reach the cleanup model as a glossary.
if prompt and target.provider == "openai":
if prompt and target.provider != "openrouter":
fields.append(("prompt", prompt))
if granularity:
fields.append(("timestamp_granularities[]", granularity))
@@ -153,7 +156,7 @@ def transcribe(target, wav_path, language="", prompt="", timeout=300):
def transcribe_segments(target, wav_path, language="", prompt="", timeout=300):
"""[(start_seconds, end_seconds, text)] using whisper-1's verbose response."""
data = _transcribe_request(
target._replace(model=timestamp_model(target.provider)),
target._replace(model=timestamp_model(target.provider, target.model)),
wav_path, language, prompt, "verbose_json",
granularity="segment", timeout=timeout,
)
@@ -297,17 +300,17 @@ def openrouter_models(api_key="", transcription=False):
return sorted(m["id"] for m in models if m.get("id"))
def openai_models(api_key, base_url=OPENAI_URL):
def openai_models(api_key, base_url=OPENAI_URL, service="OpenAI"):
if not api_key:
raise ApiError(t("{service} API key is empty. Add it in Settings.",
service="OpenAI"))
service=service))
try:
data = _get_json(
f"{base_url.rstrip('/')}/models",
{"Authorization": f"Bearer {api_key}", "User-Agent": USER_AGENT},
)
except ApiError as exc:
raise explain(exc, "OpenAI") from None
raise explain(exc, service) from None
ids = [m["id"] for m in data.get("data", []) if m.get("id")]
audio = [i for i in ids if "transcribe" in i or "whisper" in i]
return sorted(audio or ids)