AI 会议纪要自动生成 - 从录音到行动项的全流程自动化

一、会议纪要的痛点

传统会议纪要的问题:

  • 需要专人记录,占用参会时间
  • 记录质量依赖个人能力
  • 整理纪要耗时耗力
  • 行动项容易遗漏
  • 后续追踪困难

AI 自动化的价值:

  • 释放人力,专注讨论
  • 记录完整,不会遗漏
  • 即时生成,无需等待
  • 自动提取行动项
  • 便于搜索和回顾

二、技术栈选择

2.1 语音转文字 (STT)

服务 准确率 成本 特点
Whisper ⭐⭐⭐⭐ 免费 开源,本地部署
讯飞听见 ⭐⭐⭐⭐⭐ 付费 中文优秀
阿里云 ⭐⭐⭐⭐⭐ 付费 实时转写
Google Speech ⭐⭐⭐⭐ 付费 多语言支持

2.2 大语言模型

模型 摘要能力 行动项提取 成本
GPT-4 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
Claude 3 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
Qwen2.5 ⭐⭐⭐⭐ ⭐⭐⭐⭐
Llama 3 ⭐⭐⭐⭐ ⭐⭐⭐⭐ 免费

三、完整流程设计

会议录音 → 语音转文字 → 内容摘要 → 行动项提取 → 任务分配 → 纪要分发

3.1 流程图

┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│  会议录音   │ →  │  语音转文字  │ →  │  内容摘要   │
│  (音频文件)  │    │  (文字稿)   │    │  (核心要点) │
└─────────────┘    └─────────────┘    └─────────────┘
                                              ↓
┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│  纪要分发   │ ←  │  任务分配   │ ←  │  行动项提取  │
│  (邮件/IM)  │    │  (责任人)   │    │  (TODO 列表) │
└─────────────┘    └─────────────┘    └─────────────┘

四、实战实现

4.1 语音转文字

// stt-service.js
const { Whisper } = require('whisper-node');

class MeetingTranscriber {
  constructor(model = 'large') {
    this.whisper = new Whisper(model);
  }

  async transcribe(audioPath) {
    const result = await this.whisper.transcribe(audioPath, {
      language: 'zh',
      task: 'transcribe'
    });
    
    return {
      text: result.text,
      segments: result.segments,
      language: result.language
    };
  }

  async transcribeWithSpeakers(audioPath) {
    // 带说话人区分
    const result = await this.transcribe(audioPath);
    
    // 按时间戳分段,识别说话人切换
    const segments = this.identifySpeakers(result.segments);
    
    return {
      ...result,
      segments
    };
  }

  identifySpeakers(segments) {
    // 基于声音特征或时间间隔识别说话人
    // 简化版:按时间间隔分段
    const speakers = [];
    let currentSpeaker = 'Speaker 1';
    let lastEnd = 0;

    segments.forEach(seg => {
      if (seg.start - lastEnd > 2.0) {
        // 间隔超过 2 秒,可能是说话人切换
        currentSpeaker = `Speaker ${speakers.length + 1}`;
      }
      seg.speaker = currentSpeaker;
      speakers.push(seg);
      lastEnd = seg.end;
    });

    return speakers;
  }
}

// 使用示例
const transcriber = new MeetingTranscriber();
const transcript = await transcriber.transcribe('meeting.mp3');
console.log(transcript.text);

4.2 内容摘要

// summary-service.js
class MeetingSummarizer {
  constructor(aiClient) {
    this.ai = aiClient;
  }

  async summarize(transcript, options = {}) {
    const prompt = this.buildPrompt(transcript, options);
    
    const summary = await this.ai.chat([
      { role: 'system', content: '你是一位专业的会议秘书' },
      { role: 'user', content: prompt }
    ]);

    return this.parseSummary(summary);
  }

  buildPrompt(transcript, options) {
    return `
请总结以下会议内容:

【会议信息】
- 时间:${options.date || '未知'}
- 主题:${options.topic || '未知'}
- 参会人员:${options.attendees?.join('、') || '未知'}

【会议记录】
${transcript}

【输出要求】
1. 会议主题(1 句话)
2. 核心讨论点(3-5 个要点)
3. 重要决策(如有)
4. 待办事项(明确责任人和截止时间)
5. 下次会议安排(如有)

请用 Markdown 格式输出。
`;
  }

