Recursive AI

Save a speech transcript as JSON in C#

OneSpeech is a free, open-source speech recognition library for .NET from Recursive AI. MIT or Apache-2.0, no native dependencies.

Save transcript text and metadata as JSON; this example needs no model download.

Terminal
dotnet add package RecursiveAI.OneSpeech

Requires .NET 10 (net10.0); .NET 9 and earlier aren’t supported.

C#
using OneSpeech;
var doc = new Transcript { Text = "Hello." };
File.WriteAllText("transcript.json",
    doc.ToJson());
Console.WriteLine("Saved transcript.json.");

Unzip the example, then dotnet run.

Prints:

Text
Saved transcript.json.

The full program

C#
using OneSpeech;
 
var transcript = new Transcript
{
    Text = "Hello.", Language = "en",
    Words = [new Word { Text = "Hello.", TimingMethod = TimingMethod.None }]
};
File.WriteAllText("transcript.json", transcript.ToJson());
var restored = Transcript.FromJson(File.ReadAllText("transcript.json"));
Console.WriteLine("Saved transcript.json.");
Console.WriteLine($"Equal: {transcript == restored}");
Console.WriteLine($"Untimed: {restored.Words[0].Start is null && restored.Words[0].End is null}");
Console.WriteLine($"Speaker not processed: {restored.Words[0].Speaker is null}");
Console.WriteLine($"Provenance entries: {restored.Models.Length}");

The full program creates an untimed word, saves it and checks the restored transcript. No audio was recognized, so its model source and license records (provenance) are empty. Invalid documents throw InvalidTranscriptJsonException; file I/O errors remain file errors.

Text
Saved transcript.json.
Equal: True
Untimed: True
Speaker not processed: True
Provenance entries: 0

The full program writes this transcript.json (formatted here for reading):

JSON
{
  "schemaVersion": 1,
  "transcript": {
    "text": "Hello.",
    "words": [
      {
        "text": "Hello.",
        "start": null,
        "end": null,
        "confidence": null,
        "timingMethod": "None",
        "speaker": null,
        "overlap": false,
        "language": null
      }
    ],
    "segments": [],
    "turns": [],
    "language": "en",
    "duration": 0,
    "models": []
  }
}

Variations

To use System.Text.Json instead, serialize the full program’s transcript in one line. No converter registration is needed: Transcript carries its converter.

C#
string json = System.Text.Json.JsonSerializer.Serialize(transcript);

This writes the same schema as ToJson. Handle an unsupported schema version:

C#
using OneSpeech;
try
{
    Transcript.FromJson("""{"schemaVersion":2,"transcript":{"text":"Hello."}}""");
}
catch (InvalidTranscriptJsonException)
{
    Console.WriteLine("Unsupported transcript schema rejected.");
}
Text
Unsupported transcript schema rejected.

The short answer

Write transcript.ToJson() to a file and restore it with Transcript.FromJson. OneSpeech uses a versioned JSON envelope—a root object with a schema version and a nested transcript—rather than serializing only the recognized text. It preserves supplied text, timing, speaker labels and model provenance (records of model sources, versions and licenses), and rejects invalid documents instead of repairing missing facts.

The small example constructs “Hello.” rather than running recognition. That keeps file serialization independent of model downloads. In an application, save the Transcript returned by recognition through the same methods. The full program adds an untimed word and checks value equality after reading the file back.

How do I serialize a speech transcript to JSON in C#?

For a OneSpeech Transcript, use its explicit methods when you want transcript-specific error types. The root JSON object contains schemaVersion and transcript; the current major schema is version 1. Text is stored as supplied, not reconstructed from the word array. This matters when written punctuation or whitespace differs from individual word entries.

Nullable timing stays nullable. An untimed word has both start and end set to null, not zero-valued timestamps. Available times are finite, nonnegative seconds encoded as JSON numbers relative to the original audio. Serialization does not align words, identify speakers or improve recognition.

Model provenance records preserve IDs, source URLs, revisions, licenses, attribution and file digests. The constructed example has no model provenance because no model produced it. Real recognition results can carry provenance; saving them preserves those records rather than dropping them. A provenance record does not grant permission to download or redistribute a model.

A null speaker means speaker assignment was not processed. This is different from an explicit unassigned speaker after processing. Keeping that distinction avoids turning “unknown because not attempted” into a claim that an assignment was attempted and failed. The schema documentation defines the fields and validation rules.

How to turn text into a JSON file?

Construct a transcript with the text you actually have, then use the snippet at the top. Do not populate guessed word boundaries or speaker IDs merely to fill the JSON. Empty arrays are valid, and the format writes null values explicitly. The full example shows how to preserve an untimed word when word-level text is available but alignment is not.

File.WriteAllText replaces the named output file. Choose an application-controlled output path and avoid accidentally overwriting another transcript. The serialization call returns a string; file permission and storage errors remain ordinary file errors, separate from transcript validation failures.

How do I deserialize transcript JSON in C#?

Read the file and pass its contents to Transcript.FromJson. Valid transcripts compare by ordered collection values: a round trip preserves equality, including provenance, spacing and null timing. Equality is stricter than comparing the top-level text alone.

Unsupported schema versions, unknown fields, malformed JSON, missing required fields, invalid intervals and exceeded budgets are rejected. Explicit null arrays are also refused; omitted optional arrays retain their empty defaults. The variation supplies an unsupported schema version and catches InvalidTranscriptJsonException.

If your application uses System.Text.Json, the transcript converter reads and writes the same envelope but reports invalid documents through JsonException. For trimmed or NativeAOT applications, register a generated JSON context instead of depending on reflection. Keep application request-body limits appropriate to your memory budget; the library’s maximum document allowance is not an instruction to accept arbitrarily large uploads.

All onespeech recipes