Turnkey Automatic Transcription for Zoom, Google Meet, Teams
A retail chain with 200 stores holds 50 meetings per week. Manual minutes take 20 hours. We automated meeting transcription: integration with Zoom, Google Meet, and Teams, STT with diarization, meeting summarization, and structured meeting minutes turnkey. The client saves 15 hours per week on minuting — about 80% of time. Our experience: 10+ years in AI/ML, 40+ projects in transcription for banks, retail, and IT. We guarantee SLA 99.9% and confidentiality under NDA.
Problems We Solve
Built-in transcription platforms have low accuracy with noise or accents (up to 70% errors with overlapping speech), do not distinguish speakers, and do not generate meeting minutes. Meetings without minutes lose tasks and decisions. Our solution closes these gaps: speech recognition accuracy reaches 95%, speaker diarization works even with voice overlap, and business NLP models extract key decisions and tasks.
How We Capture Audio from Conferences Without Delays
We use three approaches: downloading recordings via API (5–10 minute delay), webhooks (auto-start after meeting, <1 minute), and embedded bots (real time). Choice depends on latency requirements and integration complexity. For corporate clients with high-speed requirements, we recommend webhooks — they enable automatic processing start immediately after the meeting ends.
Downloading via API is simple but introduces delay until meeting end:
# Zoom API for downloading recordings
import requests
def download_zoom_recording(meeting_id: str, token: str) -> bytes:
recordings = requests.get(
f"https://api.zoom.us/v2/meetings/{meeting_id}/recordings",
headers={"Authorization": f"Bearer {token}"}
).json()
audio_file = next(
f for f in recordings["recording_files"]
if f["file_type"] == "M4A" # only audio
)
return requests.get(audio_file["download_url"]).content
Zoom Webhooks — auto-start after meeting end:
@app.post("/zoom/webhook")
async def zoom_webhook(request: Request):
data = await request.json()
if data["event"] == "recording.completed":
meeting_id = data["payload"]["object"]["id"]
asyncio.create_task(process_meeting_recording(meeting_id))
Embedded bots for platforms that support app installation (Zoom Apps, Teams Bot).
| Approach |
Latency |
Complexity |
Requirements |
| Download API |
5–10 min |
Low |
API key, storage |
| Webhook |
<1 min |
Medium |
Server, webhook endpoint |
| Bot |
Real time |
High |
Platform support |
Why Speaker Diarization Matters
Speaker diarization determines "who speaks when." Without it, minutes lose context: it's unclear who made a decision or assigned a task. Our method is 2x more accurate than standard solutions (e.g., Zoom's built-in transcription) for meetings with overlapping voices. Accuracy 95% for groups up to 10 participants.
Transcription with Diarization
async def transcribe_meeting(audio_path: str, participants: list[str] = None) -> dict:
transcriber = CallTranscriber()
result = await transcriber.transcribe_call(audio_path)
protocol = await generate_meeting_protocol(result, participants)
return protocol
async def generate_meeting_protocol(transcript: dict, participants: list) -> dict:
"""Generate structured meeting minutes via LLM"""
full_text = "\n".join(
f"{turn['speaker']}: {turn['text']}"
for turn in transcript["turns"]
)
response = await client.chat.completions.create(
model="gpt-4o",
messages=[{
"role": "system",
"content": "Create meeting minutes with sections: Agenda, Key Decisions, Tasks (with assignees and deadlines), Next meeting."
}, {"role": "user", "content": full_text}]
)
return {
"summary": response.choices[0].message.content,
"transcript": transcript,
"participants": participants,
"duration": transcript["duration"]
}
Integration with Microsoft Teams via Graph API
# Download Teams recording via Microsoft Graph
def get_teams_recording(meeting_id: str, token: str) -> bytes:
recordings = requests.get(
f"https://graph.microsoft.com/v1.0/me/onlineMeetings/{meeting_id}/recordings",
headers={"Authorization": f"Bearer {token}"}
).json()
Tech stack: PyTorch for diarization models, OpenAI Whisper for STT, LangChain for LLM orchestration, Pinecone for vector search across transcripts. Everything deploys in the client's isolated environment.
What's Included
- Integration with one platform (Zoom, Meet, or Teams).
- Automatic transcription start after meeting.
- STT with diarization (up to 10 speakers).
- Protocol generation (agenda, decisions, tasks).
- Web interface for viewing and searching transcripts.
- REST API for protocol export.
- Calendar integration (Google Calendar) for automatic meeting link retrieval.
- Documentation and training for 2 users.
- 2 weeks of support.
Comparison with Alternatives
| Solution |
STT Accuracy |
Diarization |
Summarization |
Integration |
| Built-in Zoom |
60-70% |
No (only participant list) |
No |
Only Zoom |
| Otter.ai |
80-85% |
Yes (up to 5) |
Basic |
Limited |
| Our solution |
95% |
Yes (up to 10) |
Business context |
Zoom, Meet, Teams, API |
Implementation Process
-
Analytics: determine platforms, meeting volume, CRM integration needs.
-
Integration: set up webhooks, OAuth, obtain access.
-
Testing: run 10 recordings, calibrate model for accents and noise.
-
Deployment: deploy on client's server or cloud.
-
Training: 2-hour online training for the team.
-
Support: 2 weeks post-launch.
Timelines and Pricing
Integration with one platform — from 1 week. With two or three — up to 3 weeks. Pricing is individual, depending on monthly meeting volume and additional features (e.g., CRM connection). For reference, manual transcription of a one-hour meeting typically costs $50–100 — automation reduces these costs by up to 80%. Contact us for a free project estimate — we'll prepare a proposal within 2 days. Request implementation to save up to 80% of meeting note-taking time.
Zoom API documentation details
Zoom API documentation — used for retrieving recordings. By our estimates, a one-hour meeting costs an average of $75 in manual minute-taking, making automation economically justified.
Our solution is 3x more affordable than Otter.ai for high-volume customers and 2x more accurate than Zoom's built-in transcription.
Speech Recognition and Synthesis: ASR, TTS, Voice Cloning
We tackled a client's challenge: transcribe 40,000 hours of call center recordings in a week. Their existing cloud ASR (Google Speech-to-Text) yielded a WER of 28% on industry-specific vocabulary and cost $0.006 per minute — prohibitively expensive at that volume. The goal was to reduce WER below 10% and switch to self-hosted inference. After deploying a custom pipeline based on Whisper with fine-tuning and faster-whisper inference, the client saved $12,000 per month and achieved a WER of 7.3%.
How does speech recognition ASR handle noisy call center recordings?
The most common issue is not the architecture but the data: noisy audio without level normalization (-23 LUFS instead of standard), mixed languages in one channel, accents, domain-specific vocabulary. Out-of-the-box Whisper large-v3 gives 8–12% WER on clean Russian and drops to 25–35% on recordings with PSTN artifacts and G.711 narrowband codec. By applying loudnorm preprocessing and fine-tuning on 200 hours of labeled data, we consistently cut WER by a factor of 3.
Typical problems we encounter
WER does not converge to the desired metric. Often the culprit is not the architecture but the data: noisy audio without level normalization (-23 LUFS instead of standard), mixed languages in one channel, accents, domain-specific vocabulary. Out-of-the-box Whisper large-v3 gives 8–12% WER on clean Russian and drops to 25–35% on recordings with PSTN artifacts and G.711 narrowband codec.
Diarization fails with more than two speakers. pyannote/speaker-diarization-3.1 works stably for 2–3 speakers, but DER (Diarization Error Rate) increases from 6% to 18–22% with 5+ conference participants. The problem worsens with overlapping speech; by default min_duration_on=0.1 cuts short interjections. We mitigate this with voice-activity detection (VAD) fine-tuning and a custom overlap-handling module.
Voice cloning — latency vs. quality. XTTS v2 (Coqui) delivers natural voice, but during streaming generation stream_chunk_size=20 the first audio chunk arrives after 1.4–2.0 seconds — unacceptable for interactive scenarios. StyleTTS2 and Kokoro are faster but require careful preparation of reference audio.
How do we solve it in practice?
The basic stack for a production pipeline:
-
ASR:
openai/whisper-large-v3 or faster-whisper (CTranslate2 backend, 4× speed vs original)
-
Diarization:
pyannote.audio 3.x + integration via whisperx for word-level alignment
-
TTS: XTTS v2 for quality, Edge-TTS or Silero for low latency
-
Cloning: XTTS v2 (3–6 s reference audio) or OpenVoice v2
A typical call center pipeline: audio from Kafka queue → ffmpeg -af loudnorm normalization to -23 LUFS → faster-whisper with beam_size=5, vad_filter=True → pyannote diarization → post-processing (punctuation via deepmultilingualpunctuation) → write to PostgreSQL with timestamps.
Case study from our practice. A fintech company with 12,000 calls per day. Initial WER on Russian with banking vocabulary — 22% (Google STT). After fine-tuning whisper-medium on 200 hours of labeled recordings via Hugging Face transformers + Seq2SeqTrainer with learning_rate=1e-5, warmup_steps=500 — WER dropped to 7.3%. Inference on a single A10G via faster-whisper with compute_type=float16 processes a 40-minute call in 55 seconds. The client saved over $140,000 annually compared to their previous cloud bill. Contact us for a free pilot estimate to see similar savings on your data.
How to fine-tune Whisper on domain data?
When a general model underperforms, fine-tuning is the first tool. The minimum dataset for noticeable improvement is 20–30 hours of labeled audio in the target domain. Labeling can be iterative: run through the base model → manually fix 10–15% errors → retrain → repeat.
training_args = Seq2SeqTrainingArguments(
per_device_train_batch_size=16,
gradient_accumulation_steps=2,
learning_rate=1e-5,
warmup_steps=500,
max_steps=5000,
fp16=True,
predict_with_generate=True,
generation_max_length=225,
)
Important: during Whisper fine-tuning, freeze the encoder for the first 1000 steps (model.freeze_encoder()), otherwise acoustic features will diverge before the decoder adapts to new vocabulary. We also recommend using CTC beam search decoding with a language model rescoring to further reduce WER by 5–10% relative.
| Model |
WER (clean) |
WER (noisy) |
RTF (A10G) |
Languages |
| Whisper large-v3 |
5.2% |
27% |
0.08 |
99 |
| Wav2Vec2-XLSR-53 |
6.8% |
32% |
0.12 |
143 |
| Google STT (cloud) |
7.0% |
28% |
– |
125 |
| DeepSpeech 0.9.3 |
11.5% |
41% |
0.06 |
8 |
Our fine-tuned Whisper models consistently outperform cloud ASR on domain-specific data — 3× WER improvement in the fintech case.
Speech synthesis: How to choose a model for your task?
| Model |
Latency (TTFB) |
Naturalness MOS |
Cloning |
Languages |
| XTTS v2 |
1.2–2.0 s |
4.1–4.3 |
Yes, 3 s reference |
17 |
| StyleTTS2 |
0.3–0.6 s |
4.0–4.2 |
Yes, requires adaptation |
en, + fine-tune |
| Kokoro-82M |
0.08–0.15 s |
3.7–3.9 |
No |
en, ja |
| Silero TTS |
0.05–0.1 s |
3.4–3.6 |
No |
ru, en, de, etc. |
| Edge-TTS |
~0.4 s (cloud) |
4.0 |
No |
100+ |
For interactive bots requiring TTFB < 300 ms — Silero or Kokoro. For content narration where naturalness is key — XTTS v2 with streaming via WebSocket.
Our process and deliverables
We start with an audit session: take 2–4 hours of your recordings, run them through several models, measure WER/CER, analyze error distribution by type (lexical, acoustic, language). This takes 1–2 days and immediately shows whether fine-tuning is needed or just post-processing.
Next, we choose the architecture for your throughput: one GPU for 1,000 min/day or a cluster with a load balancer for 100,000+ min/day. Deployment via Docker container with FastAPI or Triton Inference Server for batched inference.
What you get after engagement:
- Trained model with model card and evaluation report
- Docker image with optimized inference pipeline
- API documentation and integration examples
- Performance dashboard (Grafana) with latency P99, GPU utilization, WER tracking
- 30-day post-deployment support and hotfixing
Timelines depend on complexity:
- Basic integration of a ready model — 1–2 weeks
- Fine-tuning with data preparation and validation — 4–8 weeks
- Full voice pipeline (ASR + diarization + TTS + monitoring) — 2–4 months
Project investments typically range from $20,000 to $80,000. Get a free estimate and a detailed cost breakdown for your specific case.
Our team has 12+ years of experience in speech AI and has deployed 60+ production ASR/TTS systems delivering reliable performance. Guarantee: WER below 10% on your data or we continue fine-tuning at no extra cost.
Schedule a consultation with our speech recognition engineers — we'll help you choose the right stack and provide a transparent cost breakdown.