twocents/open source

Recordings and recovery

Find recordings, check their files, and export a meeting.

Use an ID from recordings list in the commands below:

guildscribe recordings list
guildscribe recordings show RECORDING_ID
guildscribe recordings verify RECORDING_ID
guildscribe recordings export RECORDING_ID --destination /absolute/path/to/new-export --dry-run
guildscribe recordings export RECORDING_ID --destination /absolute/path/to/new-export

How recording works

Guildscribe subscribes to Discord's independent Opus receive stream for each human speaker in the active channel. A speaking interval ends after 500 milliseconds of silence. The stream is decoded to signed 16-bit, 48 kHz stereo PCM and its sidecar is checkpointed every two seconds.

The bot joins self-muted and not deafened. While idle, a voice-state event for an occupied allowed channel selects that channel. On daemon startup or after a recording finishes, if several allowed channels are already occupied, the first one in configuration order wins. Once selected, the active channel remains exclusive: activity in other allowed channels is ignored until the recording's empty grace and finalization both finish.

When the active channel becomes empty Guildscribe keeps the grace boundary in daemon memory and starts the configured grace timer. A returning human to that channel clears the timer and continues the same meeting. Humans entering another allowed channel do not cancel the active channel's grace. Grace expiry uses the original boundary as the meeting end, disconnects the bot, closes active intervals, and begins rendering. After publication or failure, Guildscribe may immediately select another occupied allowed channel.

Rendering mixes intervals at their meeting offsets, preserves simultaneous speech, applies an FFmpeg limiter at 0.95, trims to the exact meeting duration, and encodes 192 kbps MP3 with libmp3lame. ffprobe must report positive duration before audio.part.mp3 becomes audio.mp3.

After validation Guildscribe retains every PCM payload, commits complete recording metadata, and atomically moves the recording directory beneath its year and month. A failure leaves recoverable data in in-progress with a sanitized failure in the database. PCM retention never depends on transcription state.

At daemon startup Guildscribe scans in-progress. A recording interrupted during capture or empty-channel grace is marked recoveredAfterRestart and rendered using its last saved interval offsets. A recording interrupted during finalization is rendered again. A valid existing audio.mp3 is reused.

Find a recording

recordings list discovers both published recordings and recoverable directories under in-progress. It returns records ordered by descending startedAt plus aggregate totals. Each record reports its storage class, recording lifecycle fields, combined-audio byte size, PCM file count and byte size, transcription status, transcript segment count, total file count, and total bytes for the entire recording directory.

recordings show <recordingID> returns the same record shape for one exact recording ID. Missing IDs fail with recording_not_found; an ID present in more than one storage location fails with recording_ambiguous. These commands only inspect filesystem metadata and never read or expose captured audio or transcript contents.

Verify and export

recordings verify is read-only. It validates recording identity and lifecycle, interval sidecars and counts, PCM existence and stereo-frame alignment, connection-gap invariants, combined MP3 duration through FFprobe, participant metadata, the complete transcript schema and source references, and exact stored transcript segments and source-interval consistency. It also returns byte counts and SHA-256 digests for every saved file. Failed checks make the command envelope unsuccessful without changing the recording.

recordings export copies one recording into a new absolute destination and writes checksums.sha256. It excludes pending transcription responses and never changes the source recording. The destination must not already exist or be inside the source. --dry-run returns the plan without writing. --wav uses the mandatory FFmpeg installation to add a portable PCM WAV copy; WAV is created only for the export and is not stored with the original recording. If export fails, Guildscribe removes only the newly created partial destination.

Portable exports contain meeting media, participant and interval files, and a standalone SQLite database for that meeting and its transcript. They exclude unrelated meetings and channel messages. The live database owns runtime metadata; new recordings do not use recording.json.

Intervals are signed 16-bit little-endian PCM at 48 kHz stereo, with JSON sidecars for identity and meeting-relative timing. Connection gaps have sidecars without PCM. Participant identity and presence live in participants.json. Raw PCM is retained permanently, regardless of transcription outcome.

On this page