mostlyright.finance.transcripts.streaming_transcriber
Streaming STT engine.
StreamingTranscriber turns the live PCM frame stream
(Iterator[tuple[pcm_bytes, spoken_at]] from
mostlyright.finance.transcripts.capture.base.CaptureAdapter.live()) into
incremental transcript Segments + provisional final-only
:class:FactDeltas that the SSE endpoint fans out over the
:class:~mostlyright.finance.transcripts.segment_bus.SegmentBus.
Pipeline:
- VAD-guided chunking.
_vad_chunks()groups the incoming frames into ~3-5 s windows with ~0.5 s overlap. A speech run ends on a VAD speech-end (a silence gap). The plan mandates NO torch / NO silero here — we use a LIGHTWEIGHT energy gate (RMS over the s16le samples) behind a pluggablevadinterface, so a real Silero-ONNX VAD can be dropped in later WITHOUT touching this engine. - Transcribe. Each in-flight window is transcribed with the per-call
initial_prompt(seeded from the market strike terms viaseed_initial_prompt()). faster-whisper is the engine — it is injected as a callabletranscriberso unit tests stub it and NO realWhisperModel/ no real audio is needed. The default production transcriber lazy-imports faster-whisper (behind the[earnings]extra). - partial → final. An in-flight window emits a revisable PARTIAL
Segment(is_final=False). On the speech-end boundary the segment is re-emitted FINAL (is_final=True) with the stabilised text. - final-only counting.
classify_mentions()runs over FINAL segments ONLY →FactDeltas aggregated per(term, compound_type)(resolution_status="provisional",is_final=True,kalshi_counted=validate_kalshi_counted_occurrence(...)). A term in a PARTIAL is NEVER counted (else a retracted word settles a market). classify_mentions (NOT count_mentions) is the production counter: it additionally surfaces CLOSED-compound candidates (firefighterforfire) that count_mentions never matches — without them a Polymarket closed-straddle silently resolvedresolved_no.
Authority. is_final denotes STT-segment finality
ONLY; a counted fact delta is is_final=True yet STILL
resolution_status="provisional". Settlement/research authority is gated on
resolution_status / source, NEVER on is_final. Live deltas are
early-signal rows — the post-call ledger stays authoritative.
Legal. Audio is a TRANSIENT ingest artifact — the emitted
Segment / FactDelta carry TEXT + facts ONLY, never PCM bytes.
The bus enforces the same gate structurally.
DEFERRED (operator / live). This engine is fully implemented + tested
against SYNTHETIC PCM and a STUB transcriber. Validation against a REAL live
earnings webcast (a webcast in progress) and a real faster-whisper model on
real audio requires an operator with a live call and the [earnings] extra
installed — that end-to-end run is DEFERRED and cannot be exercised in unit
tests. The energy VAD is a floor; swapping in a real Silero-ONNX VAD (which
would add a pip dep and must clear the package-legitimacy checkpoint) is
also deferred.
Module Attributes
Section titled “Module Attributes”TranscribeFn | (window_pcm, *, initial_prompt) -> text. |
|---|---|
TurnProvider | A turn provider maps a (partial) segment to the role-parser Turn whose speaker_role / role_source drive the fail-closed Kalshi rule. |
Classes
Section titled “Classes”FactDelta(term_canonical, …[, …]) | A provisional live fact delta counted off a FINAL segment (never a partial). |
|---|---|
Segment(text, is_final, spoken_at, …[, …]) | One streaming transcript segment — TEXT ONLY (never audio). |
StreamingTranscriber(*[, transcriber, …]) | VAD-chunked streaming STT → partial/final segments + final-only fact deltas. |
class mostlyright.finance.transcripts.streaming_transcriber.FactDelta(term_canonical, matched_surface_form, mention_count, speaker_role, role_source, speaker_name, kalshi_counted, is_final, spoken_at, stream_seq, compound_type=‘standalone’, resolution_status=‘provisional’, source=‘earnings_call’)
Section titled “class mostlyright.finance.transcripts.streaming_transcriber.FactDelta(term_canonical, matched_surface_form, mention_count, speaker_role, role_source, speaker_name, kalshi_counted, is_final, spoken_at, stream_seq, compound_type=‘standalone’, resolution_status=‘provisional’, source=‘earnings_call’)”Bases: object
A provisional live fact delta counted off a FINAL segment (never a partial).
Shaped for schema.finance.fact.v1: resolution_status="provisional"
(live early-signal — NOT a settlement source), is_final=True (STT
finality — orthogonal to authority), kalshi_counted derived via the
unchanged fail-closed validate_kalshi_counted_occurrence()
(mode-agnostic). TEXT/facts only — no audio.
compound_type is the per-delta compound axis — one
delta per (term, compound_type), never an aggregate mixing types, so the
venue filters in fact_builder apply row-wise (closed candidates surface
for Polymarket human review; Kalshi-No on closed). ADDITIVE with default
"standalone": an existing SSE consumer or a persisted pre-fix delta is
unaffected (standalone counts for both venues exactly as before the axis).
- Parameters:
compound_type: str
Section titled “compound_type: str”is_final: bool
Section titled “is_final: bool”kalshi_counted: bool
Section titled “kalshi_counted: bool”matched_surface_form: str
Section titled “matched_surface_form: str”mention_count: int
Section titled “mention_count: int”resolution_status: str
Section titled “resolution_status: str”role_source: str
Section titled “role_source: str”source: str
Section titled “source: str”speaker_name: str | None
Section titled “speaker_name: str | None”speaker_role: str
Section titled “speaker_role: str”spoken_at: float
Section titled “spoken_at: float”stream_seq: int
Section titled “stream_seq: int”term_canonical: str
Section titled “term_canonical: str”to_stt_count(, turn_index=None)
Section titled “to_stt_count(, turn_index=None)”Map this delta to a build_fact_rows stt_counts occurrence record.
The propagation seam (review F1): compound_type survives from the
live classifier through the occurrence record into the fact row, so the
venue filters + the fail-loud closed-candidate resolution operate on the
SAME axis end-to-end. turn_index (when known) links the occurrence
to the role-parser turns list so build_fact_rows re-derives the
speaker scope from the authoritative turn.
TEMPORAL MAPPING: this delta’s spoken_at is an
ENGINE-RELATIVE float (seconds into the stream, e.g. 12.5), NOT a
wallclock. It maps into offset_seconds — the schema’s
engine-relative int audit field, which build_fact_rows already
accepts. It is NEVER emitted as the occurrence’s spoken_at: that
schema column is timestamp_utc and pyarrow silently coerces a float
to microseconds-after-epoch, persisting 1970-01-01 00:00:00.000012+00:00 as the temporal audit marker. spoken_at is
left ABSENT (the column is nullable); a caller holding a genuine
tz-aware wallclock sets it on the occurrence record explicitly —
build_fact_rows fail-louds on any non-tz-aware-datetime value.
class mostlyright.finance.transcripts.streaming_transcriber.Segment(text, is_final, spoken_at, stream_seq, knowledge_time, fact_deltas=)
Section titled “class mostlyright.finance.transcripts.streaming_transcriber.Segment(text, is_final, spoken_at, stream_seq, knowledge_time, fact_deltas=)”Bases: object
One streaming transcript segment — TEXT ONLY (never audio).
is_final is STT-segment finality ONLY (partial vs final text);
it NEVER gates settlement authority. spoken_at is the aired/event-time
wallclock of the window’s start; knowledge_time is the STT-finalization/
publish wallclock (>= spoken_at). fact_deltas is populated
on FINAL segments ONLY.
- Parameters:
fact_deltas: list[FactDelta]
Section titled “fact_deltas: list[FactDelta]”is_final: bool
Section titled “is_final: bool”knowledge_time: float
Section titled “knowledge_time: float”spoken_at: float
Section titled “spoken_at: float”stream_seq: int
Section titled “stream_seq: int”class mostlyright.finance.transcripts.streaming_transcriber.StreamingTranscriber(, transcriber=None, initial_prompt_terms=None, market_terms=None, turn_provider=None, model_size=‘small’)
Section titled “class mostlyright.finance.transcripts.streaming_transcriber.StreamingTranscriber(, transcriber=None, initial_prompt_terms=None, market_terms=None, turn_provider=None, model_size=‘small’)”Bases: object
VAD-chunked streaming STT → partial/final segments + final-only fact deltas.
- Parameters:
- transcriber (
Callable[...,str] |None) – A callable(window_pcm, *, initial_prompt) -> text. Injected so unit tests stub faster-whisper. WhenNone, a lazy faster-whisper transcriber is built (DEFERRED / operator-only path). - initial_prompt_terms (
Sequence[str] |None) – The market strike terms the per-callinitial_promptis seeded from (reusesseed_initial_prompt()). - market_terms (
Sequence[Mapping[str,object]] |None) – Per-term market specs (term_canonicalat minimum) the final-only counter runs over. When empty, no fact deltas are produced. - turn_provider (
Callable[[Segment],Turn|None] |None) – Maps a segment to the role-parserTurn(speaker_role / role_source) driving the fail-closed Kalshi rule. Defaults to anunknown/diarization_advisoryturn (Kalshi-excluded — fail-closed). - model_size (str)
- transcriber (
fact_deltas: list[FactDelta]
Section titled “fact_deltas: list[FactDelta]”All fact deltas emitted this run (final-only) — inspectable by callers.
run(frame_iter)
Section titled “run(frame_iter)”Consume (pcm_frame, spoken_at) frames → yield partial/final Segments.
For each VAD speech run: yields ONE revisable partial per accumulated
window (is_final=False), then ONE final (is_final=True) on the
speech-end boundary. The FINAL carries the STABILISED text of the ENTIRE
run (every window’s transcription, overlap de-duplicated), NOT just the
post-flush tail — so a term spoken early in a continuous run is counted
exactly once. Fact deltas are computed on the FINAL segment only and
appended to fact_deltas (and to the final segment’s
fact_deltas list).
mostlyright.finance.transcripts.streaming_transcriber.TranscribeFn
Section titled “mostlyright.finance.transcripts.streaming_transcriber.TranscribeFn”(window_pcm, *, initial_prompt) -> text. Injected
so unit tests stub it; the production default lazy-imports faster-whisper.
- Type: A transcriber callable
mostlyright.finance.transcripts.streaming_transcriber.TurnProvider
Section titled “mostlyright.finance.transcripts.streaming_transcriber.TurnProvider”A turn provider maps a (partial) segment to the role-parser Turn
whose speaker_role / role_source drive the fail-closed Kalshi rule.
‘s live role attribution supplies this; tests inject a fixed turn.
alias of Callable[[Segment], Turn | None]