Skip to content

About

Node.js CLI + Express API that turns sales call recordings into objections, deal sizes and action items with Gemini audio, and logs them to Notion.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

3 Commits

Folders and files

Repository files navigation

Sales Call Transcript Summarizer

Turn sales call recordings into a CRM-ready debrief: key objections, deal size and action items, plus BANT qualification, deal health, coaching tips and a follow-up email draft. Built on Gemini audio, with an Express API and Notion logging.

recording.mp3 ─► Gemini transcribes (speakers + timestamps) ─► Gemini extracts insights (JSON schema)
              ─► deal math + health score ─► Markdown / JSON / CSV ─► Notion page (optional)

What you get per call

Objections Category (price, budget, timing, authority, competitor, security...), exact buyer quote + timestamp, severity, how the rep answered, resolved or not, and a better answer to use next
Deal size Amount, currency and period as spoken; annual value and total contract value computed in code (e.g. $4,500/mo × 12), seats, the basis and the quote it came from
Action items Task, owner (seller/buyer), due date resolved from the call date ("next Thursday" → 2026-11-05), priority
Deal intel BANT, decision makers and process, competitors, timeline, risks, stage, sentiment, win probability
Deal health A rule-based 0-100 score (BANT coverage, open objections, next meeting, sentiment, competition) with its reasons, as a second opinion next to the model's win probability
Follow-up email Recap email that answers the open objections and confirms next steps

Outputs: <date>-<call>.md (readable report), .json (everything), .transcript.txt, .actions.csv, and a folder-wide calls.csv index for Excel or CRM import.

Quick start

npm install
node bin/call-summarizer.js demo          # offline sample, no keys needed -> output/demo/
cp .env.example .env                      # add GEMINI_API_KEY (free: https://aistudio.google.com/apikey)
node bin/call-summarizer.js doctor        # checks Node, Gemini and Notion
node bin/call-summarizer.js summarize recordings/acme-2026-10-28.mp3

Requires Node 20+.

Commands

call-summarizer summarize <files or folders...>   # alias: run
    -o, --out <dir>            output folder (default output/)
    -c, --context <text>       what you sell (better objection answers + email); default SELLER_CONTEXT
    -d, --date <yyyy-mm-dd>    call date; default: date in file name, else file time
    -l, --language <name>      spoken-language hint, e.g. German
    --output-language <name>   language of the summary/email
    --currency <code>          when a number is said without a currency
    --notes <text>             rep notes added to the prompt
    -n, --notion [--replace]   create a Notion page (replace = recreate an existing one)
    --refresh | --no-cache     redo Gemini calls / skip the cache
    --mime <type>              force a MIME type for odd extensions
    -f, --format md,json,csv,txt   --no-write   --json   --concurrency <n>
call-summarizer transcribe <files...>   # transcript only
call-summarizer demo [--notion]         # sample call; --notion tests your Notion setup
call-summarizer serve [--port 3000]     # Express API + upload page
call-summarizer doctor
call-summarizer notion-setup            # adds the recommended columns to your database
call-summarizer history [--json]

Inputs: audio mp3 wav m4a aac ogg opus flac aiff, video mp4 mov webm mkv (Zoom/Meet/Teams exports), or existing transcripts txt md vtt srt json (these skip transcription). Files up to 14 MB are sent inline; larger ones go through the Gemini Files API automatically (deleted right after).

Cache: transcripts are cached by audio hash + model, analyses by transcript + options, in data/cache/. Re-running a call is free, and changing --context only redoes the analysis, not the transcription.

Notion

  1. Create an internal integration at https://www.notion.so/profile/integrations and copy the secret into NOTION_TOKEN.
  2. Create a database (any title column works), open ... → Connections → add your integration.
  3. Put the database URL or ID in NOTION_DATABASE_ID, then run notion-setup to add the columns: Company, Call Date, Call Type, Stage, Deal Size, Annual Value, Currency, Win Probability, Health Score, Health, Sentiment, Objections, Open Objections, Action Items, Next Step, Next Meeting, Competitors, Summary, Source, Call ID.
  4. summarize <file> --notion. Each call becomes a page with the debrief, objections (with quotes and suggested answers), action items as checkboxes, BANT, the follow-up email and the full transcript.

Only columns that exist with the right type are filled, so you can delete the ones you don't want. Pages are de-duplicated by Call ID (--replace recreates). If Notion fails, the local report is still written and the command exits with code 1.

HTTP API (serve)

Method Path Body
GET / Drag-and-drop upload page
POST /api/calls multipart file + optional context, callDate, language, outputLanguage, currency, notes, notion=true, replace=true
POST /api/calls/text JSON { "transcript": "...", "title": "...", "callDate": "2026-10-28", ... }
GET /api/calls?limit=50 Recent calls
GET /health Status

Add ?format=md for a Markdown answer or ?transcript=1 to include the transcript in the JSON. Set API_TOKEN before exposing the server; clients then send Authorization: Bearer <token> (or x-api-key).

curl -H "Authorization: Bearer $API_TOKEN" -F file=@call.mp3 -F notion=true http://localhost:3000/api/calls

This makes it easy to plug into Zapier, Make or n8n (for example: new Zoom recording → POST to /api/calls → Notion + Slack).

Docker: docker build -t call-summarizer . && docker run -p 3000:3000 --env-file .env -v calls:/data call-summarizer

How it works

  • src/gemini.js – Gemini REST client: inline or resumable Files API upload, retries on 429/5xx (honours retryDelay), one switch to GEMINI_FALLBACK_MODEL on overload or daily quota.
  • src/prompts.js – transcription prompt, extraction rules and the JSON responseSchema.
  • src/analysis.js – cleans the model output, does the deal math and the health score (the model never does arithmetic).
  • src/transcript.js – VTT/SRT/JSON transcript import and talk ratio.
  • src/notion.js – schema-aware properties, page blocks (2,000-char chunks, 100-block batches), dedup, notion-setup.
  • src/pipeline.js, src/store.js, src/format.js, src/server.js, bin/call-summarizer.js.

Tests

npm test

51 tests with node:test. All Gemini and Notion calls are faked, so no keys are needed.

License

MIT

About

Node.js CLI + Express API that turns sales call recordings into objections, deal sizes and action items with Gemini audio, and logs them to Notion.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages