Instructions to use Trelis/tiron with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Trelis/tiron with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("automatic-speech-recognition", model="Trelis/tiron")# Load model directly from transformers import AutoProcessor, AutoModelForSpeechSeq2Seq processor = AutoProcessor.from_pretrained("Trelis/tiron") model = AutoModelForSpeechSeq2Seq.from_pretrained("Trelis/tiron", device_map="auto") - Notebooks
- Google Colab
- Kaggle
Tiron
Released 21 July 2026.
Tiron is a multi-speaker meeting transcription model. It jointly transcribes and attributes speech to speakers in a single decoding pass: for each 30-second audio window it emits an inline transcript with <|speakerN|> turn markers (up to 8 speakers per window) and <|t.tt|> timestamps.
Tiron uses the Whisper large-v3 architecture with an extended token vocabulary (<|speaker1|> β¦ <|speaker8|>, <|nospeech|>). It is a drop-in WhisperForConditionalGeneration checkpoint.
Tiron is state of the art for whole-meeting transcription β among systems that reliably transcribe entire meetings, it leads every test set we evaluated (see Benchmarks).
For whole meetings (beyond a single 30s window), use the open-source harness at TrelisResearch/tiron, which adds chunking, cross-window speaker linking (ECAPA voice embeddings), and SRT/VTT/JSON output.
Benchmarks
Tiron is state of the art for whole-meeting transcription: among systems that can reliably transcribe an entire meeting end to end, it leads every test set we evaluated.
The closest such rival is AssemblyAI universal-3-pro (in its best diarized configuration), so we report the head-to-head against it below. Google's Gemini Pro is a strong short-clip transcriber β competitive with Tiron on short (~6 min) meetings β but degrades sharply on longer audio, truncating or failing outright on the longer ICSI and NOTSOFAR meetings, so it cannot be scored across full meeting corpora.
Pooled corpus cpWER (lower is better) on held-out meeting test sets, scored with identical references and normalization for every system:
| Test set | AssemblyAI universal-3-pro | Tiron | Ξ |
|---|---|---|---|
| AMI (4 meetings) | 39.49 | 35.24 | β4.3 pts (β11%) |
| ICSI (3 meetings) | 34.64 | 20.91 | β13.7 pts (β40%) |
| NOTSOFAR-1 (10 meetings) | 38.62 | 37.55 | β1.1 pts (β3%) |
| Macro (mean of corpora) | 37.58 | 31.23 | β6.4 pts (β17%) |
Meetings evaluated (whole-meeting audio, far-field where applicable):
- AMI:
ES2004a,IS1009a,TS3003a,EN2002a - ICSI:
Bmr013,Bmr018,Bro021 - NOTSOFAR-1:
MTG_32040,MTG_32063,MTG_32072,MTG_32074,MTG_32092,MTG_32179,MTG_32185,MTG_32256,MTG_32257,MTG_32322
Scoring notes: cpWER is concatenated-permutation WER over whole meetings (transcription and speaker-attribution errors both count). Each corpus figure is pooled β total errors Γ· total reference words across that corpus's meetings β and the macro is the mean of the three corpus figures. On NOTSOFAR-1, stretches the human annotators marked <UNKNOWN/> (unintelligible) are masked from both hypothesis and reference for every system, so no system is rewarded for staying silent there. AMI and ICSI are unaffected by this mask.
Numbers are from a single decoding run. Tiron's speaker-count estimation has run-to-run variance, so an individual meeting's cpWER can move by a point or two between runs (occasionally more on a hard meeting); corpus figures are correspondingly stable to about Β±1 point. Expect small differences when reproducing.
Output format
Per 30-second window the model emits speaker blocks with within-window timestamps:
<|speaker1|><|0.00|> Thanks everyone for joining.<|2.96|><|3.52|> Let's get started.<|4.80|><|speaker2|><|2.98|> Morning!<|3.40|>
Speaker indices are local to the window (first speaker to talk is <|speaker1|>). The harness links speakers across windows into stable meeting-level identities using ECAPA voice embeddings.
Usage with transformers (single window, β€30s)
import torch
import soundfile as sf
from transformers import WhisperProcessor, WhisperForConditionalGeneration
repo = "Trelis/tiron"
processor = WhisperProcessor.from_pretrained(repo)
model = WhisperForConditionalGeneration.from_pretrained(
repo, torch_dtype=torch.bfloat16
).to("cuda").eval()
# Tiron drives decoding itself β disable Whisper's default token suppression.
model.config.forced_decoder_ids = None
model.config.suppress_tokens = []
model.config.begin_suppress_tokens = []
gc = model.generation_config
gc.forced_decoder_ids = None
gc.language = None
gc.task = None
gc.suppress_tokens = None
gc.begin_suppress_tokens = None
if hasattr(gc, "no_timestamps_token_id"):
delattr(gc, "no_timestamps_token_id")
gc.no_speech_threshold = None
tok = processor.tokenizer
audio, sr = sf.read("clip.wav", dtype="float32") # 16 kHz mono, up to 30s
feats = processor.feature_extractor(
audio, sampling_rate=16000, return_tensors="pt"
).input_features.to("cuda", torch.bfloat16)
prefix = [
tok.convert_tokens_to_ids("<|startoftranscript|>"),
tok.convert_tokens_to_ids("<|en|>"), # or any Whisper language token
tok.convert_tokens_to_ids("<|transcribe|>"),
]
with torch.no_grad():
out = model.generate(
input_features=feats,
decoder_input_ids=torch.tensor([prefix], device="cuda"),
max_new_tokens=444,
do_sample=False,
num_beams=1,
)
# Render speaker + timestamp tokens inline. Whisper's built-in decoders show
# EITHER timestamps OR added tokens, not both, so walk the ids directly:
ts_begin = tok.convert_tokens_to_ids("<|notimestamps|>") + 1 # <|0.00|>
ts_end = tok.convert_tokens_to_ids("<|30.00|>")
skip = {tok.convert_tokens_to_ids(t) for t in
("<|startoftranscript|>", "<|en|>", "<|transcribe|>", "<|endoftext|>")}
parts, buf = [], []
def flush():
if buf:
parts.append(tok.decode(buf)); buf.clear()
for tid in out[0].tolist():
if tid in skip:
continue
name = tok.convert_ids_to_tokens(tid)
if name and name.startswith("<|speaker"):
flush(); parts.append(name)
elif ts_begin <= tid <= ts_end:
flush(); parts.append(f"<|{(tid - ts_begin) * 0.02:.2f}|>")
else:
buf.append(tid)
flush()
print("".join(parts)) # <|speaker1|><|0.02|> ... <|2.38|><|speaker2|> ...
(Whisper's decode(..., decode_with_timestamps=True) renders timestamps but strips the <|speakerN|> tokens, and plain decode(..., skip_special_tokens=False) does the reverse β hence the small manual walk above. The harness does this for you, and also links speakers across windows.)
Usage with the harness (whole meetings)
The Tiron harness runs the full meeting pipeline: 30s chunking with an onset guardrail, per-chunk decoding, ECAPA-based cross-chunk speaker linking (with an optional second staggered decode pass that calibrates the clustering threshold per meeting β on by default, as benchmarked above), and stable SPEAKER_XX labels.
git clone https://github.com/TrelisResearch/tiron
cd tiron && pip install -e .
tiron meeting.wav --output transcript.json # JSON segments
tiron meeting.wav --format srt --output meeting.srt # subtitles
Python API:
from tiron import TironEngine
engine = TironEngine("Trelis/tiron") # cuda/mps/cpu auto-detected
result = engine.transcribe("meeting.wav", language="auto")
for seg in result["segments"]:
print(f'[{seg["start"]:7.2f}β{seg["end"]:7.2f}] {seg["speaker"]}: {seg["text"]}')
Each segment is {"speaker": "SPEAKER_00", "start": ..., "end": ..., "text": ...} with meeting-global speaker labels and timestamps on the original file timeline.
The harness uses the same grammar-constrained decoding as Trelis' hosted serving (default on) and reproduces the benchmark configuration above (validated across the full test set, each corpus within ~0.2 pooled cpWER of the reference run).
Limitations
- The model's native window is 30 seconds; whole-meeting quality depends on the harness' cross-window speaker linking.
- Up to 8 speakers per 30s window and 8 global speakers per meeting.
- Speaker labels are anonymous (
SPEAKER_00, β¦); the model does not identify speakers by name or voice enrollment. - Timestamps are decoded at 20ms resolution but are approximate, especially under heavy overlap.
License
Apache 2.0.
- Downloads last month
- 22
