Transcription
Generate transcripts with your own program and retry failed jobs.
GUILDSCRIBE_TRANSCRIPTION_HOOK selects one executable worker. Omitting the
setting disables transcription. Guildscribe does not choose or bundle a model
adapter. Guildscribe saves transcription progress so unfinished jobs can resume after a
restart. The short lifecycle-hook timeout does not apply to transcription.
After saving a completed recording, Guildscribe inserts a transcripts row with
status pending. It processes one transcription at a time, separately from
Discord capture, so recording can continue while transcription runs. The states
are pending, running, complete, and failed. The validated state retains
attempts, queuedAt, nullable startedAt, nullable finishedAt, a sanitized
nullable error, and a nullable result. Daemon startup requeues pending
work and converts an interrupted running state back to pending. It does not
automatically retry failed work or retroactively enqueue recordings that
predate configuration of the hook.
Guildscribe invokes the executable with exactly one positional argument:
/absolute/path/to/transcription-hook /absolute/path/to/recordingThe recording directory is also the child working directory. The executable
receives no request document on stdin. It discovers inputs in the
recording directory: participants.json, audio.mp3, and the JSON/PCM pairs
below intervals/. Recording metadata is available through read-only SQL using
GUILDSCRIBE_DATABASE and GUILDSCRIBE_RECORDING_ID in the hook environment.
These replace the former recording.json input; existing adapters must be
updated before enabling the upgraded daemon.
The restricted child environment contains ordinary process-location values and
the two database/recording references above; it never contains the Discord
token. Before exiting successfully, the executable atomically writes a result
document like this to .transcript-result.json.pending:
The text and interval ID here are illustrative. Use an interval ID from the recording, or omit it for combined-audio transcription.
{
"language": "en",
"segments": [
{
"startOffsetMs": 0,
"endOffsetMs": 1200,
"text": "Readable segment text.",
"sourceIntervalID": "00000000-0000-4000-8000-000000000000"
}
]
}language is a nullable BCP 47 tag. sourceIntervalID is optional for
combined-audio transcription; when present, it must identify overlapping
speaking audio in the same recording. Speaker identity is resolved through the
source interval and participants.json; Guildscribe snapshots the resolved
speaker into segment columns for SQL-only searches. Segments must contain
nonempty text, start at or after zero, end after they start, be ordered by
startOffsetMs, and remain within the recording duration. Exit code zero is
accepted only when the pending result exists and passes schema validation.
The pending document is the hook's response; stdout and stderr are bounded
diagnostics only. The hook must not write the database. After it exits zero,
Guildscribe validates the result, snapshots speakers, and atomically commits
segments and status complete. The validated in-memory representation is:
{
"schemaVersion": 1,
"recordingID": "00000000-0000-4000-8000-000000000000",
"status": "complete",
"attempts": 1,
"queuedAt": "2026-11-05T12:30:00.000Z",
"startedAt": "2026-11-05T12:30:01.000Z",
"finishedAt": "2026-11-05T12:31:00.000Z",
"error": null,
"result": {
"language": "en",
"segments": []
}
}result is null before completion and on failure. Failed work requires both
finishedAt and error; complete work requires finishedAt and result. The
hook must remain running until its atomic write is complete;
Guildscribe does not poll an invalid file indefinitely. A nonzero exit, spawn
failure, missing result, or invalid result
saves status failed. Graceful daemon shutdown returns an in-flight job to
pending. Audio, interval sidecars, and PCM are retained for every outcome.
The worker never creates FLAC, WAV, or consolidated per-speaker tracks.
After the result is saved, Guildscribe emits the best-effort
transcription.completed or transcription.failed lifecycle notification when
configured. Hook stdout and stderr are bounded diagnostics and are not result
transport.
Retry failed work
Replace the example UUID with an ID from guildscribe recordings list:
{ "recordingID": "00000000-0000-4000-8000-000000000000" }guildscribe transcript retry --request retry.json --dry-run
guildscribe transcript retry --request retry.json
guildscribe transcript get RECORDING_ID --include-segmentsRetry queues work for the existing daemon; it does not start a daemon or another worker. Failed work becomes pending, pending/running requests are no-ops, and complete work is rejected. See history for exports.
Supported integrations
The current runtime uses the pending-result file described above. Asynchronous
transcript segment add, transcript complete, and transcript fail callbacks
are planned, not implemented commands. Use the generated catalog to check your
installed version.
Your hook selects the model or service and manages its scheduling and credentials. Guildscribe provides recording IDs and speaker information, validates the transcript, and writes it to the database. Capture continues when transcription is absent or fails. No summarization or reasoning stage follows transcription.