Skip to main content

小奥会议纪要 OddMinutes - 智能会议录音与纪要系统

Project description

小奥会议纪要 OddMinutes - 您的会议纪要小助手

一个基于 Django 的智能会议纪要系统,支持实时录音、AI 转录、智能摘要生成和音字联动功能。

功能特性

  • 🎙️ 麦克风 + 系统音频双轨录制 - 支持同时录制麦克风和系统音频,带自动增益控制(AGC)
  • 📝 AI 实时转录 - 对接 OddASR 服务,支持字级时间戳输出
  • 🤖 智能摘要生成 - 支持 Ollama/OpenAI/Claude/Groq 多种 LLM 提供商
  • 🔗 音字联动 - 点击文字跳转到音频对应位置,播放时高亮当前文字
  • 📤 多格式导出 - 支持 TXT、Markdown、JSON 格式导出
  • 🔍 全文搜索 - 支持转录内容搜索
  • ⏱️ 录音暂停/恢复 - 支持录音过程中暂停和恢复

快速安装

# 基础安装
pip install OddMinutes

# Windows 用户(包含系统托盘和快捷键支持)
pip install OddMinutes[windows]

# 启动程序
OddMinutes

首次运行时,程序会自动初始化数据库并创建用户数据目录。

技术架构

┌─────────────────────────────────────────────────────────────┐
│                        前端 (HTML/CSS/JS)                    │
│  - 会议列表管理                                              │
│  - 录音控制面板(电平监测)                                   │
│  - 转录内容展示(音字联动)                                    │
│  - AI 摘要展示                                               │
│  - 笔记编辑                                                  │
└──────────────────────┬──────────────────────────────────────┘
                       │ HTTP / WebSocket
┌──────────────────────▼──────────────────────────────────────┐
│                      Django 后端                             │
│  ┌─────────┐ ┌──────────┐ ┌────────────┐ ┌──────────┐       │
│  │  core   │ │ meetings │ │ recording  │ │summary   │       │
│  │ 首页/    │ │ 会议CRUD │ │ 音频录制   │ │ AI摘要   │       │
│  │ 路由    │ │ 搜索/导出 │ │ 电平监测   │ │ 模板配置  │       │
│  └─────────┘ └──────────┘ └────────────┘ └──────────┘       │
│  ┌──────────────┐ ┌───────────┐ ┌──────────────┐            │
│  │ transcription│ │ system_app│ │   Channels   │            │
│  │ ASR转录      │ │ 系统设置  │ │ WebSocket    │            │
│  │ 音频上传     │ │ 通知/更新 │ │ 实时电平推送  │            │
│  └──────────────┘ └───────────┘ └──────────────┘            │
└──────────────────────┬──────────────────────────────────────┘
                       │ HTTP API
┌──────────────────────▼──────────────────────────────────────┐
│                    外部服务依赖                               │
│  ┌──────────────┐         ┌──────────────────┐             │
│  │   OddASR     │         │   Ollama/OpenAI  │             │
│  │ (语音识别)    │         │    (LLM 摘要)    │             │
│  │ 127.0.0.1:9002│        │ localhost:11434  │             │
│  └──────────────┘         └──────────────────┘             │
└─────────────────────────────────────────────────────────────┘

项目结构

