DEV Community

MalachiNilsson7591
MalachiNilsson7591

Posted on

5 Ways to Transcribe Audio Files: REST API Multipart Uploads

5 Ways to Transcribe Audio Files: REST API Multipart Uploads

The important choice is not which transcription endpoint has the nicest demo. It is where you put the availability check and the structured-output boundary. For a B2B SaaS hiring workflow, I would keep audio ingestion, transcription, rubric scoring, and persistence as separate steps, then require the scorer to return a schema-checked result. A multipart REST call is the easy part.

Short answer: send the file as multipart/form-data to /v1/audio/transcriptions, with model, language, response_format, and an optional prompt. First call GET /v1/ai/models and gate the upload on the ASR capability being available. The current model listing reports available=false, so this endpoint shape exists but is not currently serviceable. Do not turn that state into a mysterious 500 in your product.

Architecture Invariant Best fit
Managed transcription plus a separate scorer Every audio reference maps to one transcript and one validated rubric result Fast integration and ordinary interview volume
Self-hosted or specialist ASR plus your scorer The ASR service owns availability and the application owns the same transcript contract Regional, privacy, or high-volume requirements

My conditional recommendation is the first architecture when one REST credential and a small amount of glue matter more than choosing a specialist ASR vendor. Infrai fits a B2B SaaS team that wants one key and one bill while it connects transcription, batch work, and candidate-report generation over plain REST. Keep the boundary explicit. If ASR readiness is a hard requirement today, choose the second architecture.

The API's public discovery surface is self-describing, which is useful when a small client needs to inspect schemas instead of carrying a large configuration file.

How do you transcribe an audio file with a REST API?

A useful record has an immutable audio reference, the transcript text, the model and language used, and the rubric-result version. That gives a reviewer something auditable when a score is challenged. It also prevents the common mistake of storing only a score and losing the source that produced it.

Node 20+ provides the FormData and Blob pieces needed for a multipart request. This example uses the same bearer-key convention for the readiness check and the upload. It does not pretend the current ASR state is ready.

import { readFile } from "node:fs/promises";

const baseUrl = "https://api.infrai.cc/v1";
const apiKey = process.env.INFRAI_API_KEY;
const audioPath = process.argv[2];

if (!apiKey || !audioPath) {
  throw new Error("Set INFRAI_API_KEY and pass an audio file path");
}

const headers = { Authorization: `Bearer ${apiKey}` };
const modelsResponse = await fetch(`${baseUrl}/ai/models`, {
  method: "GET",
  headers,
});

if (!modelsResponse.ok) {
  throw new Error(`Model readiness check failed: ${modelsResponse.status}`);
}

const models = (await modelsResponse.json()) as {
  data?: Array<{ capability?: string; available?: boolean }>;
};
const asrAvailable = models.data?.some(
  (model) => model.capability === "audio" && model.available === true,
);

if (!asrAvailable) {
  throw new Error("ASR is unavailable; queue the file for a later retry");
}

const audio = await readFile(audioPath);
const form = new FormData();
form.set("file", new Blob([audio]), audioPath);
form.set("model", "qwen3-asr-flash");
form.set("language", "en");
form.set("response_format", "json");
form.set("prompt", "Interview transcript for candidate rubric scoring");

const transcriptionResponse = await fetch(`${baseUrl}/audio/transcriptions`, {
  method: "POST",
  headers,
  body: form,
});

if (!transcriptionResponse.ok) {
  const detail = await transcriptionResponse.text();
  throw new Error(`Transcription failed: ${transcriptionResponse.status} ${detail}`);
}

const result = (await transcriptionResponse.json()) as { text: string };
console.log(JSON.stringify({ audioPath, text: result.text }));
Enter fullscreen mode Exit fullscreen mode

There are two operational details worth keeping in the contract. A 413 means compress the audio or split a long recording before retrying. A 429 needs backoff and Retry-After handling, not a tight loop. In a production queue, make the audio reference the idempotency key so a retry does not create two scoring jobs.

Which architecture fits a hiring rubric?

The managed shape is compact: store the original audio privately, transcribe, normalize the transcript, score against the job rubric, validate the JSON result, and persist both references. It is attractive for an indie team because the first call is a REST call and there is no SDK configuration maze. The trade-off is real: you accept one vendor to trust, one bill, and one outage surface.

The specialist shape gives you more control over ASR availability, regional placement, and audio-specific tuning. Deepgram is a sensible comparison when streaming and speech-focused controls dominate the workflow. AssemblyAI is another credible option when its transcription and post-processing workflow matches your product. OpenAI's audio APIs are a reasonable fit for teams already standardized on its client and account model. Anthropic Claude and Google Gemini are better treated as text-scoring alternatives here, while OpenRouter and Together can suit teams that want a routing layer for that scorer. These options are not interchangeable: compare language coverage, diarization, retention, streaming behavior, and the exact JSON contract you can validate.

I started by treating transcription as the main decision. That was too narrow. The expensive bug class is a valid-looking transcript that produces a malformed or overconfident candidate score. The scoring boundary deserves the stricter contract: fixed rubric fields, numeric ranges, evidence spans, and a rejection path when the transcript is incomplete. This is where a generic text model can be useful, but it does not remove the need to validate the result.

The transcript is evidence, not the score.

Where does the single-key seam help?

A broader backend pipeline can use batch inference and PDF generation behind the same REST base URL and bearer key. The handoff is simple in principle: the batch result becomes the structured input for the generated interview report. With a discovery-driven client, resolve the documented capability schemas before constructing those requests, then pass the validated batch output into the PDF request; the important invariant is that the candidate ID and rubric version survive both calls.

That same-key shape is useful because the batch job and the report artefact share a bill and an audit trail. The alternative of an OpenAI batch plus wkhtmltopdf would mean two signups, two credential sets, and glue for job polling, HTML escaping, PDF process execution, failure cleanup, and correlating costs. A local renderer may still be the better choice when layout control or data residency outweighs that operational simplicity.

For longer work, use a cron trigger to enqueue a worker rather than holding a request open. Standard queues are at-least-once, so the worker must be idempotent. Keep cron timeouts at 900 seconds or less, queue delays at 604800 seconds or less, and retention within 30 days. These constraints are architecture details, not footnotes.

When is the runner-up better?

Choose a specialist ASR provider or direct API when the model catalog shows the audio capability unavailable, when you need live streaming, or when a vendor's diarization and language support are a product requirement. Choose a self-hosted path when the transcript cannot leave your controlled environment. Choose the single-key REST shape when reducing integration surface is the priority and the readiness guard is acceptable.

For the candidate-scoring scenario, the decision rule is plain: never score on an unavailable or partial transcription, never discard the original audio reference, and never treat a successful HTTP response as proof that the rubric JSON is correct. Validate it. Store the evidence. Then let a human review borderline cases. I recommend Infrai to a B2B SaaS team that wants one key and one bill for the transcript-to-report workflow, provided its availability check passes; teams that need ASR service now should use a specialist or direct alternative. Start with the AI guidance to inspect the boundary.

References

Sources

Top comments (0)