  parseSummary(summary) {
    // 解析 AI 返回的结构化内容
    return {
      raw: summary,
      // 可以进一步解析为结构化数据
    };
  }
}

4.3 行动项提取

// action-items.js
class ActionItemExtractor {
  constructor(aiClient) {
    this.ai = aiClient;
  }

  async extract(transcript) {
    const prompt = `
从以下会议记录中提取所有行动项:

${transcript}

提取要求:
1. 每个行动项包含:任务描述、责任人、截止时间(如有)
2. 按优先级排序(高/中/低)
3. 输出 JSON 格式

输出格式:
[
  {
    "task": "任务描述",
    "assignee": "责任人",
    "deadline": "截止时间",
    "priority": "高|中|低"
  }
]
`;

    const result = await this.ai.chat([
      { role: 'user', content: prompt }
    ]);

    return JSON.parse(result);
  }

  async assignTasks(actionItems, teamMembers) {
    // 智能分配任务
    const assignments = [];

    for (const item of actionItems) {
      if (!item.assignee || item.assignee === '待定') {
        // 根据任务内容匹配合适的成员
        const bestMatch = this.matchAssignee(item, teamMembers);
        item.assignee = bestMatch;
      }
      assignments.push(item);
    }

    return assignments;
  }

  matchAssignee(item, members) {
    // 基于技能、工作负载等匹配
    // 简化版:随机分配
    return members[Math.floor(Math.random() * members.length)];
  }
}

4.4 纪要生成与分发

// meeting-notes.js
class MeetingNotesGenerator {
  constructor({ transcriber, summarizer, extractor }) {
    this.transcriber = transcriber;
    this.summarizer = summarizer;
    this.extractor = extractor;
  }

  async generate(audioPath, metadata = {}) {
    // 1. 语音转文字
    console.log('📝 转写中...');
    const transcript = await this.transcriber.transcribe(audioPath);

    // 2. 生成摘要
    console.log('📋 生成摘要...');
    const summary = await this.summarizer.summarize(transcript.text, metadata);

    // 3. 提取行动项
    console.log('✅ 提取行动项...');
    const actionItems = await this.extractor.extract(transcript.text);

    // 4. 生成完整纪要
    const notes = this.formatNotes({
      metadata,
      transcript,
      summary,
      actionItems
    });

    return notes;
  }

  formatNotes({ metadata, transcript, summary, actionItems }) {
    return `
# 会议纪要

## 基本信息
- **时间**: ${metadata.date || '未知'}
- **主题**: ${metadata.topic || '未知'}
- **参会**: ${metadata.attendees?.join('、') || '未知'}
- **记录**: AI 自动生成

---

## 会议摘要

${summary.raw}

---

## 行动项

${actionItems.map((item, i) => `
### ${i + 1}. ${item.task}
- **责任人**: ${item.assignee}
- **优先级**: ${item.priority}
- **截止时间**: ${item.deadline || '待定'}
`).join('\n')}

---

## 完整记录

<details>
<summary>点击查看完整会议记录</summary>

${transcript.text}

</details>

---
*Generated by AI Meeting Assistant*
`;
  }

  async distribute(notes, channels) {
    // 分发到不同渠道
    const results = [];

    for (const channel of channels) {
      switch (channel.type) {
        case 'email':
          results.push(await this.sendEmail(channel.to, notes));
          break;
        case 'slack':
          results.push(await this.sendSlack(channel.channel, notes));
          break;
        case 'file':
          results.push(await this.saveFile(channel.path, notes));
          break;
      }
    }

    return results;
  }

  async sendEmail(to, notes) {
    // 发送邮件
    console.log(`📧 发送到:${to}`);
    return { channel: 'email', to, status: 'sent' };
  }

  async sendSlack(channel, notes) {
    // 发送到 Slack
    console.log(`💬 发送到 Slack: ${channel}`);
    return { channel: 'slack', channel, status: 'sent' };
  }