OddMinutes/
├── OddMinutes/              # Python 包入口(用于 PyPI 安装)
│   ├── __init__.py          # 包初始化
│   ├── launcher.py          # 命令行启动器入口
│   ├── manage.py            # Django 管理命令(引导用)
│   └── .env.example         # 环境变量示例(引导用)
├── core/                    # 核心模块(首页、基础模型)
│   ├── models.py            # BaseModel 抽象基类
│   ├── views.py             # 首页和会议详情视图
│   ├── urls.py              # 路由配置
│   ├── audio_utils.py       # 音频转换工具(WAV→MP3)
│   └── management/commands/init_defaults.py  # 初始化命令
├── meetings/                # 会议管理模块
│   ├── models.py            # Meeting、TranscriptSegment、SummaryProcess、MeetingExport
│   ├── views.py             # 会议 CRUD、搜索、导出、清理
│   ├── urls.py              # 路由配置
│   └── serializers.py       # DRF 序列化器
├── recording/               # 录音模块
│   ├── models.py            # RecordingSession、RecordingCheckpoint、AudioDevice
│   ├── views.py             # 录音控制 API
│   ├── urls.py              # 路由配置
│   ├── audio_recorder.py    # 音频录制器(双轨、AGC、混音)
│   ├── consumers.py         # WebSocket 电平推送消费者
│   └── routing.py           # WebSocket 路由
├── transcription/           # 转录模块
│   ├── models.py            # TranscriptionJob、TranscriptionConfig
│   ├── views.py             # 转录 API(文件转录、重新转录、上传)
│   ├── urls.py              # 路由配置
│   ├── oddasr_client.py     # OddASR OpenAI 兼容客户端
│   ├── consumers.py         # WebSocket 实时转录消费者
│   └── routing.py           # WebSocket 路由
├── summary/                 # AI 摘要模块
│   ├── models.py            # SummaryTemplate、AIModelConfig、SummaryLanguagePreference
│   ├── views.py             # 摘要生成 API
│   ├── urls.py              # 路由配置
│   └── ai_processor.py      # AI 摘要处理器(支持多提供商、chunk 分段处理)
├── system_app/              # 系统设置模块
│   ├── models.py            # SystemSettings、UpdateInfo、NotificationLog
│   ├── views.py             # 系统设置、通知、更新检查 API
│   ├── urls.py              # 路由配置
│   └── tray_icon.py         # 系统托盘图标
├── meeting_minutes/         # Django 项目配置
│   ├── settings.py          # 项目配置
│   ├── urls.py              # 全局路由
│   ├── asgi.py              # ASGI 入口(支持 WebSocket)
│   ├── static/              # 静态资源
│   │   ├── css/style.css    # 样式文件
│   │   ├── js/app.js        # 前端逻辑
│   │   └── favicon.ico      # 网站图标
│   └── templates/           # HTML 模板
│       └── core/
│           ├── index.html   # 主页面
│           └── meeting_detail.html  # 会议详情页
├── media/                   # 媒体文件存储(音频文件)
├── logs/                    # 日志文件
├── .env                     # 环境变量配置
├── .env.example             # 环境变量示例
├── requirements.txt         # Python 依赖
├── launcher.py              # 根目录启动脚本
├── manage.py                # Django 管理命令
└── pyproject.toml           # PyPI 打包配置

外部服务依赖

1. OddASR 语音识别服务

安装 OddASR 服务

pip install oddasr

运行 OddASR 服务

oddasr-server

必需 - 用于音频转录,提供 OpenAI 兼容的 /v1/audio/transcriptions 接口。

  • 默认地址:http://127.0.0.1:9002
  • 配置文件:.env 中的 ODDASR_HOSTODDASR_PORT
  • 支持 verbose_json 响应格式,返回段级和字级时间戳

2. Ollama / LLM 服务

可选 - 用于 AI 摘要生成。

  • 默认地址:http://localhost:11434(Ollama)
  • 支持提供商:Ollama(本地)、OpenAI、Claude、Groq
  • 通过 pydantic-ai 库统一调用

3. FFmpeg

必需 - pydub 依赖 FFmpeg 进行音频格式转换。

安装与运行

环境要求

  • Python 3.12+
  • FFmpeg(需添加到系统 PATH)
  • OddASR 服务(运行中)
  • Ollama(可选,用于本地 LLM 摘要)

PyPI 安装(推荐)

# 基础安装
pip install OddMinutes

# Windows 用户(包含系统托盘和快捷键支持)
pip install OddMinutes[windows]

启动程序

OddMinutes

