A Cassini portable meeting is an ordinary .opus file. Any player plays it,
because that is all it is: Ogg Opus, 48 kHz. It also carries its own
word-timestamped transcript, the speakers, and a record of what produced the
text, in the OpusTags header, where a player that does not care ignores them.
The website is https://format.gocassini.com/. Everything on it is built from this repository.
SPEC.md: the specification. Version 1, published 2026-09-02.spec/: the two JSON Schemas; the transcript body (cassini-words-v1.md); the audio digest (cassini-opus-audio-integrity-v1.md); the conformance suite; and the private drafts that came before version 1.tools/: small readers and a producer in Python and JavaScript, standard library only, meant to be copied.site/: the website, and undersite/static/demo/a real file to check against.design/: the measurements and arguments behind the non-obvious parts. Some files are historical and not published on the site.LICENSE.md: CC-BY-4.0 prose, CC0 everything an implementer copies.
The site lists every tool, with its language and licence, at https://format.gocassini.com/build/, including a browser reader that needs no install. From this repository:
tools/cassini-extract.py meeting.opus --tags # the descriptor tags
tools/cassini-extract.py meeting.opus --list # which transcripts are inside
tools/cassini-extract.py meeting.opus # the manifest as JSON
tools/cassini-read-pure.py meeting.opus # no ffprobe: parses the container itselfVersion 1, published 2026-09-02, simplified 2026-09-07. The change history is in
CHANGELOG.md.
Two layers of metadata. The first is plain comments any tool shows: TITLE,
CASSINI_SPEAKER_COUNT, CASSINI_AUDIO_OPUS_SHA256. The second is a JSON
manifest, gzipped, base64url-encoded and split across numbered comments. Each
transcript body is a second such payload under its own prefix.
CASSINI_FORMAT=org.cassini.portable-meeting/1
CASSINI_PAYLOAD_ENCODING=base64url+gzip+utf8json
CASSINI_PAYLOAD_CHUNK_COUNT=1
CASSINI_PAYLOAD_SHA256=a4d048386f81bd4b...
CASSINI_PAYLOAD_000=H4sIAAAAAAAC_61W227jNhD9...
CASSINI_TX_SCRIPT_PAYLOAD_CHUNK_COUNT=3
CASSINI_TX_SCRIPT_PAYLOAD_000=H4sIAAAAAAAC_...
CASSINI_DECODE_HINT=Concatenate CASSINI_PAYLOAD_000..N for the manifest; ...
CASSINI_DECODE_HINT is there so that someone with ffprobe and no
documentation still gets the transcript out. A message in a bottle.
Three commitments run through it:
- Progressive enhancement. A player that understands nothing plays the audio. A reader that understands the tags gets everything.
- Keep what a better model could use later. The words a recogniser produced survive next to derived display text, with provenance saying what made each.
- The digest is a join key, not a seal. A SHA-256 over the Opus packets says whether this transcript describes this recording. It catches accidents, not adversaries.
gocassini is the reference implementation: it records
a meeting, transcribes it and packs the result into one of these files. It is
open source and ships as a
Nextcloud app. The readers in
tools/ and on the site are the others. If you build one, say so: a format that
only one program reads is not really a format.
Issues and pull requests welcome.