offmute: a Gemini pipeline for meeting audio that splits into 10 minute chunks and 4 screenshots
An experiment in meeting transcription and diarization with just an LLM. Maybe I went a little overboard though
At a glance
- What is it?
- SouthBridgeAI's 0.1.15 transcription and diarization experiment, written by its author as something he may have gone overboard on. What the deprecated tier flag, the per-stage models and the packaging details actually commit you to.
- Who is it for?
- offmute is worth reading as a working example of a chunked multimodal pipeline rather than as a transcription product you can rely on today: it is version 0.1.15, its own repository ships a PROBLEMS.md and a TODO.md beside the README, and the pipeline description in the page stops at its first step.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Activity is slowing. The repository last received commits 6 months ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 4, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Six legacy tiers survive behind a flag marked deprecated
The model selection went through a migration and both systems are still wired up. The CLI exposes `-m, --model` with three values, pro, flash and flash-lite, defaulting to pro, and the older `-t, --tier` flag is explicitly marked deprecated with a pointer to the model flag. The six tiers behind it are not just aliases, because they mix models per stage. The business tier uses Gemini 2.0 Pro for description and report but Gemini 2.0 Flash for transcription. The budget tier inverts the emphasis, using Gemini 2.5 Flash for description and Flash Lite for transcription and report. The first and economy tiers use one model throughout, and the two experimental tiers target Gemini 2.5 Pro Preview and Flash Preview. The module API keeps the old flexibility, since each call takes its own model names.
import {
generateDescription,
generateTranscription,
generateReport,
} from "offmute";The option object shown below that import passes screenshotModel, audioModel, mergeModel and transcriptionModel separately, which the CLI no longer exposes.
The audio path needs an ffmpeg binary no install step provides
Five runtime dependencies are declared and one of them is a wrapper rather than a program. @google/generative-ai does the model calls, commander parses the options, cli-progress draws the progress bar and chalk colours the output. The fifth, fluent-ffmpeg, is a Node binding that shells out to an ffmpeg binary expected to be present on the machine. Nothing in the installation section mentions it: the CLI route is `npx offmute <Meeting_Location> <options>` and the package route is `npm install offmute`, with a note that bunx or bun runs faster if you have it. So a machine without ffmpeg installed gets a failure from a child process rather than a dependency error at install time, which is the harder failure to diagnose. Since chunking, screenshot extraction and the intermediate audio files all sit downstream of that call, everything else in the pipeline depends on a system package the page never names.
The build moves declaration files with shell commands
The package build is one npm script and it ends with mv and cp, which means it assumes a POSIX shell.
"build": "tsup src/index.ts src/run.ts && tsc --emitDeclarationOnly --declaration --declarationDir dist && mv dist/index.d.ts dist/index.d.mts && cp dist/index.d.mts dist/index.d.cts"TypeScript emits a single index.d.ts, and the script renames it to .d.mts and then copies it to .d.cts, because the package declares "type": "module" while still shipping a CommonJS build at ./dist/index.cjs alongside the ESM entry at ./dist/index.js. Both branches of the exports map point their types at the .d.cts file, so an ESM consumer receives the CommonJS-flavoured declaration. The published contents are limited to dist and package.json by the files array, and a .npmignore sits at the root as a second, older mechanism doing a similar job. The repository default branch is master and there are no published releases, so the version history is whatever the changelog and the tag list say.
Intermediates live in a temporary directory unless you ask to keep them
File handling is the tidiest part of the tool and it is worth knowing the layout before debugging anything. By default the pipeline writes into a system temporary directory and removes it when processing finishes, which is why the page advertises a clean filesystem as a feature. Two flags change that: --save-intermediates keeps them, and --intermediates-dir puts them somewhere you choose. When saved, the layout mirrors the pipeline stages.
.offmute_meeting/
├── screenshots/ # Video screenshots
├── audio/ # Processed audio chunks
├── transcription/ # Per-chunk transcriptions
└── report/ # Report generation dataThe directory is named after the input file in a hidden form, so two recordings with the same base name in different directories collide. The other behaviour to know about is incremental writing: output files are created early and updated as work proceeds, so a long run leaves partial transcripts and a partly built report behind while it is still going.
Four screenshots and ten minute chunks are the defaults that shape the cost
Two numeric defaults control how much of a meeting reaches the model, and both are adjustable on the command line. --screenshot-count defaults to 4, which is the sampling rate for video frames, and --audio-chunk-minutes defaults to 10, which is the length of each audio chunk. The page shows the levers being pushed in both directions: -sc 8 for visual-heavy workshop material and -ac 20 for presentations where a single chunk can hold the content. Neither example is a benchmark, they are illustrations of intent, but the shape is clear. Four screenshots across a one hour meeting will miss most slide changes, which matters because one of the advertised capabilities is recognising when a demo is being displayed. Chunk length is the other half, since transcription happens per chunk and the report is built from the merged result.
Speaker identification is offered as an attempt, not a guarantee
The feature list is written with more precision than the marketing-style bullets around it suggest. Transcription and diarization are the core promise, converting audio or video to text while identifying different speakers. Speaker identification is described as attempting to name speakers and their roles where possible, and the repository description itself calls the whole thing an experiment in meeting transcription and diarization with just an LLM. There is no accuracy figure, no comparison against a dedicated diarization model and no statement about what happens when two people share a microphone. The -i flag is the lever for this, and the examples show it used for tone, emotion and hesitation detection as well as domain focus, which is a reminder that the same prompt controls both transcription and interpretation.
The pipeline description stops at its first step
The section that should explain how the stages fit together is the one that ends earliest. The pipeline is introduced as multi-stage, and the numbered list begins with a single line starting with the letters Con before the page ends, so the stages are named in the feature list and implied by the intermediate directory layout but never actually described in sequence. What a reader can reconstruct is that screenshots, audio chunks and per-chunk transcriptions all feed a merge step, and that the report is generated last from the merged material, with the deprecated tier names confirming that description, merge and report stages used to be model-selectable independently. Two files at the root probably carry the rest: PROBLEMS.md and TODO.md, both committed alongside the README, which is a more honest signal of the project's state than the feature bullets.
Version 0.1.15 on master, with no release history to check
The maturity signals are consistent. The package version is 0.1.15, the default branch is master, no GitHub releases exist, and the last commit on the repository dates from 2026-04-08. The author field names a single maintainer, and the package description ends with a line about having gone a little overboard. Against that, the CLI surface is unusually complete for a pre-1.0 tool: eleven documented options, a help command, incremental progress output that can be watched section by section, three model choices and instructions that reach the prompts. The gap to keep in mind is not feature count but the boundary. This tool uploads meeting audio and video to a hosted model, and the page says nothing about retention, whether the audio is used for training, or where the processing happens.
Editorial conclusion
offmute is worth reading as a working example of a chunked multimodal pipeline rather than as a transcription product you can rely on today: it is version 0.1.15, its own repository ships a PROBLEMS.md and a TODO.md beside the README, and the pipeline description in the page stops at its first step. Use it if you want to see how audio chunking, screenshot sampling and incremental report writing are wired to a single model API, and if sending meeting recordings to a hosted model is acceptable for your data. Check three things first. Audio processing goes through the fluent-ffmpeg wrapper, which needs an ffmpeg binary on the machine that no install step mentions. Speaker naming is described as an attempt, so do not plan a directory of contacts around it. And nothing in the page addresses what happens to the audio once uploaded, which for meeting recordings is the question to answer before anyone runs this on a real call.
Frequently asked questions
What does offmute use to transcribe a meeting?
Google's Gemini models, chosen with --model. Pro maps to Gemini 2.5 Pro and is the default, flash to Gemini 2.5 Flash and flash-lite to Gemini 2.5 Flash Lite. The API key is read from the GEMINI_API_KEY environment variable.
Can I use offmute as a library instead of the CLI?
Yes. generateDescription, generateTranscription and generateReport are exported from offmute, and the options object takes per-stage models such as screenshotModel, audioModel, mergeModel and transcriptionModel, together with showProgress and userInstructions.
How does offmute split a long meeting?
Audio is chunked at 10 minutes by default through --audio-chunk-minutes, and 4 screenshots are sampled from video by default through --screenshot-count. Intermediates go to a temporary directory that is cleaned up unless --save-intermediates is passed, in which case they land in a hidden directory named after the input file with screenshots, audio, transcription and report subdirectories.
Is the offmute --tier flag still supported?
It is marked deprecated and still works, with six legacy tiers named first, business, economy, budget, experimental and experimentalBudget, each mapping to a different mix of Gemini 2.0 and Gemini 2.5 Preview models. The page points new usage at --model instead.
What happens to a meeting recording uploaded to offmute?
The page does not address it. It states that the recording is processed by Gemini for transcription, diarization, visual analysis and report generation, and says nothing about retention, training use or where the processing takes place.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/southbridgeai-offmute)