首次运行时,程序会自动完成以下操作:

  • 初始化数据库(自动执行 migrate)
  • 创建用户数据目录(位于 %APPDATA%\Local\OddMeta\OddMinutes~/.local/share/OddMeta/OddMinutes
  • 复制必要的配置文件

开发安装(从源码)

git clone https://github.com/oddmeta/OddMinutes.git
cd OddMinutes

# 安装开发依赖
pip install -r requirements.txt

# 安装 Windows 额外依赖(Windows 用户)
pip install pywin32 keyboard pynput

# 配置环境变量
copy .env.example .env

编辑 .env 文件,设置关键配置:

# Django 配置
DJANGO_SECRET_KEY=your-secret-key-here
DEBUG=True
ALLOWED_HOSTS=localhost,127.0.0.1

# OddASR 配置(必需)
ODDASR_HOST=127.0.0.1
ODDASR_PORT=9002

# Ollama 配置(可选,用于本地 LLM)
OLLAMA_HOST=http://localhost:11434

# 音频配置
AUDIO_SAMPLE_RATE=16000
AUDIO_CHANNELS=1
AUDIO_CHUNK_DURATION=5

# 会议设置
AUTO_CLEANUP_DAYS=7
MAX_AUDIO_FILE_SIZE=500

初始化数据库

python manage.py migrate
python manage.py init_defaults

启动服务

# 使用启动脚本
start.bat

# 或直接运行
python manage.py runserver 127.0.0.1:9011

# 或使用命令行入口
python launcher.py

服务启动后访问:http://127.0.0.1:9011

用户数据目录

通过 PyPI 安装后,用户数据和配置文件存储在以下位置:

  • Windows: %APPDATA%\Local\OddMeta\OddMinutesC:\Users\<用户名>\AppData\Local\OddMeta\OddMinutes
  • Linux: ~/.local/share/OddMeta/OddMinutes
  • macOS: ~/Library/Application Support/OddMeta/OddMinutes

该目录包含:

  • .env - 环境变量配置文件
  • db.sqlite3 - SQLite 数据库文件
  • media/ - 音频文件存储目录
  • logs/ - 日志文件目录

配置说明

环境变量 默认值 使用模块 说明
DJANGO_SECRET_KEY django-insecure-change-me 全局 Django 安全密钥
DEBUG True 全局 调试模式
ALLOWED_HOSTS localhost,127.0.0.1 全局 允许的主机
ODDASR_HOST 127.0.0.1 transcription OddASR 服务主机
ODDASR_PORT 9002 transcription OddASR 服务端口
OLLAMA_HOST http://localhost:11434 summary Ollama 服务地址
AUDIO_SAMPLE_RATE 16000 recording 音频采样率
AUDIO_CHANNELS 1 recording 音频通道数
AUDIO_CHUNK_DURATION 5 recording 音频块持续时间(秒)
AUTO_CLEANUP_DAYS 7 meetings 自动清理天数
MAX_AUDIO_FILE_SIZE 500 全局 最大音频文件大小(MB)

API 接口

会议管理 /api/meetings/

方法 路径 说明
GET /api/meetings/ 获取会议列表
POST /api/meetings/ 创建新会议
GET /api/meetings/{id}/ 获取会议详情
PUT/PATCH /api/meetings/{id}/ 更新会议信息
DELETE /api/meetings/{id}/ 删除会议
POST /api/meetings/{id}/export/ 导出会议(支持 txt/md/json)
POST /api/meetings/search/ 搜索转录内容
POST /api/meetings/cleanup/ 清理旧会议
PATCH /api/meetings/transcript-segments/{id}/ 更新转录片段

录音控制 /api/recording/

方法 路径 说明
GET /api/recording/devices/ 获取音频设备列表
POST /api/recording/start/ 开始录音
POST /api/recording/pause/ 暂停录音
POST /api/recording/resume/ 恢复录音
POST /api/recording/stop/ 停止录音
GET /api/recording/level/ 获取当前音频电平
GET /api/recording/status/ 获取录音状态

转录服务 /api/transcription/

方法 路径 说明
POST /api/transcription/transcribe/ 转录音频文件
POST /api/transcription/retranscribe/ 重新转录
POST /api/transcription/upload/ 上传音频并转录
GET /api/transcription/status/{id}/ 获取转录任务状态
GET/POST /api/transcription/config/ 获取/设置转录配置
GET /api/transcription/oddasr-status/ 检查 OddASR 服务状态

AI 摘要 /api/summary/

方法 路径 说明
POST /api/summary/generate/ 生成会议摘要
GET /api/summary/status/{id}/ 获取摘要状态
POST /api/summary/regenerate/ 重新生成摘要
GET/POST /api/summary/templates/ 获取/创建摘要模板
GET/POST/PUT/DELETE /api/summary/model-config/ AI 模型配置管理
GET/POST /api/summary/language-preferences/ 语言偏好设置
POST /api/summary/stream/ 流式生成摘要(SSE)

系统设置 /api/system/

方法 路径 说明
GET/POST /api/system/settings/ 获取/更新系统设置
GET /api/system/check-updates/ 检查更新
GET /api/system/notifications/ 获取通知列表
POST /api/system/notifications/read/ 标记通知为已读
POST /api/system/notifications/send/ 发送系统通知
POST /api/system/onboarding/complete/ 完成首次引导
GET /api/system/info/ 获取系统信息

WebSocket 接口

音频电平推送

  • 路径: ws://host:port/ws/recording/level/
  • 用途: 实时推送麦克风和系统音频电平数据
  • 推送频率: 10 次/秒

推送数据格式:

{
  "mic_level": 0.1234,
  "system_level": 0.0567,
  "mixed_level": 0.1234,
  "peak_mic": 0.2345,
  "peak_system": 0.0890,
  "status": "recording",
  "duration": 45.5,
  "agc": {
    "enabled": true,
    "mic_gain": 1.5,
    "system_gain": 1.0,
    "target_rms": 8000
  }
}

实时转录

  • 路径: ws://host:port/ws/transcription/realtime/
  • 用途: 实时音频转录

数据流详解

完整流程示例

  1. 创建会议 → POST /api/meetings/ → 创建 Meeting 记录(status=recording)

  2. 开始录音 → POST /api/recording/start/

    • 选择麦克风设备和可选的系统音频设备
    • AudioRecorder.start() 启动双轨录制
    • 开启 AGC(自动增益控制),保持目标 RMS 电平 8000
    • 实时计算音频电平,通过 WebSocket 推送到前端
  3. 录音过程

    • 麦克风和系统音频分别采集(16kHz, 单声道, 16-bit)
    • 应用 AGC 增益控制
    • 混音处理(麦克风 55% + 系统音频 55%),带软压限防止削波
    • 每 5 秒生成音频块,触发转录回调
  4. 停止录音 → POST /api/recording/stop/

    • 合并缓冲区数据,编码为 WAV 格式
    • 保存到 media/audio/meetings/{date}/{filename}.wav
    • 自动转换为 MP3 格式(audio_utils.convert_audio_to_mp3
    • 更新 Meeting 状态为 completed
  5. 转录音频 → POST /api/transcription/transcribe/

    • 创建 TranscriptionJob(status=processing)
    • 后台线程调用 OddASR 客户端
    • 请求格式:model=whisper-1, response_format=verbose_json, timestamp_granularities[]=word
    • OddASR 返回包含 segmentswords 的 JSON 数据
  6. 保存转录结果

    • 解析 segments,每个 segment 包含 text、speaker、start、end、words
    • 创建 TranscriptSegment 记录,words 字段存储字级时间戳
    • 更新 Meeting 状态为 completed
  7. 生成摘要 → POST /api/summary/generate/

    • 创建 SummaryProcess(status=processing)
    • 合并所有转录文本
    • 按 chunk_size=5000、overlap=1000 分段
    • 每段调用 LLM(默认 Ollama/Qwen3-8B)生成结构化摘要
    • 聚合所有 chunk 的摘要结果
  8. 结构化摘要格式

    {
      "MeetingName": "会议名称",
      "People": {"title": "参会人员", "blocks": [...]},
      "SessionSummary": {"title": "会议概要", "blocks": [...]},
      "CriticalDeadlines": {"title": "关键截止日期", "blocks": [...]},
      "KeyItemsDecisions": {"title": "关键事项与决策", "blocks": [...]},
      "ImmediateActionItems": {"title": "立即行动项", "blocks": [...]},
      "NextSteps": {"title": "后续步骤", "blocks": [...]},
      "MeetingNotes": {"meeting_name": "...", "sections": [...]}
    }
    
  9. 前端渲染

    • 转录内容按 speaker 合并显示
    • 每个 word 带有 data-start/data-end 属性(音字联动)
    • 音频播放时自动高亮当前 word 和 segment
    • 点击 word 跳转到对应时间点

数据库模型

核心模型关系

Meeting (会议)
├── transcriptions → TranscriptSegment[] (转录片段)
├── recording → RecordingSession (录音会话)
├── transcription_jobs → TranscriptionJob[] (转录任务)
├── summary_process → SummaryProcess (摘要处理)
└── exports → MeetingExport[] (导出记录)

TranscriptSegment (转录片段)
├── meeting → Meeting (所属会议)
└── words → JSON (字级时间戳数据)

SummaryProcess (摘要处理)
└── meeting → Meeting (所属会议)

RecordingSession (录音会话)
├── meeting → Meeting (所属会议)
└── checkpoints → RecordingCheckpoint[] (检查点)

关键字段说明

Meeting 模型

字段 类型 说明
title CharField 会议标题
status CharField 状态:recording/paused/completed/processing
audio_file FileField 音频文件路径
audio_duration FloatField 音频时长(秒)
summary JSONField AI 摘要结果
notes TextField 用户笔记
language CharField 语言:auto/zh/en

TranscriptSegment 模型

字段 类型 说明
meeting ForeignKey 关联会议
text TextField 转录文本
speaker CharField 发言人
audio_start_time FloatField 音频开始时间(秒)
audio_end_time FloatField 音频结束时间(秒)
duration FloatField 片段时长(秒)
is_final BooleanField 是否最终结果
words JSONField 字级时间戳(OddASR verbose_json 返回)

words 字段结构(字级时间戳)

[
  {"word": "你好", "start": 0.5, "end": 0.8, "probability": 0.98},
  {"word": "世界", "start": 0.9, "end": 1.2, "probability": 0.95}
]

前端功能

音字联动

前端实现了音频播放与文字的双向联动:

  1. 播放时高亮:音频播放到某个时间点,自动高亮对应的 word 和 segment
  2. 点击跳转:点击某个 word,音频跳转到对应时间点并开始播放
  3. 拖动同步:拖动音频进度条,自动滚动到对应的文字位置

转录编辑模式

支持对转录内容进行编辑:

  • 编辑转录文本
  • 修改发言人名称
  • 批量保存修改

实时电平监测

通过 WebSocket 实时显示麦克风和系统音频的电平:

  • 实时电平条显示
  • AGC 增益信息提示
  • 峰值监测

搜索功能

支持在所有会议的转录内容中进行全文搜索,返回匹配的会议列表和上下文。

技术栈

分类 技术
后端框架 Django 5.0.7
API 框架 Django REST Framework 3.15.2
WebSocket Django Channels 4.1.0
数据库 SQLite(默认)
音频录制 sounddevice
音频处理 pydub、numpy、scipy
语音识别 OddASR(OpenAI 兼容)
AI 摘要 pydantic-ai(Ollama/OpenAI/Claude/Groq)
前端 HTML5、CSS3、JavaScript(原生)

开发命令

# 启动开发服务器
python manage.py runserver 127.0.0.1:9011

# 创建数据库迁移
python manage.py makemigrations

# 执行数据库迁移
python manage.py migrate

# 初始化默认数据
python manage.py init_defaults

# 创建超级用户
python manage.py createsuperuser

# 进入 Django Shell
python manage.py shell

# 运行测试
python manage.py test

注意事项

  1. OddASR 服务:使用前请确保 OddASR 服务已启动并正常运行
  2. FFmpeg:安装 pydub 前需确保 FFmpeg 已安装并添加到系统 PATH
  3. Ollama:使用本地 LLM 生成摘要时,需先 ollama pull qwen3:8b 下载模型
  4. 音频设备权限:首次使用录音功能时需授予麦克风权限
  5. 系统音频录制:Windows 下录制系统音频需要启用立体声混音设备或使用虚拟音频线缆

License

MIT License

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

oddminutes-0.1.0.tar.gz (133.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

oddminutes-0.1.0-py3-none-any.whl (126.7 kB view details)

Uploaded Python 3

File details

Details for the file oddminutes-0.1.0.tar.gz.

File metadata

  • Download URL: oddminutes-0.1.0.tar.gz
  • Upload date:
  • Size: 133.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.0

File hashes

Hashes for oddminutes-0.1.0.tar.gz
Algorithm Hash digest
SHA256 2e3719f4c835a6ab94cc79fb2ae0e0e2330c815defaae63ef6ff83d29b08443f
MD5 3eebce2690f46df63327203bc9e2d209
BLAKE2b-256 876fa6484f72a18729a906b4a1a3de03097d5adc46e540acf6ee28baf99e3a8f

See more details on using hashes here.

File details

Details for the file oddminutes-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: oddminutes-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 126.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.0

File hashes

Hashes for oddminutes-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d3d35a26f8e1b6611033b8ffb5f9e47eaae9c7a2628726a76f49d7b98cc8d44a
MD5 a30bdf9255a45a6d12327017481da019
BLAKE2b-256 7ad079776b155b3eb3e833775ff55722e60f680aef35dfeafb688f7b9b318e7c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page