Automate Meeting Summaries from Transcripts Using Python in 15 Minutes
You're drowning in meeting notes. Every day brings 3-4 meetings, each generating a transcript you need to read, summarize, and extract action items from. It takes 30 minutes per meeting just to create a useful summary.
That's 2.5 hours daily spent on post-meeting admin work.
Here's the problem: Meeting transcripts are verbose, unstructured, and filled with tangents. Finding the key decisions and action items means reading every word. Most people skip this step entirely, leading to missed commitments and confused teams.
But what if you could automate the entire process? Feed in a transcript, get back a clean summary with categorized action items in seconds.
I'll show you how to build this automation using Python and the OpenAI API. You'll have a working script in 15 minutes that can process any meeting transcript, regardless of format.
Why Automate Meeting Summary Generation
Before diving into code, understand the ROI:
Manual Process:
- Read 30-page transcript: 15 minutes
- Identify key points: 10 minutes
- Extract action items: 5 minutes
- Write summary: 10 minutes
- Total: 40 minutes per meeting
Automated Process:
- Run Python script: 30 seconds
- Review AI summary: 3 minutes
- Make minor edits: 2 minutes
- Total: 5.5 minutes per meeting
For someone with 15 meetings per week, that's 8.5 hours saved - over a full workday.
Prerequisites and Setup
You'll need:
- Python 3.8 or higher
- OpenAI API key (get one at platform.openai.com)
- Basic command line familiarity
Install Required Packages
1pip install openai python-dotenv
Create a .env file for your API key:
1OPENAI_API_KEY=your_api_key_here
Never commit API keys to version control. Use environment variables or .env files with .gitignore.
The Meeting Summary Automation Script
Here's the complete script that processes meeting transcripts:
1import os2from openai import OpenAI3from dotenv import load_dotenv4from datetime import datetime56# Load environment variables7load_dotenv()89# Initialize OpenAI client10client = OpenAI(api_key=os.getenv('OPENAI_API_KEY'))1112def generate_meeting_summary(transcript_text, meeting_date=None):13 """14 Generate a structured meeting summary from transcript text.1516 Args:17 transcript_text (str): The full meeting transcript18 meeting_date (str): Optional date of the meeting1920 Returns:21 str: Formatted meeting summary with action items22 """2324 # Construct the prompt for GPT-425 system_prompt = """You are an expert meeting summarizer. Your job is to:26 1. Create a concise executive summary (2-3 sentences)27 2. List key discussion points with brief explanations28 3. Extract all action items with assigned owners and deadlines29 4. Note important decisions made30 5. Flag any unresolved questions or blockers3132 Format your response as structured markdown with clear sections."""3334 user_prompt = f"""Please analyze this meeting transcript and create a structured summary:3536TRANSCRIPT:37{transcript_text}3839{"MEETING DATE: " + meeting_date if meeting_date else ""}4041Create a comprehensive but concise summary following best practices for meeting documentation."""4243 try:44 # Call OpenAI API45 response = client.chat.completions.create(46 model="gpt-4-turbo-preview",47 messages=[48 {"role": "system", "content": system_prompt},49 {"role": "user", "content": user_prompt}50 ],51 temperature=0.3, # Lower temperature for more factual summaries52 max_tokens=150053 )5455 summary = response.choices[0].message.content56 return summary5758 except Exception as e:59 return f"Error generating summary: {str(e)}"6061def process_transcript_file(file_path):62 """63 Read transcript from file and generate summary.6465 Args:66 file_path (str): Path to transcript file6768 Returns:69 str: Generated summary70 """71 try:72 with open(file_path, 'r', encoding='utf-8') as f:73 transcript = f.read()7475 print(f"Processing transcript from: {file_path}")76 print(f"Transcript length: {len(transcript)} characters\n")7778 # Extract date from filename if possible79 meeting_date = None80 if '_' in file_path:81 try:82 date_part = file_path.split('_')[1].split('.')[0]83 meeting_date = date_part84 except:85 pass8687 summary = generate_meeting_summary(transcript, meeting_date)88 return summary8990 except FileNotFoundError:91 return f"Error: File not found at {file_path}"92 except Exception as e:93 return f"Error processing file: {str(e)}"9495def save_summary(summary, output_path):96 """97 Save summary to a file.9899 Args:100 summary (str): The generated summary101 output_path (str): Where to save the summary102 """103 try:104 with open(output_path, 'w', encoding='utf-8') as f:105 f.write(f"# Meeting Summary - {datetime.now().strftime('%Y-%m-%d')}\n\n")106 f.write(summary)107 print(f"\nā Summary saved to: {output_path}")108 except Exception as e:109 print(f"\nā Error saving summary: {str(e)}")110111def main():112 """113 Main function to run the meeting summary automation.114 """115 print("=== Meeting Summary Generator ===\n")116117 # Get transcript file path from user118 transcript_file = input("Enter the path to your transcript file: ").strip()119120 if not transcript_file:121 print("ā No file path provided")122 return123124 # Process the transcript125 summary = process_transcript_file(transcript_file)126127 # Display the summary128 print("\n" + "="*60)129 print("GENERATED SUMMARY")130 print("="*60 + "\n")131 print(summary)132 print("\n" + "="*60)133134 # Ask if user wants to save135 save_choice = input("\nSave this summary to a file? (y/n): ").strip().lower()136137 if save_choice == 'y':138 output_file = input("Enter output filename (default: meeting_summary.md): ").strip()139 if not output_file:140 output_file = "meeting_summary.md"141142 save_summary(summary, output_file)143144if __name__ == "__main__":145 main()
How the Script Works
Step 1: Prompt Engineering for Quality Summaries
The script uses a carefully crafted system prompt that instructs GPT-4 to:
- Create executive summaries: 2-3 sentence overviews
- Extract key points: Main discussion topics with context
- Identify action items: With owners and deadlines
- Document decisions: Important conclusions reached
- Flag blockers: Unresolved issues needing attention
The temperature=0.3 setting ensures consistent, factual summaries rather than creative interpretations.
Step 2: Processing Different Transcript Formats
The script handles various transcript formats:
1# Works with plain text transcripts2meeting_transcript_20260128.txt34# Works with timestamped transcripts5[00:01:23] John: We need to prioritize the Q2 roadmap.6[00:01:45] Sarah: I agree. Let's focus on customer feedback.78# Works with speaker-labeled transcripts9John: We need to prioritize the Q2 roadmap.10Sarah: I agree. Let's focus on customer feedback.
GPT-4 automatically identifies speakers, timestamps, and structure regardless of format.
Step 3: Structured Output Generation
The AI generates markdown-formatted summaries following this template:
1## Executive Summary2[2-3 sentence overview]34## Key Discussion Points5- **Topic 1**: Brief explanation6- **Topic 2**: Brief explanation78## Action Items9- [ ] **Task description** - Owner: [Name] - Due: [Date]10- [ ] **Task description** - Owner: [Name] - Due: [Date]1112## Decisions Made13- Decision 1 with context14- Decision 2 with context1516## Unresolved Questions17- Question or blocker 118- Question or blocker 2
This format is consistent, scannable, and ready to share with your team.
Running the Script
Basic Usage
1python meeting_summarizer.py
When prompted, enter your transcript file path:
Enter the path to your transcript file: transcripts/meeting_20260128.txt
The script processes the file and displays the summary:
Processing transcript from: transcripts/meeting_20260128.txt Transcript length: 4523 characters ============================================================ GENERATED SUMMARY ============================================================ ## Executive Summary Team discussed Q2 product roadmap prioritization, focusing on customer feedback from recent surveys. Agreed to deprioritize feature X and accelerate feature Y timeline by 2 weeks. [... rest of summary ...]
Saving Summaries
After generation, the script asks if you want to save:
Save this summary to a file? (y/n): y Enter output filename (default: meeting_summary.md): q2_planning_summary.md ā Summary saved to: q2_planning_summary.md
Advanced Usage: Batch Processing
Process multiple transcripts automatically:
1import os2import glob34def batch_process_transcripts(directory_path):5 """6 Process all transcript files in a directory.78 Args:9 directory_path (str): Path to directory containing transcripts10 """11 # Find all .txt files in directory12 transcript_files = glob.glob(os.path.join(directory_path, "*.txt"))1314 print(f"Found {len(transcript_files)} transcript files\n")1516 for transcript_file in transcript_files:17 print(f"Processing: {transcript_file}")1819 # Generate summary20 summary = process_transcript_file(transcript_file)2122 # Create output filename23 base_name = os.path.splitext(os.path.basename(transcript_file))[0]24 output_file = f"{base_name}_summary.md"2526 # Save summary27 save_summary(summary, output_file)2829 print(f"Completed: {output_file}\n")3031# Usage32batch_process_transcripts("./meeting_transcripts")
This processes an entire folder of transcripts, generating individual summary files for each.
Integrating with Meeting Tools
Connect to Otter.ai
Export transcripts from Otter and process automatically:
1import requests2from datetime import datetime, timedelta34def fetch_recent_otter_transcripts(api_key, days=7):5 """6 Fetch recent transcripts from Otter.ai API.7 """8 url = "https://otter.ai/forward/api/v1/speeches"9 headers = {"Authorization": f"Bearer {api_key}"}1011 # Calculate date range12 end_date = datetime.now()13 start_date = end_date - timedelta(days=days)1415 params = {16 "start_date": start_date.isoformat(),17 "end_date": end_date.isoformat()18 }1920 response = requests.get(url, headers=headers, params=params)21 return response.json()2223# Fetch and process24transcripts = fetch_recent_otter_transcripts(os.getenv('OTTER_API_KEY'))25for transcript in transcripts['speeches']:26 summary = generate_meeting_summary(transcript['transcript'])27 save_summary(summary, f"otter_summary_{transcript['id']}.md")
Connect to Microsoft Teams
Process Teams meeting recordings:
1from azure.identity import DefaultAzureCredential2from microsoft.graph import GraphServiceClient34async def get_teams_transcripts(meeting_id):5 """6 Fetch transcript from Microsoft Teams using Graph API.7 """8 credential = DefaultAzureCredential()9 client = GraphServiceClient(credential)1011 # Get meeting transcript12 transcript = await client.users.by_user_id('me').onlineMeetings.by_online_meeting_id(meeting_id).transcripts.get()1314 return transcript
Cost Analysis
Understanding API costs helps justify the automation:
OpenAI API Costs (GPT-4 Turbo)
- Input: $0.01 per 1K tokens
- Output: $0.03 per 1K tokens
Typical meeting transcript:
- 30-minute meeting: ~5,000 words = ~6,500 tokens input
- Summary output: ~500 words = ~650 tokens output
Cost per summary: $0.06 + $0.02 = $0.08
For 15 meetings per week:
- Weekly cost: $1.20
- Monthly cost: $4.80
- Annual cost: $62.40
Compare this to the 442 hours saved annually (8.5 hours/week Ć 52 weeks). At even $50/hour, you save $22,100 in time value.
ROI: 35,400%
Best Practices and Pro Tips
Optimize Prompt Quality
Your prompt quality directly affects summary accuracy:
Poor prompt:
1"Summarize this meeting."
Good prompt:
1"""Analyze this meeting transcript and create a structured summary including:21. Executive summary (2-3 sentences)32. Key discussion points with context43. Action items with owners and deadlines54. Decisions made65. Unresolved questions or blockers78Format as markdown with clear sections."""
The detailed prompt gives GPT-4 clear expectations, producing better results.
Handle Long Transcripts
GPT-4 Turbo has a 128K token context window, but very long meetings might exceed this:
1def chunk_long_transcript(transcript, max_tokens=100000):2 """3 Split long transcripts into processable chunks.4 """5 # Rough estimate: 1 token ā 4 characters6 max_chars = max_tokens * 478 if len(transcript) <= max_chars:9 return [transcript]1011 # Split into chunks at paragraph boundaries12 paragraphs = transcript.split('\n\n')13 chunks = []14 current_chunk = ""1516 for para in paragraphs:17 if len(current_chunk) + len(para) < max_chars:18 current_chunk += para + "\n\n"19 else:20 chunks.append(current_chunk)21 current_chunk = para + "\n\n"2223 if current_chunk:24 chunks.append(current_chunk)2526 return chunks2728# Process each chunk and combine summaries29chunks = chunk_long_transcript(long_transcript)30summaries = [generate_meeting_summary(chunk) for chunk in chunks]31final_summary = combine_summaries(summaries)
Add Custom Fields
Customize output for your team's needs:
1system_prompt = """You are an expert meeting summarizer. Create a summary with:21. Executive summary (2-3 sentences)32. Attendees (if mentioned)43. Key discussion points54. Action items (format: - [ ] Task - Owner: Name - Due: Date)65. Decisions made76. Budget implications (if any)87. Next meeting date/time (if mentioned)98. Unresolved questions1011Use markdown formatting with emoji indicators:12š for action items13ā for decisions14ā for questions15š° for budget items"""
This creates scannable summaries with visual indicators.
Troubleshooting Common Issues
Issue: "Rate limit exceeded"
Cause: Too many API requests too quickly
Solution: Add delays between requests
1import time23for transcript in transcript_files:4 summary = generate_meeting_summary(transcript)5 save_summary(summary, f"summary_{i}.md")6 time.sleep(2) # 2-second delay between requests
Issue: Incomplete action items
Cause: Vague language in transcript
Solution: Add follow-up prompt to extract details
1# First, generate basic summary2summary = generate_meeting_summary(transcript)34# Then, extract action items specifically5action_items_prompt = f"""Review this meeting summary and extract ALL action items, including:6- Implied tasks (things someone mentioned they "should" or "will" do)7- Tasks without explicit owners (assign to most relevant person mentioned)8- Tasks without deadlines (infer reasonable deadline from context)910Summary:11{summary}1213Format each action item as:14- [ ] [Task description] - Owner: [Name] - Due: [Date or "TBD"]"""1516detailed_actions = client.chat.completions.create(17 model="gpt-4-turbo-preview",18 messages=[{"role": "user", "content": action_items_prompt}],19 temperature=0.220)
Issue: Summary too generic
Cause: Not enough context in prompt
Solution: Provide meeting metadata
1user_prompt = f"""Analyze this meeting transcript.23MEETING CONTEXT:4- Meeting Type: {meeting_type} # e.g., "Sprint Planning", "Client Review"5- Project: {project_name}6- Team: {team_name}7- Date: {meeting_date}89TRANSCRIPT:10{transcript_text}1112Create a detailed summary appropriate for a {meeting_type} meeting."""
Context helps GPT-4 understand what information matters most.
Conclusion
You now have a production-ready Python script that automates meeting summary generation. This single automation saves 8+ hours per week for meeting-heavy roles.
Key takeaways:
- Simple setup: 15 minutes to deploy, works immediately
- Massive ROI: $0.08 per summary vs 40 minutes manual work
- Flexible: Handles any transcript format, integrates with meeting tools
- Customizable: Adjust prompts for your team's specific needs
- Scalable: Process one meeting or batch-process hundreds
The next step: Integrate this into your meeting workflow. Export transcripts from your meeting tool (Otter, Teams, Zoom) and run them through this script automatically.
Frequently Asked Questions
Can this work with transcripts in other languages?
Yes. GPT-4 supports 50+ languages. The script works identically with transcripts in Spanish, French, German, Chinese, Japanese, and many others. The summary will be generated in the same language as the input transcript.
How accurate are the AI-generated summaries?
GPT-4 achieves 90-95% accuracy on factual extraction from transcripts. Always review the summary before sharing, especially for critical meetings involving legal, financial, or strategic decisions. The 3-minute review step catches any misinterpretations.
What if my transcripts don't have speaker labels?
The script still works. GPT-4 can infer who said what from context clues, though speaker-labeled transcripts produce slightly better results. For unlabeled transcripts, add a note about attendees in the prompt.
Can I use a cheaper model like GPT-3.5?
Yes, but summary quality decreases noticeably. GPT-3.5 often misses nuanced action items and produces less structured output. For critical meetings, stick with GPT-4. For informal team syncs, GPT-3.5 at $0.001/1K tokens input works adequately.
How do I handle confidential meetings?
Either: (1) Use a local AI model like Llama 2 instead of OpenAI's API, or (2) Use OpenAI's API with the "zero data retention" option available on Enterprise plans. Never send confidential transcripts to standard API endpoints that may use data for training.
Related articles: Automate Email Sending with Python, Build an AI Resume Scanner with Python
Sponsored Content
Interested in advertising? Reach automation professionals through our platform.
