Systems Library / AI Capabilities / How to Create an AI Meeting Recording Analyzer
AI Capabilities voice audio

How to Create an AI Meeting Recording Analyzer

Analyze meeting recordings for action items, sentiment, and key decisions.

Jay Banlasan

Jay Banlasan

The AI Systems Guy

An ai meeting recording analysis system extracts insights from every meeting automatically. I build these for teams running 10+ meetings per week where action items get lost and decisions go untracked. The system transcribes the recording, identifies who said what, extracts decisions, action items, and follow-ups, then delivers a structured summary before the next meeting starts.

No more "what did we decide in that meeting?"

What You Need Before Starting

Step 1: Transcribe with Speaker Labels

import whisper

model = whisper.load_model("medium")

def transcribe_meeting(audio_path):
    result = model.transcribe(audio_path)
    return {
        "text": result["text"],
        "segments": result["segments"],
        "duration_minutes": round(result["segments"][-1]["end"] / 60, 1) if result["segments"] else 0
    }

Step 2: Extract Meeting Intelligence

import anthropic
import json

client = anthropic.Anthropic()

def analyze_meeting(transcript_text, meeting_title, attendees=None):
    attendee_context = f"Attendees: {', '.join(attendees)}" if attendees else ""

    response = client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=1000,
        messages=[{
            "role": "user",
            "content": f"""Analyze this meeting transcript and extract structured intelligence.

Meeting: {meeting_title}
{attendee_context}

Extract:
1. SUMMARY: 3-sentence meeting summary
2. DECISIONS: List every decision made (who decided, what was decided)
3. ACTION ITEMS: List every task assigned (who, what, deadline if mentioned)
4. OPEN QUESTIONS: Unresolved questions that need follow-up
5. KEY TOPICS: Main topics discussed with time estimate per topic
6. SENTIMENT: Overall meeting tone and any tension points
7. FOLLOW-UPS: Meetings or check-ins that were scheduled

Transcript:
{transcript_text[:8000]}

Respond as JSON."""
        }]
    )
    return json.loads(response.content[0].text)

Step 3: Generate the Meeting Summary

def format_meeting_summary(analysis, meeting_title):
    summary = f"# Meeting Summary: {meeting_title}\n\n"
    summary += f"## Summary\n{analysis.get('summary', 'No summary available.')}\n\n"

    if analysis.get("decisions"):
        summary += "## Decisions Made\n"
        for d in analysis["decisions"]:
            summary += f"- {d}\n"
        summary += "\n"

    if analysis.get("action_items"):
        summary += "## Action Items\n"
        for item in analysis["action_items"]:
            summary += f"- [ ] {item}\n"
        summary += "\n"

    if analysis.get("open_questions"):
        summary += "## Open Questions\n"
        for q in analysis["open_questions"]:
            summary += f"- {q}\n"

    return summary

Step 4: Build the Processing Pipeline

import os

def process_meeting(audio_path, meeting_title, attendees=None, output_folder="meeting_notes"):
    os.makedirs(output_folder, exist_ok=True)

    transcript = transcribe_meeting(audio_path)
    analysis = analyze_meeting(transcript["text"], meeting_title, attendees)
    summary = format_meeting_summary(analysis, meeting_title)

    slug = meeting_title.lower().replace(" ", "-")[:40]
    summary_path = os.path.join(output_folder, f"{slug}_summary.md")
    with open(summary_path, "w") as f:
        f.write(summary)

    save_meeting_analysis(meeting_title, analysis, transcript["duration_minutes"])

    return {
        "summary_path": summary_path,
        "duration_minutes": transcript["duration_minutes"],
        "action_items": len(analysis.get("action_items", [])),
        "decisions": len(analysis.get("decisions", []))
    }

Step 5: Track Action Item Completion

def track_action_items(meeting_id, action_items):
    conn = sqlite3.connect("meetings.db")
    for item in action_items:
        conn.execute("""
            INSERT INTO action_items (meeting_id, description, assignee, status, created_at)
            VALUES (?, ?, ?, 'open', datetime('now'))
        """, (meeting_id, item.get("task", ""), item.get("assignee", "unassigned")))
    conn.commit()

def get_open_action_items():
    conn = sqlite3.connect("meetings.db")
    return conn.execute("""
        SELECT ai.*, m.title as meeting_title
        FROM action_items ai
        JOIN meetings m ON ai.meeting_id = m.id
        WHERE ai.status = 'open'
        ORDER BY ai.created_at DESC
    """).fetchall()

What to Build Next

Add meeting pattern analysis. Track which meetings consistently produce action items vs which are status updates that could be emails. Data-driven meeting optimization saves the most expensive resource: everyone's time.

Related Reading

Want this system built for your business?

Get a free assessment. We will map every system your business needs and show you the ROI.

Get Your Free Assessment

Related Systems