  async saveFile(path, notes) {
    // 保存文件
    const fs = require('fs').promises;
    const filename = `meeting-notes-${Date.now()}.md`;
    await fs.writeFile(`${path}/${filename}`, notes);
    console.log(`📁 保存到:${filename}`);
    return { channel: 'file', path: filename, status: 'saved' };
  }
}

五、完整工作流示例

// main.js
const { MeetingNotesGenerator } = require('./meeting-notes');
const { MeetingTranscriber } = require('./stt-service');
const { MeetingSummarizer } = require('./summary-service');
const { ActionItemExtractor } = require('./action-items');
const { OpenAIClient } = require('./ai-client');

async function processMeeting(audioPath) {
  // 初始化服务
  const aiClient = new OpenAIClient(process.env.OPENAI_API_KEY);
  const transcriber = new MeetingTranscriber();
  const summarizer = new MeetingSummarizer(aiClient);
  const extractor = new ActionItemExtractor(aiClient);

  const generator = new MeetingNotesGenerator({
    transcriber,
    summarizer,
    extractor
  });

  // 生成纪要
  const notes = await generator.generate(audioPath, {
    date: '2026-03-20',
    topic: 'Q2 产品规划讨论',
    attendees: ['张三', '李四', '王五']
  });

  // 分发纪要
  await generator.distribute(notes, [
    { type: 'email', to: 'team@company.com' },
    { type: 'slack', channel: '#meeting-notes' },
    { type: 'file', path: './meeting-notes' }
  ]);

  console.log('✅ 会议纪要处理完成!');
}

// 运行
processMeeting('meeting-2026-03-20.mp3');

六、进阶功能

6.1 实时转写

// real-time-transcription.js
class RealtimeTranscriber {
  constructor() {
    this.ws = new WebSocket('ws://stt-server:8080');
    this.buffer = [];
  }

  startStream(audioStream) {
    audioStream.on('data', chunk => {
      this.ws.send(chunk);
    });

    this.ws.on('message', data => {
      const result = JSON.parse(data);
      if (result.is_final) {
        this.buffer.push(result.text);
        console.log('📝', result.text);
      }
    });
  }

  getTranscript() {
    return this.buffer.join(' ');
  }
}

6.2 智能高亮

// highlight-key-points.js
class KeyPointHighlighter {
  constructor(aiClient) {
    this.ai = aiClient;
  }

  async highlight(transcript) {
    const prompt = `
从以下会议记录中找出关键信息:
- 重要决策
- 争议点
- 待确认事项
- 风险点

${transcript}

输出格式:
{
  "decisions": [],
  "controversies": [],
  "pending": [],
  "risks": []
}
`;

    const result = await this.ai.chat([{ role: 'user', content: prompt }]);
    return JSON.parse(result);
  }
}

6.3 任务追踪集成

// task-tracking.js
class TaskTracker {
  constructor(jiraClient) {
    this.jira = jiraClient;
  }

  async syncActionItems(actionItems, projectId) {
    const tasks = [];

    for (const item of actionItems) {
      const task = await this.jira.createIssue({
        project: projectId,
        summary: item.task,
        assignee: item.assignee,
        duedate: item.deadline,
        priority: item.priority,
        labels: ['meeting-action-item']
      });
      tasks.push(task);
    }

    return tasks;
  }
}

七、最佳实践

7.1 提高转写准确率

  • 使用高质量麦克风
  • 减少背景噪音
  • 说话清晰,避免重叠
  • 提供专业词汇表

7.2 优化摘要质量

  • 提供会议背景信息
  • 指定输出格式
  • 使用 Few-Shot 示例
  • 多轮迭代优化

7.3 确保行动项可执行

  • 明确责任人(具体到人)
  • 设定合理截止时间
  • 任务描述具体可衡量
  • 优先级清晰

八、总结

AI 会议纪要的价值:

指标 传统方式 AI 自动化 提升
记录时间 30-60 分钟 5-10 分钟 80%↓
整理时间 20-40 分钟 即时生成 100%↓
遗漏率 15-25% <5% 80%↓
分发效率 手动逐个发送 自动多渠道 90%↓

实施建议:

  1. 从重要会议开始试点
  2. 逐步建立标准流程
  3. 持续优化 Prompt 和模型
  4. 与现有工具集成

系列导航:

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