A NYC Council hearing is public, but it is hours of video. This guide shows how to turn one into a transcript that says who spoke, when, and about what. It is the process BetaNYC used for the October 16, 2026 hearing on AI, built on what we learned doing the October 5 hearing by hand. The method is open. Take it, use it, and tell us what to fix. BetaNYC's transcripts are our independent record, not the Council's official transcript.
Find the hearing on the Council's Legistar calendar. Download the agenda and the committee report. The report usually names who was invited to testify. Come back a day or two later. Written testimony is often posted after the hearing.
Our script for this: fetch_legistar.py (needs a Legistar API token, which you ask the Council for).
The video link appears on the hearing page once the hearing is over. Keep the Council's captions too. They are rough, but they are a second witness to what was said.
Our script for this: fetch_media.py (video, captions and small audio files).
Write down this hearing's names: Council Members, witnesses, groups, and the products or terms that keep coming up. Take them only from the hearing's own papers. Speech-to-text gets names wrong, and a short list helps it get them right.
Send the audio to a service that does "diarization," meaning it splits the audio by voice: "speaker 1, speaker 2." You get words and times, but no names yet. Save the full response so you never pay for the same run twice.
What we sent Deepgram: scripts/README.md, section 3.
Who is "speaker 3"? Look for clues: people saying their own names, the chair calling on someone, the oath, Zoom name tiles, and the Council's captions. (At our two hearings, the Council's on-screen banner showed only the Speaker.) An AI assistant can do the first pass if you give it the hearing's papers. Then check each name against a source in step 8.
Most hearings have parts: opening statements, the City's panel, invited witnesses, then the public. Write down when each part starts and ends. This is what lets you see who got the floor, and for how long.
Take out "um"s, stutters and false starts. Fix spelling. Keep each speaker's grammar as they said it. Never change a time or a name. Keep the unedited version next to the clean one, so anyone can compare.
Our clean-up prompt
· our checker: validate_clean.py
Check each person's name and group against the Council's records, posted testimony, or the group's own website. Write down where you checked. If you can't confirm it, say so on the page.
Say who did the checking, too. For October 16, an AI assistant checked names against public sources. Elected officials were checked against the Council's records. Our pages say that other names were not each verified by a person.
Now you can count. Count each speaker's talk time. Draw a timeline of the parts of the hearing. Make word clouds of the phrases each group used more than everyone else.
Our scripts: build_hearing.py, build_panels.py, build_wordclouds.py
· example: October 16 word clouds
One reviewer reads the code and the pages as a stranger would, looking for what breaks. Another checks every name, number and claim against its source. Fix, then send it back to both, until both say it is ready. Then open every page in a browser yourself.
Put the pages online. GitHub Pages is free. Save the video to the Internet Archive (free, with an account) so it outlasts any one website. We put the full-quality audio in a GitHub Release. Check that you may re-host the video; our license covers only what we made. Always link back to the Council's official video, and say plainly that yours is not the Council's official transcript. Give every page a way to report a mistake, and fix the inputs, not the finished page.
A transcript helps you find a moment. Quote from the video, after you check it.
Scripts handle times, counts and checks. A name or an edit that changes meaning needs a source, and the page says who checked it: a person or an AI assistant.
Publish the unedited transcript next to the clean one, the word list you sent the speech-to-text service, and where your names came from.
A missing surname or an unconfirmed group gets a note on the page, not a guess.
Full checklist with every command: docs/PIPELINE.md
Finished transcripts to learn from: betanyc.github.io/hearings-transcripts
The whole process on one page: how we turn a hearing into an open transcript
The code is MIT licensed, and the transcripts and data BetaNYC made are CC BY 4.0. The Council's video and captions are the Council's. Spot a mistake, or decoded a hearing of your own? Open an issue.
BetaNYC · Prepared 2026-10-19. Two things are not public: the script that sends audio to Deepgram, which lives in BetaNYC's private workspace, and our raw working files (the Deepgram output and speaker labels). scripts/README.md describes the Deepgram request, so you can make it yourself. You can check our transcripts against the Council's video, but you can't rerun our hearings from scratch.