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
dotnet add package SpeechRevolutionsQuickstart
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.
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
// 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.
| Option | Type | Default | Notes |
|---|---|---|---|
OutputType | OutputType | Json | Txt | Json | Srt | Vtt | Docx | Pdf |
WordTimestamps | bool | true | Per-word start/end times |
SpeakerLabels | bool | true | Label who spoke each segment |
Diarize | bool? | null | Alias for SpeakerLabels |
Nltk | bool | true | Restore punctuation & capitalization |
Tier | ProcessingTier | Standard | Standard — the only tier currently available |
CustomVocabulary | IReadOnlyList<string>? | null | Domain terms to bias toward |
Language | string? | null | ISO 639-1 code (e.g. "en") to skip detection; null detects the language automatically. When to pin |
Progress | bool | false | Render live console bars |
OnUploadProgress | Action<ProgressEvent>? | null | Upload-progress callback |
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.
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
| Member | Description |
|---|---|
result.Text | Full transcript text |
result.Transcript | Alias for result.Text |
result.Words | Words with Start, End, and Speaker |
result.Utterances | Speaker turns |
result.Content | Raw 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.
var outPath = await result.SaveAsync("output"); // -> output.jsonWebhooks
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.
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.
// 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:
export SPEECHREVOLUTIONS_API_KEY=stt_...Or pass it explicitly:
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.