AI Meeting Minutes Automation Implementation

We design and deploy artificial intelligence systems: from prototype to production-ready solutions. Our team combines expertise in machine learning, data engineering and MLOps to make AI work not in the lab, but in real business.
Showing 1 of 1 servicesAll 1566 services
AI Meeting Minutes Automation Implementation
Medium
~1-2 weeks
FAQ
AI Development Areas
AI Solution Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1212
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    822

Meeting Minute Automation with AI. The system automatically transcribes meeting recordings, identifies participants, highlights decisions and tasks, and generates structured minutes. Integrates with Zoom, Google Meet, MS Teams, Slack, and corporate task management systems. ### Pipeline Architecture

Запись встречи (аудио/видео)
    ↓ VAD + диаризация (pyannote.audio)
    ↓ Транскрибация (Whisper large-v3)
    ↓ NLP-обработка (GPT-4o / Claude)
    ↓ Извлечение: решения / задачи / ответственные / дедлайны
    ↓ Генерация протокола (Markdown / Notion / Jira)
```### Transcription with diarization```python
import whisper
from pyannote.audio import Pipeline
import torch

class MeetingTranscriber:
    def __init__(self):
        self.whisper = whisper.load_model("large-v3", device="cuda")
        self.diarizer = Pipeline.from_pretrained(
            "pyannote/speaker-diarization-3.1",
            use_auth_token="HF_TOKEN"
        )

    def transcribe_with_speakers(self, audio_path: str) -> list[dict]:
        # Диаризация
        diarization = self.diarizer(audio_path)
        segments_by_speaker = [
            {"speaker": turn.speaker, "start": turn.start, "end": turn.end}
            for turn, _, _ in diarization.itertracks(yield_label=True)
        ]

        # Транскрипция
        result = self.whisper.transcribe(audio_path, language="ru", word_timestamps=True)

        # Мёржим
        transcript = []
        for seg in result["segments"]:
            speaker = self._find_speaker(seg["start"], segments_by_speaker)
            transcript.append({
                "speaker": speaker,
                "start": seg["start"],
                "end": seg["end"],
                "text": seg["text"].strip()
            })

        return transcript

    def _find_speaker(self, timestamp: float, diar_segments: list) -> str:
        for s in diar_segments:
            if s["start"] <= timestamp <= s["end"]:
                return s["speaker"]
        return "UNKNOWN"
```### NLP processing and structure extraction```python
from openai import AsyncOpenAI
import json

client = AsyncOpenAI()

async def extract_meeting_structure(transcript: list[dict]) -> dict:
    # Форматируем транскрипт
    formatted = "\n".join([
        f"[{seg['speaker']} | {int(seg['start']//60):02d}:{int(seg['start']%60):02d}] {seg['text']}"
        for seg in transcript
    ])

    response = await client.chat.completions.create(
        model="gpt-4o",
        messages=[{
            "role": "system",
            "content": """Ты — ассистент для протоколирования встреч.
            Проанализируй транскрипт и верни JSON:
            {
              "summary": "краткое резюме 2-3 предложения",
              "participants": ["SPEAKER_00 = Иван Петров", ...],
              "agenda_items": [{"topic": "...", "discussion": "..."}],
              "decisions": [{"decision": "...", "context": "..."}],
              "action_items": [{"task": "...", "owner": "...", "deadline": "..."}],
              "next_meeting": "дата/условие следующей встречи если обсуждалась"
            }"""
        }, {
            "role": "user",
            "content": f"Транскрипт встречи:\n\n{formatted[:8000]}"
        }],
        response_format={"type": "json_object"}
    )

    return json.loads(response.choices[0].message.content)
```### Protocol generation```python
def format_meeting_minutes(structure: dict, transcript: list[dict]) -> str:
    date = datetime.now().strftime("%d.%m.%Y")
    duration_min = int(transcript[-1]["end"] / 60) if transcript else 0

    md = f"""## Протокол встречи от {date}

**Продолжительность:** {duration_min} минут
**Участники:** {", ".join(structure.get("participants", []))}

### Краткое резюме

{structure.get("summary", "")}

### Принятые решения

"""
    for d in structure.get("decisions", []):
        md += f"- **{d['decision']}**\n  _{d.get('context', '')}_\n\n"

    md += "### Задачи\n\n"
    md += "| Задача | Ответственный | Срок |\n|--------|--------------|------|\n"
    for item in structure.get("action_items", []):
        md += f"| {item['task']} | {item.get('owner', '—')} | {item.get('deadline', '—')} |\n"

    return md
```### Integrations **Zoom:** via Zoom Recordings API - automatically receive mp4/m4a files after the meeting ends. **Google Meet:** via Google Workspace Events API + Cloud Storage for recordings. **MS Teams:** via Microsoft Graph API `/communications/callRecords`.```python
@app.post("/webhook/zoom/recording")
async def zoom_recording_webhook(payload: dict):
    if payload["event"] == "recording.completed":
        recording_url = payload["payload"]["object"]["recording_files"][0]["download_url"]
        meeting_id = payload["payload"]["object"]["uuid"]
        asyncio.create_task(process_meeting_recording(meeting_id, recording_url))
    return {"status": "ok"}
```### Export```python
class MinutesExporter:
    async def to_notion(self, minutes: str, database_id: str): ...
    async def to_confluence(self, minutes: str, space_key: str): ...
    async def to_jira_tasks(self, action_items: list, project_key: str): ...
    async def to_slack(self, summary: str, channel_id: str): ...
    async def to_email(self, minutes: str, recipients: list[str]): ...
```Timeline: Basic pipeline (transcription + NLP + Markdown) — 1–2 weeks. A full-fledged system with Zoom/Teams/Notion/Jira integrations — 4–6 weeks.