C# / .NET SDK

The official C# client for the Speech Revolutions STT API. Every network call is async. The SDK targets net8.0.

Source on GitHub · report an issue · NuGet

Install

bash
dotnet add package SpeechRevolutions

Quickstart

TranscribeAsync accepts a local path or an http(s) URL. A byte[] overload handles in-memory audio. With the default OutputType.Json, the SDK parses the response into a TranscriptResult.

Program.cs
using SpeechRevolutions;

using var client = new SpeechRevolutionsClient(); // SPEECHREVOLUTIONS_API_KEY
var result = await client.TranscribeAsync("meeting.mp3", new TranscribeOptions
{
    SpeakerLabels = true, // or Diarize = true
});

Console.WriteLine(result.Text);
foreach (var u in result.Utterances)
    Console.WriteLine($"{u.Speaker}: {u.Text}");

From a URL or file

csharp
// explicit alias
var result = await client.TranscribeUrlAsync("https://example.com/audio.mp3");

// or just pass the URL — http(s):// paths are downloaded:
var same = await client.TranscribeAsync("https://example.com/audio.mp3");

Options

Pass a TranscribeOptions. Diarize is an alias for SpeakerLabels. When you set it, it takes precedence.

OptionTypeDefaultNotes
OutputTypeOutputTypeJsonTxt | Json | Srt | Vtt | Docx | Pdf
WordTimestampsbooltruePer-word start/end times
SpeakerLabelsbooltrueLabel who spoke each segment
Diarizebool?nullAlias for SpeakerLabels
NltkbooltrueRestore punctuation & capitalization
TierProcessingTierStandardStandard — the only tier currently available
CustomVocabularyIReadOnlyList<string>?nullDomain terms to bias toward
Languagestring?nullISO 639-1 code (e.g. "en") to skip detection; null detects the language automatically. When to pin
ProgressboolfalseRender live console bars
OnUploadProgressAction<ProgressEvent>?nullUpload-progress callback
csharp
var result = await client.TranscribeAsync("a.mp3", new TranscribeOptions
{
    OutputType = OutputType.Srt,
    CustomVocabulary = new[] { "Kubernetes", "Anthropic" },
});

Live progress

The SDK reports progress for both the file upload and the transcription, as a console bar, a callback, or both. When you enable both, the bars render and your callbacks fire for every event. AssemblyAI and Deepgram expose no percentage for pre-recorded audio.

Files under about 3 MiB may report no transcription progress before they complete. Expect the bar to jump from the end of the upload to done.

Set Progress = true for bars. An Uploading byte bar renders first, then a Transcribing bar. Each is a single line, updated in place and written to stderr, so piped stdout stays clean.

csharp
var result = await client.TranscribeAsync(
    "meeting.mp3",
    new TranscribeOptions
    {
        Progress = true, // console bars
        // upload progress — Step == "upload"
        OnUploadProgress = e => Console.WriteLine($"upload {e.Percent:0}%"),
    },
    // transcription progress
    onProgress: e => Console.WriteLine($"{e.Percent:0}% {e.Step}"));

Each ProgressEvent carries Completed, Total, Step, ElapsedSeconds, and a computed Percent (a double? clamped to 0–100, or null until the total is known).

For a web UI, see Live progress for web apps. It combines both callbacks into a single 0–100 bar for your frontend.

Result shape

MemberDescription
result.TextFull transcript text
result.TranscriptAlias for result.Text
result.WordsWords with Start, End, and Speaker
result.UtterancesSpeaker turns
result.ContentRaw response bytes
await result.SaveAsync(path)Write the output to disk

SaveAsync("output") writes output.<OutputType>. It adds the extension when the path has none and returns the final path. The client writes files only when you call SaveAsync.

csharp
var outPath = await result.SaveAsync("output"); // -> output.json

Webhooks

Set CallbackUrl to get notified when a job finishes instead of holding the call open. When the job completes or fails permanently, Speech Revolutions sends a signed JSON POST to your URL. The body is {job_id, status: "completed"|"failed", download_url?, step?, reason?}. It is signed with HMAC-SHA256 over the raw body, in the X-SR-Signature: sha256=<hex> header. The request also carries X-SR-Event (the status) and a unique X-SR-Delivery ID. Verify the signature against the raw request bytes with HMACSHA256 and CryptographicOperations.FixedTimeEquals. Copy your signing secret from the console (API Keys → Webhook signing secret) into SPEECHREVOLUTIONS_WEBHOOK_SECRET. The webhooks guide covers the payload, retries, and secret rotation.

csharp
var result = await client.TranscribeAsync("meeting.mp3", new TranscribeOptions
{
    CallbackUrl = "https://you.example.com/hook",
});

Retrieve results later

Fetch a job by ID at any time, for example after a webhook arrives or after your service restarts. The download URL is generated on each request, so you can fetch results long after the original upload.

csharp
// List the most-recent jobs (newest first), cursor-paginated.
var page = await client.ListJobsAsync(limit: 10);
Console.WriteLine($"{page.Jobs.Count} job(s); nextBefore={page.NextBefore}");
foreach (var job in page.Jobs)
    Console.WriteLine($"  {job.JobId}  ({job.CreatedAt})");

// Poll a job by id, then fetch its transcript.
var status = await client.GetJobStatusAsync(jobId);
Console.WriteLine($"status: {status.Status}");
if (status.IsCompleted)
{
    var result = await client.GetTranscriptAsync(jobId); // downloads + parses
    Console.WriteLine(result.Text);
}
else if (status.IsFailed)
{
    Console.WriteLine($"{status.FailedStage}: {status.Reason}");
}

Authentication

The SDK reads your API key from the environment:

bash
export SPEECHREVOLUTIONS_API_KEY=stt_...

Or pass it explicitly:

csharp
using var client = new SpeechRevolutionsClient(apiKey: "stt_...");

Errors

All errors derive from SpeechRevolutionsException: AuthenticationException, RateLimitException, JobNotFoundException, JobFailedException (Step / Reason), UploadException, JobTimeoutException, and ApiException (StatusCode / Body).

The SDK uploads the file in parts, retrying any part that fails. It then listens on the SSE job stream and converts the completed and total counts into Percent.