How BetaNYC turned two NYC Council AI hearings (October 5 and October 16, 2026) into searchable transcripts and word clouds, and the October 16 one into a panel timeline too. Scripts do the counting. AI assistants did the naming and editing at our direction, and every judgment call needs a source. The nine stages below are the process as we ran it on October 16; October 5 was done more by hand, and the scripts came out of it.
This is BetaNYC's independent record, not the Council's official transcript.
Agenda, committee report and attachments from Legistar, the Council's legislation system. fetch_legistar.py
The hearing video and the Council's own captions, turned into small audio files. fetch_media.py
Deepgram Nova-3 writes the words and groups voices ("speaker 1, speaker 2"). Since October 16 it also gets a short list of this hearing's names. lexicon.txt. The script that sends the audio is in BetaNYC's private workspace; scripts/README.md describes the request.
Who is "speaker 3"? Self-introductions, the chair calling on people, on-screen name labels, captions. The hearing is split into panels too. panels.json
Remove "um"s and false starts, fix spelling. Timestamps and names never change. validate_clean.py
Turns, speakers, captions, talk time, panel timeline. build_hearing.py, build_panels.py
The phrases each group used more than everyone else. build_wordclouds.py
For October 16: names were checked against public sources by an AI assistant, and the ones we could not confirm are listed in the hearing's known gaps. Meaning-changing edits were checked against the captions. A code review and a credibility review went back and forth until both said ship.
The site goes live. Full-quality audio goes in a GitHub Release, and the video goes to the Internet Archive, which can take hours or days to make it playable. Every page links to a correction form, and fixes go back into the inputs and rebuild.
56 of the 248 turns hold more than one voice. Each one is credited to one person and marked mixed.
A general list of BetaNYC names turned a witness's self-introduction into a BetaNYC staff name. So each hearing now gets its own short list, with a source for every term.
Four cleanup edits were undone ("lunch" to "launch", "dictated" to "abdicated"…). Neither Deepgram nor the Council's captions supported them. An edit that changes meaning needs a second source.
A witness's law firm had been guessed from a garbled word. The guess was right, but it stayed off the page until a public source confirmed it.
On-screen name labels were read from still frames of the video, so the spelling on the page matches the screen.
| File | What it is |
|---|---|
transcript/transcript-clean.txt | The readable transcript, with timestamps and names |
transcript/turns.csv | One row per turn, for spreadsheets and charts |
transcript/captions.vtt | Captions with speaker names |
speakers.csv | Who spoke, how many turns, how long |
panels.html | "Who spoke, panel by panel" timeline |
wordclouds/ | "What each group talked about" |
legistar/ | The Council's own documents for the hearing |
Site: betanyc.github.io/hearings-transcripts
Code and step-by-step checklist: github.com/BetaNYC/hearings-transcripts (see docs/PIPELINE.md)
Spot a mistake? Every page has a link to open a correction on GitHub.
BetaNYC · Prepared 2026-10-19. Numbers are from the October 16 hearing data on the repository's main branch.