Class: ActiveHarness::Providers::Audio::OpenRouter

Inherits:
Base
  • Object
show all
Defined in:
lib/active_harness/providers/audio/openrouter.rb

Constant Summary collapse

ENDPOINT =

Dedicated transcription endpoint — distinct from the chat completions endpoint used by text/image generation on OpenRouter.

"https://openrouter.ai/api/v1/audio/transcriptions"

Constants inherited from Base

Base::HTTP, Base::STREAMING_HTTP

Instance Method Summary collapse

Instance Method Details

#call(model:, audio_data:, audio_format:, language: nil, **_) ⇒ Object

Synchronous call — OpenRouter's transcription endpoint has no job/polling API. Upstream providers time out after ~60s per request, so long audio should be split into shorter chunks by the caller before transcribing.

Parameters:

  • model (String)

    e.g. "openai/whisper-1", "deepgram/nova-3"

  • audio_data (String)

    raw binary audio bytes

  • audio_format (String)

    "wav", "mp3", "flac", "m4a", "ogg", "webm", "aac"

  • language (String) (defaults to: nil)

    ISO-639-1 code, e.g. "en" (optional — auto-detected if omitted)

Raises:



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/active_harness/providers/audio/openrouter.rb', line 20

def call(model:, audio_data:, audio_format:, language: nil, **_)
  headers = {
    "Content-Type"  => "application/json",
    "Authorization" => "Bearer #{api_key}"
  }
  referer = config.openrouter_http_referer.to_s
  headers["HTTP-Referer"] = referer unless referer.empty?

  body = {
    model: model,
    input_audio: { data: Base64.strict_encode64(audio_data), format: audio_format }
  }
  body[:language] = language if language

  raw  = post_json(URI(ENDPOINT), headers: headers, body: body, timeout: 90)
  data = parse!(raw)
  handle_error!(data)

  text = data["text"]
  raise Errors::ProviderError, "No transcription text in response: #{data.keys}" if text.nil?

  { content: text, provider: :openrouter, model: model, usage: extract_transcription_usage(data) }
end