Meeting summaries were eating 30+ minutes per meeting. I automated the entire process — from recording to action item creation.
Architecture
Zoom/Meet Recording
↓
Whisper (transcription)
↓
Claude API (analysis)
↓
┌─────┼─────┐
↓ ↓ ↓
Email Slack Asana
(summary) (alert) (tasks)
Step 1: Transcription
import whisper
import os
def transcribe_meeting(audio_path):
model = whisper.load_model("base")
result = model.transcribe(audio_path)
# Save transcript
transcript_path = audio_path.replace('.mp3', '_transcript.txt')
with open(transcript_path, 'w') as f:
f.write(result['text'])
return result['text']
For production, I use Whisper API or Otter.ai — faster and handles longer recordings.
Step 2: AI Analysis
import anthropic
def analyze_meeting(transcript, meeting_context=None):
client = anthropic.Anthropic()
context = f"Meeting context: {meeting_context}" if meeting_context else ""
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=2000,
messages=[{
"role": "user",
"content": f"""Analyze this meeting transcript and generate a structured summary.
{context}
Transcript:
{transcript}
Generate the following sections:
## Meeting Summary
2-3 sentence executive summary of what was discussed and decided.
## Key Decisions
Numbered list of decisions made, with who made them.
## Action Items
Table format:
| Task | Owner | Deadline | Priority |
Each action item must have a specific owner and deadline.
## Open Questions
Unresolved items that need follow-up.
## Notable Quotes
Any particularly important statements (with attribution).
## Next Meeting
Suggested agenda items for the next meeting.
"""
}]
)
return response.content[0].text
# Example usage
transcript = transcribe_meeting("weekly_standup_2026-03-25.mp3")
summary = analyze_meeting(transcript, "Weekly engineering standup, Q1 sprint review")
Step 3: Distribution
import smtplib
from email.mime.text import MIMEText
import requests
def distribute_summary(summary, attendees, slack_channel=None):
# Email to all attendees
for attendee in attendees:
msg = MIMEText(summary, 'html')
msg['Subject'] = f"Meeting Summary — {datetime.now().strftime('%B %d, %Y')}"
msg['From'] = "meetings@yourdomain.com"
msg['To'] = attendee['email']
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as server:
server.login(EMAIL, PASSWORD)
server.send_message(msg)
# Slack notification
if slack_channel:
requests.post(SLACK_WEBHOOK, json={
"channel": slack_channel,
"text": f"Meeting summary posted. Action items:\n{extract_action_items(summary)}"
})
def create_tasks(summary):
action_items = parse_action_items(summary)
for item in action_items:
# Create Asana task
requests.post("https://app.asana.com/api/1.0/tasks",
headers={"Authorization": f"Bearer {ASANA_TOKEN}"},
json={
"data": {
"name": item['task'],
"assignee": item['owner_email'],
"due_on": item['deadline'],
"projects": [PROJECT_ID],
"notes": f"From meeting on {datetime.now().strftime('%Y-%m-%d')}\n\n{item['context']}"
}
})
Step 4: Full Pipeline
def process_meeting(audio_path, attendees, meeting_type="general"):
print(f"Processing: {audio_path}")
# 1. Transcribe
transcript = transcribe_meeting(audio_path)
print(f"Transcribed: {len(transcript)} characters")
# 2. Analyze
context = f"{meeting_type} meeting with {len(attendees)} attendees"
summary = analyze_meeting(transcript, context)
print("Analysis complete")
# 3. Distribute
distribute_summary(summary, attendees, slack_channel="#meeting-summaries")
print("Summary distributed")
# 4. Create tasks
create_tasks(summary)
print("Action items created in Asana")
return summary
# Automation: Watch for new recordings
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class MeetingHandler(FileSystemEventHandler):
def on_created(self, event):
if event.src_path.endswith(('.mp3', '.mp4', '.wav')):
# Look up attendees from calendar
attendees = get_meeting_attendees(event.src_path)
process_meeting(event.src_path, attendees)
Results
| Metric | Before | After |
|---|---|---|
| Summary creation time | 30-45 min | 2 min (automated) |
| Action item tracking | "I forgot" | 100% captured |
| Meeting follow-up rate | ~60% | ~95% |
| Time saved per week (10 meetings) | 5-7.5 hrs | 0 hrs (fully automated) |
Production Tips
- Handle audio quality: Whisper struggles with poor audio. Add noise reduction pre-processing.
- Speaker identification: Use pyannote.audio for speaker diarization — critical for attributing action items.
- Retry logic: API calls fail. Build retry with exponential backoff.
- Privacy: Never store raw transcripts longer than needed. Process and delete.
For the complete implementation plus 29 more automation blueprints: AI Automation Playbook — $147
What's your current meeting workflow? Comment and I'll suggest the quickest automation win.
Top comments (0)