heygen-com/hyperframes · error

Unrecognized JSON transcript format. Expected whisper.cpp (t

Error message

Unrecognized JSON transcript format. Expected whisper.cpp (transcription[].tokens), OpenAI API (words[]), or normalized ([{text, start, end}]).

What it means

Thrown by detectJsonFormat when a .json transcript file was successfully parsed as JSON but its structure doesn't match any of the three recognized formats: whisper-cpp (object with a transcription array), OpenAI API (object with a words array), or normalized words-json (array of objects with text and start fields). This is a content-level validation, not a JSON syntax error.

Source

Thrown at packages/cli/src/whisper/normalize.ts:54

 */
export function detectFormat(filePath: string): TranscriptFormat {
  const ext = extname(filePath).toLowerCase();
  if (ext === ".srt") return "srt";
  if (ext === ".vtt") return "vtt";
  if (ext === ".json") return detectJsonFormat(JSON.parse(readFileSync(filePath, "utf-8")));
  throw new Error(`Unsupported transcript file extension: ${ext}. Use .json, .srt, or .vtt`);
}

function detectJsonFormat(raw: unknown): TranscriptFormat {
  if (raw && typeof raw === "object" && !Array.isArray(raw)) {
    const obj = raw as Record<string, unknown>;
    if (obj.transcription && Array.isArray(obj.transcription)) return "whisper-cpp";
    if (obj.words && Array.isArray(obj.words)) return "openai";
  }
  if (Array.isArray(raw) && raw[0]?.text !== undefined && raw[0]?.start !== undefined) {
    return "words-json";
  }
  throw new Error(
    "Unrecognized JSON transcript format. Expected whisper.cpp (transcription[].tokens), " +
      "OpenAI API (words[]), or normalized ([{text, start, end}]).",
  );
}

// ---------------------------------------------------------------------------
// Parsers
// ---------------------------------------------------------------------------

/**
 * Rejoin word fragments that whisper splits across tokens:
 * - Single capital + lowercase continuation: C + aught -> Caught, G + onna -> Gonna
 * - Word ending in consonant + in': shin + in' -> shinin', hid + in' -> hidin'
 */
function mergeFragments(words: Word[]): void {
  for (let i = 0; i < words.length - 1; i++) {
    const curr = words[i];
    const next = words[i + 1];

View on GitHub (pinned to c2996c8626)

Solutions

  1. Inspect the JSON structure and map it to one of the three supported schemas (whisper-cpp transcription[], OpenAI words[], or normalized [{text, start, end}]).
  2. Convert the transcript to SRT or VTT format instead, which has a simpler, well-defined structure.
  3. If using whisper-cpp output, ensure you're using the correct output format flag (--output-json with transcription field).
  4. For custom JSON, transform it to the normalized [{text, start, end}] format before passing.

Example fix

// before: [{"word": "hello", "ts": 0}]  (unrecognized schema)
// after:  [{"text": "hello", "start": 0, "end": 0.5}]  (normalized words-json)
Defensive patterns

Strategy: type-guard

Validate before calling

function isRecognizedJsonFormat(raw: unknown): boolean {
  if (raw && typeof raw === "object" && !Array.isArray(raw)) {
    const obj = raw as Record<string, unknown>;
    if (Array.isArray(obj.transcription) || Array.isArray(obj.words)) return true;
  }
  if (Array.isArray(raw) && raw[0]?.text !== undefined && raw[0]?.start !== undefined) return true;
  return false;
}

Type guard

function isNormalizedWordsArray(raw: unknown): raw is Array<{ text: string; start: number; end: number }> {
  return Array.isArray(raw) && raw.every(
    (item) => typeof item === "object" && item !== null &&
      typeof item.text === "string" &&
      typeof item.start === "number" &&
      typeof item.end === "number",
  );
}

Try / catch

try {
  const format = detectFormat(filePath);
} catch (err) {
  if (err instanceof Error && err.message.includes("Unrecognized JSON transcript format")) {
    console.error(`${err.message}. Convert to SRT/VTT or use a supported JSON schema.`);
    process.exit(1);
  }
  throw err;
}

Prevention

When it happens

Trigger: The JSON file is valid JSON but has a different schema — e.g. a raw array without text/start keys, an object with a segments array but no transcription or words field, or a proprietary caption format. Also triggered by an empty JSON object or empty array.

Common situations: Using a transcript from a tool that exports a different JSON schema (e.g. Deepgram, AssemblyAI, Rev); an incomplete or truncated export; a manually-created JSON with wrong field names; a whisper-cpp output from a version that changed its schema.

Related errors


AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12). Data as JSON: /api/errors/b4d42a198aecf510. Report an issue: GitHub.