main
mula.liu 2026-01-19 17:52:53 +08:00
commit 126167715e
36 changed files with 4446 additions and 0 deletions

72
.dockerignore 100644
View File

@ -0,0 +1,72 @@
# Git相关
.git
.gitignore
.gitattributes
# 文档
*.md
README.md
LICENSE
CHANGELOG.md
# 编辑器和IDE
.vscode
.idea
*.swp
*.swo
*~
.DS_Store
# 依赖目录
**/node_modules
**/__pycache__
**/*.pyc
**/.pytest_cache
**/.coverage
**/htmlcov
# 构建产物这些会在Dockerfile中单独处理
**/dist
**/build
**/.next
**/.nuxt
# 环境变量文件
.env
.env.*
!.env.example
# 日志文件
**/*.log
**/logs
**/npm-debug.log*
**/yarn-debug.log*
**/yarn-error.log*
# 测试相关
**/coverage
**/.nyc_output
**/test
**/tests
# 临时文件
**/tmp
**/temp
**/.cache
# Docker相关
docker-compose*.yml
!docker-compose.yml
Dockerfile*
!Dockerfile
# 备份文件
backups/
*.backup
*.bak
# 上传文件会通过volume挂载
uploads/
# 项目备份
project_backup_*/

30
.env.example 100644
View File

@ -0,0 +1,30 @@
# ==================== 数据库配置 ====================
# MySQL数据库配置
MYSQL_ROOT_PASSWORD=Unis@123
MYSQL_DATABASE=imeeting
MYSQL_USER=imeeting
MYSQL_PASSWORD=Unis@123
MYSQL_PORT=3306
# ==================== 缓存配置 ====================
# Redis配置
REDIS_PORT=6379
REDIS_PASSWORD=Unis@123
REDIS_DB=0
# ==================== 应用端口配置 ====================
# iMeeting服务HTTP端口默认80
HTTP_PORT=80
# ==================== 应用配置 ====================
# 应用访问地址(用于生成外部链接、二维码等)
# - 直接访问: http://服务器IP
# - 域名访问: https://your-domain.com 需配置接入服务器Nginx
BASE_URL=https://imeeting.unisspace.com
# 前端API地址通过Nginx代理访问后端
VITE_API_BASE_URL=/api
# ==================== LLM配置 ====================
# 通义千问API密钥请替换为实际密钥
QWEN_API_KEY=sk-c2bf06ea56b4491ea3d1e37fdb472b8f

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

65
.gitignore vendored 100644
View File

@ -0,0 +1,65 @@
# OS files
.DS_Store
Thumbs.db
# Environment variables
.env
backend/.env
frontend/.env
frontend/.env.local
frontend/.env.production.local
# Docker / Data
data/
backups/
logs_export/
# Node.js
node_modules/
frontend/node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
frontend/dist/
frontend/logs/
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
env/
venv/
.env/
.venv/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
backend/venv/
backend/__pycache__/
backend/logs/
# Project specific
backend/uploads/
backend/config/
backend/app.zip
资料/*.zip
# IDEs
.vscode/
.idea/
*.swp
*.swo

682
AI.md 100644
View File

@ -0,0 +1,682 @@
# imeeting 录音AI解析功能技术方案
## 需求分析
用户上传完整的会议录音文件,系统需要完成以下处理:
1. **人声分离**:识别和分离不同的说话人
2. **语音转文字**:将音频内容转换为文字转录
3. **时间戳标记**:为每段对话标记时间戳
4. **智能摘要**:生成会议摘要和关键信息提取
## 技术选择对比
### 1. 语音转文字 (ASR) 技术
#### 选项AOpenAI Whisper
**优势:**
- 开源免费,支持本地部署
- 多语言支持(包括中文)
- 准确率高,特别是对中文识别效果好
- 支持不同模型大小tiny, base, small, medium, large
- 可以输出时间戳信息
- 社区活跃,文档完善
**劣势:**
- 需要GPU加速才能获得最佳性能
- 大模型文件较大large模型约3GB
- 处理速度相对较慢
**部署方式:**
```python
import whisper
model = whisper.load_model("medium")
result = model.transcribe("audio.mp3", language="zh")
```
#### 选项BAzure Speech Services
**优势:**
- 微软云服务,稳定可靠
- 支持实时转录和批量转录
- 中文识别准确率高
- 支持说话人识别
- 自动标点和格式化
**劣势:**
- 需要付费使用
- 依赖网络连接
- 数据隐私考虑
#### 选项C百度语音识别API
**优势:**
- 针对中文优化
- 识别准确率高
- 提供免费额度
- 国内服务稳定
**劣势:**
- 需要付费(超出免费额度)
- API调用限制
- 数据需上传到百度服务器
### 2. 说话人分离 (Speaker Diarization) 技术
#### 选项Apyannote-audio
**优势:**
- 开源免费
- 专业的说话人分离库
- 支持实时和批量处理
- 可以与Whisper很好集成
- 输出详细的说话人时间段信息
**劣势:**
- 需要预训练模型
- 对音频质量要求较高
- 处理复杂场景(多人同时说话)效果有限
**使用示例:**
```python
from pyannote.audio import Pipeline
pipeline = Pipeline.from_pretrained("pyannote/speaker-diarization")
diarization = pipeline("audio.wav")
```
#### 选项BAzure Speaker Recognition
**优势:**
- 集成在Azure Speech Services中
- 可以识别特定说话人身份
- 云端处理,无需本地资源
**劣势:**
- 付费服务
- 需要预先注册说话人声纹
### 3. 智能摘要生成技术
#### 选项AOpenAI GPT API
**优势:**
- 强大的文本理解和总结能力
- 支持中文
- 可以生成结构化摘要
- API调用简单
**劣势:**
- 付费服务
- 需要网络连接
- Token限制
#### 选项B本地LLM如Llama2/ChatGLM
**优势:**
- 可本地部署
- 数据隐私安全
- 一次部署长期使用
**劣势:**
- 需要大量GPU内存
- 部署复杂度高
- 中文效果可能不如专业API
## 推荐技术方案
### 方案一:完全开源方案(推荐)
```
音频文件 → Whisper (语音转文字) → pyannote-audio (说话人分离) → 本地LLM (摘要生成)
```
**技术栈:**
- **ASR**: OpenAI Whisper (medium模型)
- **说话人分离**: pyannote-audio
- **摘要生成**: ChatGLM-6B 或 Llama2-7B-Chat
- **音频处理**: librosa, pydub
- **后端**: Python FastAPI
- **任务队列**: Celery + Redis
**优势:**
- 完全开源无API费用
- 数据隐私安全
- 可控性强,可定制化
**挑战:**
- 需要GPU服务器资源
- 部署复杂度较高
- 需要模型优化调参
### 方案二:混合方案
```
音频文件 → Whisper (语音转文字) → pyannote-audio (说话人分离) → Qwen3 (摘要生成)
```
**优势:**
- ASR和说话人分离本地处理保护音频隐私
- 摘要生成使用成熟API效果好
- 平衡了成本和效果
## 实施架构
### 处理流程
1. **文件上传**: 用户上传音频文件到服务器
2. **预处理**: 音频格式转换、降噪处理
3. **说话人分离**: 使用pyannote-audio识别说话人片段
4. **语音识别**: 使用Whisper对每个说话人片段进行转录
5. **后处理**: 合并转录结果,添加时间戳和说话人标签
6. **摘要生成**: 基于转录文本生成会议摘要
7. **结果存储**: 将处理结果存储到数据库
### 技术要求
- **硬件**: 推荐NVIDIA GPU (4GB+ VRAM)
- **内存**: 16GB+ RAM
- **存储**: SSD存储用于模型文件和临时音频文件
- **网络**: 如使用云API需要稳定网络连接
### 性能估算
对于1小时的会议录音
- **Whisper转录**: 约5-15分钟取决于GPU性能
- **说话人分离**: 约2-5分钟
- **摘要生成**: 约30秒-2分钟
- **总处理时间**: 8-22分钟
## 后续优化方向
1. **实时处理**: 支持流式音频处理
2. **多语言支持**: 扩展到英文等其他语言
3. **说话人识别**: 建立说话人声纹库,实现身份识别
4. **关键词提取**: 自动提取会议关键词和主题
5. **情感分析**: 分析说话人情感倾向
6. **会议洞察**: 生成会议参与度、发言时长等统计信息
## 环境部署指南
### 系统要求
**推荐配置16GB内存 + T4 GPU + Ubuntu**
- **操作系统**: Ubuntu 20.04 LTS 或更高版本
- **GPU**: NVIDIA T4 (16GB VRAM) 或同等性能显卡
- **内存**: 16GB RAM 最低32GB 推荐
- **存储**: 100GB+ SSD存储空间
- **CPU**: 8核心以上处理器
- **Python**: 3.8-3.11
### 1. Whisper 语音转文字环境部署
#### 1.1 安装CUDA和cuDNN
```bash
# 安装NVIDIA驱动
sudo apt update
sudo apt install nvidia-driver-470
# 安装CUDA 11.8
wget https://developer.download.nvidia.com/compute/cuda/11.8.0/local_installers/cuda_11.8.0_520.61.05_linux.run
sudo chmod +x cuda_11.8.0_520.61.05_linux.run
sudo ./cuda_11.8.0_520.61.05_linux.run
# 配置环境变量
echo 'export PATH=/usr/local/cuda-11.8/bin:$PATH' >> ~/.bashrc
echo 'export LD_LIBRARY_PATH=/usr/local/cuda-11.8/lib64:$LD_LIBRARY_PATH' >> ~/.bashrc
source ~/.bashrc
```
#### 1.2 创建Python虚拟环境
```bash
# 安装conda
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.sh
# 创建虚拟环境
conda create -n imeeting python=3.10
conda activate imeeting
```
#### 1.3 安装Whisper和依赖
```bash
# 安装PyTorch (CUDA版本)
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
# 安装Whisper
pip install openai-whisper
# 安装音频处理库
pip install librosa pydub soundfile
# 验证安装
python -c "import whisper; print('Whisper installed successfully')"
```
#### 1.4 下载并测试Whisper模型
```bash
# 在Python中预下载模型
python -c "
import whisper
# 下载medium模型 (适合中文约1.5GB)
model = whisper.load_model('medium')
print('Medium model downloaded successfully')
"
```
#### 1.5 Whisper使用示例
```python
import whisper
import time
# 加载模型
model = whisper.load_model("medium")
# 转录音频
def transcribe_audio(audio_path):
start_time = time.time()
result = model.transcribe(
audio_path,
language="zh", # 中文
task="transcribe",
verbose=True,
word_timestamps=True # 获取词级别时间戳
)
processing_time = time.time() - start_time
print(f"处理时间: {processing_time:.2f}秒")
return result
# 使用示例
# result = transcribe_audio("meeting.wav")
# print(result["text"])
```
### 2. pyannote-audio 说话人分离环境部署
#### 2.1 安装pyannote.audio
```bash
# 激活虚拟环境
conda activate imeeting
# 安装pyannote.audio
pip install pyannote.audio
# 安装额外依赖
pip install pytorch-lightning
```
#### 2.2 获取Hugging Face访问权限
```bash
# 安装huggingface-hub
pip install huggingface-hub
# 登录Hugging Face (需要先在https://huggingface.co注册账号)
huggingface-cli login
```
**注意**: 需要在Hugging Face上申请访问pyannote模型的权限
1. 访问 https://huggingface.co/pyannote/speaker-diarization
2. 点击"Request access"申请访问权限
3. 等待审批通过通常1-2天
#### 2.3 pyannote.audio使用示例
```python
from pyannote.audio import Pipeline
import torch
# 检查GPU是否可用
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"使用设备: {device}")
# 加载说话人分离模型
pipeline = Pipeline.from_pretrained(
"pyannote/speaker-diarization-3.1",
use_auth_token=True # 使用HF token
)
# 将模型移动到GPU
pipeline = pipeline.to(device)
def speaker_diarization(audio_path):
"""说话人分离"""
diarization = pipeline(audio_path)
# 输出结果
speakers_info = []
for turn, _, speaker in diarization.itertracks(yield_label=True):
speakers_info.append({
"speaker": speaker,
"start": turn.start,
"end": turn.end,
"duration": turn.end - turn.start
})
return speakers_info
# 使用示例
# speakers = speaker_diarization("meeting.wav")
# for info in speakers:
# print(f"说话人 {info['speaker']}: {info['start']:.2f}s - {info['end']:.2f}s")
```
### 3. Ollama + 本地LLM 摘要生成环境部署
#### 3.1 安装Ollama
```bash
# 下载并安装Ollama
curl -fsSL https://ollama.ai/install.sh | sh
# 启动Ollama服务
sudo systemctl start ollama
sudo systemctl enable ollama
# 验证安装
ollama --version
```
#### 3.2 下载和配置中文LLM模型
```bash
# 下载Qwen2.5模型 (推荐用于中文摘要)
ollama pull qwen2.5:7b
# 或者下载ChatGLM3模型
ollama pull chatglm3:6b
# 或者下载Llama3.1中文版
ollama pull llama3.1:8b
# 查看已下载的模型
ollama list
```
#### 3.3 配置Ollama服务
```bash
# 创建Ollama配置目录
sudo mkdir -p /etc/systemd/system/ollama.service.d
# 创建配置文件
sudo tee /etc/systemd/system/ollama.service.d/override.conf > /dev/null <<EOF
[Service]
Environment="OLLAMA_HOST=0.0.0.0"
Environment="OLLAMA_NUM_PARALLEL=2"
Environment="OLLAMA_MAX_LOADED_MODELS=2"
Environment="OLLAMA_GPU_MEMORY_FRACTION=0.8"
EOF
# 重新加载配置并重启服务
sudo systemctl daemon-reload
sudo systemctl restart ollama
```
#### 3.4 安装Python客户端
```bash
# 安装Ollama Python客户端
pip install ollama
# 安装其他依赖
pip install requests
```
#### 3.5 LLM摘要生成使用示例
```python
import ollama
import json
class MeetingSummarizer:
def __init__(self, model_name="qwen2.5:7b"):
self.model_name = model_name
self.client = ollama.Client()
def generate_summary(self, transcript_text, speakers_info):
"""生成会议摘要"""
# 构建提示词
prompt = f"""
请根据以下会议转录内容生成详细的会议摘要:
转录内容:
{transcript_text}
请按以下格式输出摘要:
1. 会议概述
2. 主要讨论点
3. 决策事项
4. 待办事项
5. 参会人员发言要点
请用中文回答,保持简洁明了。
"""
try:
response = self.client.chat(
model=self.model_name,
messages=[
{
'role': 'user',
'content': prompt
}
],
options={
'temperature': 0.3,
'top_p': 0.9,
'max_tokens': 2000
}
)
return response['message']['content']
except Exception as e:
print(f"摘要生成错误: {e}")
return None
# 使用示例
# summarizer = MeetingSummarizer()
# summary = summarizer.generate_summary(transcript_text, speakers_info)
# print(summary)
```
### 4. 完整集成部署脚本
#### 4.1 创建部署脚本
```bash
# 创建部署脚本
cat > setup_imeeting_ai.sh << 'EOF'
#!/bin/bash
set -e
echo "开始部署imeeting AI环境..."
# 更新系统
sudo apt update && sudo apt upgrade -y
# 安装必要的系统依赖
sudo apt install -y wget curl git build-essential
# 安装NVIDIA驱动如果还没安装
if ! command -v nvidia-smi &> /dev/null; then
echo "安装NVIDIA驱动..."
sudo apt install -y nvidia-driver-470
echo "请重启系统后重新运行此脚本"
exit 1
fi
# 安装Miniconda
if [ ! -d "$HOME/miniconda3" ]; then
echo "安装Miniconda..."
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.sh -b
rm Miniconda3-latest-Linux-x86_64.sh
fi
# 初始化conda
source ~/miniconda3/bin/activate
# 创建虚拟环境
echo "创建Python虚拟环境..."
conda create -n imeeting python=3.10 -y
conda activate imeeting
# 安装PyTorch和相关库
echo "安装PyTorch..."
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
# 安装AI相关库
echo "安装AI相关库..."
pip install openai-whisper pyannote.audio ollama
pip install librosa pydub soundfile huggingface-hub
# 安装Ollama
echo "安装Ollama..."
curl -fsSL https://ollama.ai/install.sh | sh
# 启动Ollama服务
sudo systemctl start ollama
sudo systemctl enable ollama
# 下载模型
echo "下载模型..."
ollama pull qwen2.5:7b
echo "环境部署完成!"
echo "请使用以下命令激活环境:"
echo "conda activate imeeting"
EOF
chmod +x setup_imeeting_ai.sh
```
#### 4.2 运行部署脚本
```bash
./setup_imeeting_ai.sh
```
### 5. 性能优化建议
#### 5.1 GPU内存优化
```python
import torch
# 清理GPU缓存
def clear_gpu_cache():
if torch.cuda.is_available():
torch.cuda.empty_cache()
# 使用混合精度
from torch.cuda.amp import autocast
# 在推理时使用autocast
with autocast():
result = model.transcribe(audio_path)
```
#### 5.2 批处理优化
```python
# 批量处理音频文件
def batch_process_audio(audio_files, batch_size=2):
results = []
for i in range(0, len(audio_files), batch_size):
batch = audio_files[i:i+batch_size]
# 处理批次
for audio_file in batch:
result = process_single_audio(audio_file)
results.append(result)
# 清理缓存
clear_gpu_cache()
return results
```
### 6. 监控和日志
#### 6.1 系统监控
```bash
# 安装监控工具
pip install nvidia-ml-py3 psutil
# GPU监控脚本
python -c "
import nvidia_ml_py3 as nvml
import psutil
import time
nvml.nvmlInit()
handle = nvml.nvmlDeviceGetHandleByIndex(0)
while True:
# GPU使用率
util = nvml.nvmlDeviceGetUtilizationRates(handle)
print(f'GPU使用率: {util.gpu}%')
# 内存使用
mem_info = nvml.nvmlDeviceGetMemoryInfo(handle)
print(f'GPU内存: {mem_info.used/1024**3:.1f}GB / {mem_info.total/1024**3:.1f}GB')
# CPU和RAM
print(f'CPU使用率: {psutil.cpu_percent()}%')
print(f'RAM使用率: {psutil.virtual_memory().percent}%')
print('-' * 40)
time.sleep(5)
"
```
### 7. 故障排除
#### 7.1 常见问题
1. **CUDA版本不匹配**: 确保PyTorch版本与CUDA版本匹配
2. **GPU内存不足**: 减小模型尺寸或使用CPU模式
3. **Hugging Face访问权限**: 确保已获得pyannote模型访问权限
4. **Ollama服务未启动**: 检查服务状态 `sudo systemctl status ollama`
#### 7.2 测试脚本
```python
# 创建测试脚本
def test_environment():
"""测试环境是否正确配置"""
# 测试CUDA
import torch
print(f"CUDA可用: {torch.cuda.is_available()}")
if torch.cuda.is_available():
print(f"GPU设备: {torch.cuda.get_device_name(0)}")
print(f"GPU内存: {torch.cuda.get_device_properties(0).total_memory / 1024**3:.1f}GB")
# 测试Whisper
try:
import whisper
print("✓ Whisper安装成功")
except ImportError:
print("✗ Whisper安装失败")
# 测试pyannote
try:
from pyannote.audio import Pipeline
print("✓ pyannote.audio安装成功")
except ImportError:
print("✗ pyannote.audio安装失败")
# 测试Ollama
try:
import ollama
client = ollama.Client()
models = client.list()
print(f"✓ Ollama连接成功可用模型: {len(models['models'])}")
except Exception as e:
print(f"✗ Ollama连接失败: {e}")
if __name__ == "__main__":
test_environment()
```
## 开发阶段规划
### 阶段一:基础转录功能
- 集成Whisper进行基础语音转文字
- 实现音频文件上传和处理队列
- 基础的转录结果展示
### 阶段二:说话人分离
- 集成pyannote-audio
- 实现多说话人识别和标记
- 优化音频预处理流程
### 阶段三:智能摘要
- 集成大语言模型或API
- 实现会议摘要自动生成
- 添加关键信息提取功能
### 阶段四:系统优化
- 性能优化和错误处理
- 用户界面完善
- 部署和运维自动化

431
DOCKER_README.md 100644
View File

@ -0,0 +1,431 @@
# Docker部署快速开始
本目录包含完整的Docker Compose部署配置支持一键部署iMeeting应用。
## 📋 文件说明
| 文件 | 说明 |
|------|------|
| `docker-compose.yml` | Docker Compose配置文件 |
| `.env.example` | 环境变量模板 |
| `.dockerignore` | Docker构建忽略文件 |
| `start.sh` ⭐ | 一键启动脚本(推荐) |
| `stop.sh` | 停止服务脚本 |
| `manage.sh` | 服务管理脚本 |
| `generate-ssl-cert.sh` | SSL证书生成脚本 |
| `DOCKER_DEPLOYMENT.md` | 详细部署文档 |
| `DOCKER_README.md` | 本文档 |
## 🏗️ 系统架构
```
方式一:直接访问
用户 → http://服务器IP → iMeeting Nginx (80) → Frontend/Backend
方式二域名访问HTTPS
用户 → https://domain → 接入服务器Nginx (SSL) → iMeeting服务器 (80) → Frontend/Backend
```
**5个服务容器**
- **Nginx**: HTTP入口仅HTTPSSL由接入服务器处理
- **Frontend**: React前端应用
- **Backend**: FastAPI后端服务
- **MySQL**: 数据库
- **Redis**: 缓存
**数据持久化**
- `./data/` - 所有数据存储在此目录
## 🚀 快速开始
### 方式一:使用启动脚本(推荐)
```bash
# 1. 复制并配置环境变量
cp .env.example .env
vim .env # 配置七牛云、LLM密钥等
# 2. 一键启动
./start.sh
```
脚本会自动完成:
- ✅ 检查Docker依赖
- ✅ 创建必要目录
- ✅ 生成SSL证书
- ✅ 配置后端环境变量
- ✅ 构建前端
- ✅ 启动所有服务
- ✅ 等待健康检查
### 方式二:手动启动
```bash
# 1. 配置环境变量
cp .env.example .env
cp backend/.env.example backend/.env
vim .env # 配置主环境变量
vim backend/.env # 配置后端环境变量
# 2. 生成SSL证书
./generate-ssl-cert.sh
# 3. 构建前端
cd frontend
npm install
npm run build
cd ..
# 4. 启动所有服务
docker-compose up -d
# 5. 查看服务状态
docker-compose ps
```
## 🌐 访问地址
启动成功后:
**直接访问HTTP**
- **HTTP访问**: http://localhost 或 http://服务器IP
- **API文档**: http://localhost/docs 或 http://服务器IP/docs
- **API路径**: http://localhost/api/ 或 http://服务器IP/api/
**域名访问HTTPS**
- 需要在接入服务器配置Nginx反向代理
- 参考文档:[GATEWAY_NGINX_CONFIG.md](GATEWAY_NGINX_CONFIG.md)
- 访问示例https://imeeting.yourdomain.com
## ⚙️ 环境变量配置
### 必须配置项
编辑 `.env` 文件,修改以下配置:
```bash
# 七牛云存储(必填,否则无法上传文件)
QINIU_ACCESS_KEY=your_actual_access_key
QINIU_SECRET_KEY=your_actual_secret_key
QINIU_BUCKET=your_bucket_name
QINIU_DOMAIN=your_domain.clouddn.com
# LLM API必填否则无法使用AI功能
QWEN_API_KEY=your_actual_qwen_api_key
# 生产环境必改密码
MYSQL_ROOT_PASSWORD=change_this_password
MYSQL_PASSWORD=change_this_password
REDIS_PASSWORD=change_this_password
```
### 可选配置项
```bash
# 应用访问地址(用于生成二维码等)
BASE_URL=http://localhost # 生产环境改为: https://your-domain.com
# Nginx端口默认80/443
HTTP_PORT=80
HTTPS_PORT=443
# 如需直接访问后端/前端(开发调试用)
# BACKEND_PORT=8001
# FRONTEND_PORT=3001
```
## 📦 数据目录
所有数据存储在 `./data/` 目录:
```
data/
├── mysql/ # MySQL数据库文件
├── redis/ # Redis持久化文件
├── uploads/ # 用户上传的文件(音频、图片等)
└── logs/ # 日志文件
├── backend/
├── frontend/
└── nginx/
```
**重要提示**
- 定期备份 `data/` 目录
- 生产环境建议挂载独立数据盘到 `./data/`
## 🔧 日常管理
### 使用管理脚本(推荐)
```bash
./manage.sh
```
交互式菜单提供以下功能:
1. 查看服务状态
2. 查看实时日志
3. 重启所有服务
4. 重启单个服务
5. 进入容器终端
6. **备份数据库**
7. 恢复数据库
8. 清理Redis缓存
9. 更新服务
10. 查看资源使用
11. 导出日志
### 常用命令
```bash
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs -f # 所有服务
docker-compose logs -f nginx # Nginx日志
docker-compose logs -f backend # 后端日志
tail -f data/logs/nginx/imeeting_access.log # 访问日志
# 重启服务
docker-compose restart # 重启所有
docker-compose restart nginx # 重启Nginx
# 停止服务
./stop.sh # 交互式停止
docker-compose down # 停止并删除容器
```
## 🔐 域名和HTTPS配置
iMeeting服务器本身仅提供HTTP服务。如需通过域名访问HTTPS需要在接入服务器配置Nginx反向代理。
### 配置接入服务器
完整配置步骤请参考:[GATEWAY_NGINX_CONFIG.md](GATEWAY_NGINX_CONFIG.md)
**简要步骤**
1. 在接入服务器安装Nginx
2. 使用Let's Encrypt获取SSL证书
3. 配置Nginx反向代理到iMeeting服务器IP
4. 配置DNS A记录指向接入服务器
**配置示例**
```nginx
server {
listen 443 ssl http2;
server_name imeeting.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/imeeting.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/imeeting.yourdomain.com/privkey.pem;
location / {
proxy_pass http://iMeeting服务器IP:80;
# ... 其他配置
}
}
```
详见:[GATEWAY_NGINX_CONFIG.md](GATEWAY_NGINX_CONFIG.md)
## 🔍 故障排查
### 查看日志
```bash
# 服务日志
docker-compose logs -f
# 文件日志
tail -f data/logs/nginx/imeeting_error.log
tail -f data/logs/backend/*.log
```
### 检查服务状态
```bash
docker-compose ps
```
所有服务应显示 `healthy` 状态。
### 测试连接
```bash
# 测试Nginx
curl http://localhost/health
# 测试HTTPS
curl -k https://localhost/health
# 测试API文档
curl http://localhost/docs
```
### 常见问题
| 问题 | 解决方法 |
|------|----------|
| 端口被占用 | 修改.env中的HTTP_PORT |
| 502错误 | 检查backend和frontend是否健康 |
| 数据库连接失败 | 检查backend/.env配置 |
| 前端无法访问API | 检查VITE_API_BASE_URL配置 |
| 如何配置HTTPS | 参考GATEWAY_NGINX_CONFIG.md配置接入服务器 |
详见:`DOCKER_DEPLOYMENT.md` 故障排查章节
## 📊 服务组件
| 服务 | 容器名 | 内部端口 | 外部端口 | 健康检查 |
|------|--------|----------|----------|----------|
| Nginx | imeeting-nginx | 80 | 80 | ✅ |
| Frontend | imeeting-frontend | 3001 | - | ✅ |
| Backend | imeeting-backend | 8001 | - | ✅ |
| MySQL | imeeting-mysql | 3306 | - | ✅ |
| Redis | imeeting-redis | 6379 | - | ✅ |
外部仅暴露Nginx的80端口HTTP其他服务通过内部网络通信。
如需HTTPS请在接入服务器配置SSL。
## 🔄 更新部署
### 更新代码
```bash
# 拉取最新代码
git pull
# 重新构建
docker-compose build
# 重启服务
docker-compose up -d
```
### 仅更新前端
```bash
cd frontend
npm run build
cd ..
docker-compose build frontend
docker-compose up -d frontend
docker-compose restart nginx
```
### 仅更新后端
```bash
docker-compose build backend
docker-compose up -d backend
```
## 💾 备份与恢复
### 备份数据库
```bash
# 使用管理脚本
./manage.sh # 选择"6) 备份数据库"
# 或手动执行
docker-compose exec mysql mysqldump -uroot -p imeeting > backup.sql
```
### 备份所有数据
```bash
# 备份data目录
tar czf imeeting_backup_$(date +%Y%m%d).tar.gz data/
# 备份配置
tar czf imeeting_config_$(date +%Y%m%d).tar.gz .env backend/.env nginx/
```
### 恢复数据
```bash
# 恢复数据库
docker-compose exec -T mysql mysql -uroot -p imeeting < backup.sql
# 恢复data目录
tar xzf imeeting_backup_20240101.tar.gz
```
## 🛡️ 安全提示
生产环境部署前,请务必:
1. ✅ **修改所有默认密码**
- MYSQL_ROOT_PASSWORD
- MYSQL_PASSWORD
- REDIS_PASSWORD
2. ✅ **配置真实SSL证书**
- 使用Let's Encrypt或商业证书
- 不要使用自签名证书
3. ✅ **设置文件权限**
```bash
chmod 600 .env backend/.env
chmod 600 nginx/ssl/server.key
```
4. ✅ **启用防火墙**
```bash
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
```
5. ✅ **定期备份数据**
- 设置自动备份脚本
- 异地备份
6. ✅ **监控日志**
- 定期检查错误日志
- 设置日志轮转
## 📚 更多信息
详细的部署说明、配置选项、性能优化等,请查看:
- **详细部署文档**: [DOCKER_DEPLOYMENT.md](DOCKER_DEPLOYMENT.md)
- **Nginx配置说明**: [nginx/README.md](nginx/README.md)
## 🆘 获取帮助
如遇问题:
1. 查看日志:`docker-compose logs -f`
2. 查看健康状态:`docker-compose ps`
3. 查看详细文档:`DOCKER_DEPLOYMENT.md`
4. 提交Issue到项目仓库
## 📞 快速命令参考
```bash
# 启动
./start.sh # 一键启动(推荐)
docker-compose up -d # 启动所有服务
# 管理
./manage.sh # 管理菜单(推荐)
docker-compose ps # 查看状态
docker-compose logs -f # 查看日志
docker-compose restart # 重启服务
# 停止
./stop.sh # 停止服务(推荐)
docker-compose down # 停止并删除容器
# 备份
./manage.sh # 选择备份功能
tar czf backup.tar.gz data/ # 备份所有数据
# 更新
git pull && docker-compose build && docker-compose up -d
```
---
**祝您使用愉快!** 🎉

167
README.md 100644
View File

@ -0,0 +1,167 @@
# iMeeting - 智慧会议平台
## 项目简介
iMeeting 是一个基于 AI 技术的智能会议记录与内容管理平台,通过自动化的语音转录、说话人识别和 AI 摘要功能,帮助专业人士高效管理会议内容,从繁琐的记录工作中解放出来。
## 核心价值
- **解放生产力** - 自动化的会议转录和摘要,让用户从繁琐的记录工作中解放出来
- **信息不丢失** - 精准记录每一次会议的细节,确保关键信息和决策得到妥善保存
- **高效回顾** - 通过时间轴、发言人和关键词,快速定位会议内容
- **便捷分享** - 轻松分享会议纪要、材料和关键节点给相关人员
## 技术栈
### 平台端 (Backend)
- **框架**: Python 3.9+ / FastAPI
- **数据库**: MySQL 5.7+
- **缓存**: Redis 5.0+
- **AI服务**: 阿里云通义千问 (Dashscope)
- 语音识别: Paraformer-v2
- 说话人分离
- 大语言模型摘要
- **存储**: 本地对象存储
- **身份认证**: JWT / Python-JOSE
- **部署**: Docker / Nginx
### 客户端 (Frontend)
- **框架**: React 19.1 + Vite 7.0
- **UI组件**: Ant Design 5.27
- **路由**: React Router DOM 7.7
- **Markdown**: @uiw/react-md-editor 4.0
- **可视化**: Markmap (思维导图)
- **其他工具**:
- Axios (HTTP 客户端)
- html2canvas + jsPDF (导出功能)
- QRCode.react (二维码生成)
- Lucide React (图标库)
## 功能模块
### 平台功能
| 功能模块 | 功能描述 | 状态 |
|---------|---------|------|
| **用户管理** | 用户创建、编辑、删除、密码重置、角色权限管理 | ✅ 已完成 |
| **会议管理** | 会议创建、编辑、删除、参会人员管理 | ✅ 已完成 |
| **音频处理** | 音频文件上传、存储、格式验证 | ✅ 已完成 |
| **异步转录服务** | 基于Paraformer的异步语音识别 | ✅ 已完成 |
| **说话人分离** | 基于CAM++ ,支持自定义标签 | ✅ 已完成 |
| **AI 摘要生成** | 异步生成会议纪要,支持自定义 Prompt | ✅ 已完成 |
| **任务状态管理** | 转录任务和 LLM 任务的状态追踪 | ✅ 已完成 |
| **声纹采集** | 用户声纹数据采集和管理 | ✅ 已完成 |
| **身份认证** | JWT Token 认证、登录登出、Token 刷新 | ✅ 已完成 |
| **图片上传** | 会议相关图片上传,支持 Markdown 引用 | ✅ 已完成 |
| **多会议知识模块** | 基于多会议摘要的知识总结 | ✅ 已完成 |
| **完整的对外接口** | 提供基于PC客户端、手机客户端、专用设备的服务接口 | ✅ 已完成 |
| | | |
| *待扩展功能* | *以下功能将在后续版本中添加* | |
| **对话模式的M-Agent** | 对话模式的会议Agent| |
| **平台多租户**| 云平台支持多租户| |
### PC客户端功能
| 功能模块 | 功能描述 | 状态 |
|---------|---------|------|
| **用户登录** | 登录界面、Token 存储、自动登录 | ✅ 已完成 |
| **会议列表** | 会议展示、筛选、搜索 | ✅ 已完成 |
| **会议采集** | 支持快速会议和自定义会议 | ✅ 已完成 |
| **导出功能** | 会议纪要预览 | ✅ 已完成 |
| **响应式设计** | 适配不同屏幕尺寸 | ✅ 已完成 |
| | | |
| *待扩展功能* | *以下功能将在后续版本中添加* | |
| **声纹采集界面** | 声纹录制、上传、状态管理 | |
| **会议总结概览** | 获取按会议ID的总结一览| |
### 手机客户端功能
| 功能模块 | 功能描述 | 状态 |
|---------|---------|------|
## 快速开始
### 环境要求
- Node.js 16+
- Python 3.9+
- MySQL 5.7+
- Redis 5.0+
- Docker (可选)
### 安装与运行
#### 后端启动
```bash
cd backend
pip install -r requirements.txt
python main.py
```
默认运行在 `http://localhost:8000`
#### 前端启动
```bash
cd frontend
npm install
npm run dev
```
默认运行在 `http://localhost:5173`
### 配置说明
详细的配置文档请参考:
- 数据库设计: [database.md](./database.md)
- 项目详细设计: [project.md](./project.md)
- AI 集成文档: [AI.md](./AI.md)
## 核心特性
### 异步任务处理
系统采用异步任务架构,支持大文件和长时间处理:
- **语音转录任务**: 基于阿里云 Dashscope 的异步 API,支持任务状态追踪
- **AI 摘要任务**: 使用 FastAPI BackgroundTasks,支持进度更新和轮询
### 数据安全
- JWT Token 认证机制
- 基于角色的权限控制 (RBAC)
- 密码 bcrypt 加密
- Token 黑名单机制
### 高性能
- Redis 缓存任务状态
- 异步处理避免阻塞
- 分页查询优化
- 音频流式传输
## API 文档
启动后端服务后,访问以下地址查看 API 文档:
- Swagger UI: `http://localhost:8000/docs`
- ReDoc: `http://localhost:8000/redoc`
## 未来规划
- [ ] 实时转录 - 支持对正在进行的会议进行实时语音转文字
- [ ] 日历集成 - 与 Google Calendar、Outlook Calendar 集成
- [ ] 行动项提取 - AI 自动识别会议中的待办事项
- [ ] 跨会议搜索 - 对所有会议内容进行全文语义搜索
- [ ] 移动端应用 - 开发 iOS 和 Android 原生应用
- [ ] 多语言支持 - 支持中英文等多语言界面
- [ ] 会议协作 - 支持多人实时协作编辑会议纪要
- [ ] 数据分析 - 会议统计分析和可视化报表
## 许可证
[请添加许可证信息]
## 联系方式
[请添加联系方式]

908
ROADMAP.md 100644
View File

@ -0,0 +1,908 @@
# iMeeting 产品路线图
## 项目概述
iMeeting 是一个智能会议管理和知识库系统,旨在通过 AI 技术提升会议效率,自动生成会议纪要,并从多次会议中提炼知识。
---
## Phase 1: 基础会议管理与知识库系统(已完成)
### 核心功能
#### 1. 会议管理
- **会议创建与录音**:支持创建会议并关联音频文件
- **音频转录**:基于阿里云 DashScope 的语音识别,支持异步转录
- **AI 总结生成**:使用大语言模型(通义千问)自动生成会议纪要
- **提示词模版**:支持预定义和自定义提示词模版,适配不同会议场景
- **标签系统**:支持为会议添加标签,方便分类和检索
#### 2. 知识库系统
- **基于会议的知识提炼**:从多个会议纪要中提炼知识库内容
- **自定义提示词**:用户可以指定特定的分析角度和总结需求
- **Markdown 输出**:知识库内容以 Markdown 格式存储和展示
- **标签关联**:支持知识库的标签分类
- **共享机制**:支持知识库的个人/共享模式
#### 3. 用户权限管理
- **用户认证**:基于 JWT 的用户登录与会话管理
- **角色权限**:区分普通用户和管理员
- **菜单权限**:动态菜单权限控制系统
#### 4. 管理后台
- **用户管理**:用户创建、编辑、删除、权限配置
- **系统监控**:在线用户、任务监控、系统资源监控
- **提示词仓库**:集中管理所有提示词模版
### 技术架构
#### 后端技术栈
- **框架**FastAPIPython
- **数据库**MySQL 8.0
- **缓存**Redis 5.0+
- **AI 服务**:阿里云 DashScope通义千问
- **对象存储**:七牛云 OSS
- **异步任务**FastAPI BackgroundTasks
#### 前端技术栈
- **框架**React 18
- **路由**React Router
- **UI 组件**Ant Design + 自定义组件
- **Markdown 渲染**react-markdown
#### 数据模型(核心表)
- `users`:用户表
- `meetings`:会议表
- `knowledge_bases`:知识库表
- `prompts`:提示词模版表
- `transcription_tasks`:转录任务表
- `summary_tasks`:总结任务表
- `knowledge_base_tasks`:知识库生成任务表
- `tags`:标签表
---
## Phase 2: 知识库系统大升级(规划中)
### 升级目标
将知识库系统从单一的"会议纪要汇总"升级为功能完整的"AI 知识助手",参考 NotebookLM 的交互模式,提供多维度的知识管理和音频播客生成能力。
---
### 1. 输入来源扩展
#### 1.1 功能需求
- ✅ **会议来源**(已支持):从多个会议纪要中提炼
- 🆕 **外部文件上传**
- 支持 PDF、Word、TXT、Markdown 文件
- 支持音频文件MP3、WAV、M4A
- 支持视频文件MP4、AVI、MOV提取音频
- 单个知识库可混合多种来源
#### 1.2 技术方案
##### 文档解析
```python
# 依赖库选型
- PDF: PyPDF2 / pdfplumber文本提取
- Word: python-docxDOCX 文件)
- Markdown: 直接读取
- TXT: 直接读取支持多种编码UTF-8、GBK
```
**技术评估**
- ✅ **可行性**Python 生态成熟
- ⚠️ **挑战**
- PDF 中的表格、图片识别(可选用 OCR
- 大文件处理(需要分块上传和处理)
- 💰 **成本**:无额外费用,依赖开源库
##### 音频/视频处理
```python
# 依赖库选型
- 音频提取: ffmpeg-python视频转音频
- 音频格式转换: pydub
```
**技术评估**
- ✅ **可行性**:高,现有转录流程可复用
- ⚠️ **挑战**
- 视频文件较大,需要优化存储和处理
- 需要增加进度反馈
- 💰 **成本**
- 视频存储成本增加(七牛云存储费用)
- 转录费用与现有一致(按时长计费)
##### 数据库设计
```sql
-- 新增表:知识库来源文件表
CREATE TABLE kb_source_files (
file_id INT AUTO_INCREMENT PRIMARY KEY,
kb_id INT NOT NULL COMMENT '关联的知识库ID',
file_type ENUM('pdf', 'docx', 'txt', 'markdown', 'audio', 'video') NOT NULL,
file_name VARCHAR(255) NOT NULL,
file_url VARCHAR(512) NOT NULL COMMENT '文件存储URL',
file_size BIGINT COMMENT '文件大小(字节)',
extracted_text TEXT COMMENT '提取的文本内容',
upload_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (kb_id) REFERENCES knowledge_bases(kb_id) ON DELETE CASCADE
);
-- 修改知识库表
ALTER TABLE knowledge_bases
ADD COLUMN source_type ENUM('meetings', 'files', 'mixed') DEFAULT 'meetings' COMMENT '内容来源类型';
```
---
### 2. 提示词模版升级
#### 2.1 功能需求
- ✅ **选择模版**(已支持):从提示词仓库选择预设模版
- 🆕 **附加提示词**:在模版基础上追加自定义需求
- 🆕 **结构化输出**:生成标题 + 多级内容(章节、小节)
- 🆕 **输出格式控制**支持指定输出结构JSON Schema
#### 2.2 技术方案
##### 提示词组合
```python
def build_knowledge_prompt(
template_prompt: str, # 基础模版
additional_prompt: str, # 附加提示词
output_format: dict # 输出格式控制
) -> str:
"""
组合提示词策略:
1. 基础模版(定义分析维度和风格)
2. 附加提示词(用户自定义需求)
3. 输出格式要求(结构化 JSON 或 Markdown
"""
return f"""
{template_prompt}
## 用户补充要求
{additional_prompt}
## 输出格式要求
请按照以下结构输出Markdown 格式):
# 标题
## 章节1
### 小节1.1
内容...
### 小节1.2
内容...
## 章节2
...
"""
```
**技术评估**
- ✅ **可行性**:高,现有提示词系统可直接扩展
- 📊 **优化方向**
- 使用通义千问的 `response_format` 参数实现结构化输出
- 提供可视化的输出结构编辑器
- 💰 **成本**:无额外成本
##### 结构化输出(通义千问支持)
```python
# 通义千问支持 JSON Schema 格式控制
response_format = {
"type": "json_schema",
"json_schema": {
"name": "knowledge_base_output",
"schema": {
"type": "object",
"properties": {
"title": {"type": "string"},
"sections": {
"type": "array",
"items": {
"type": "object",
"properties": {
"section_title": {"type": "string"},
"subsections": {
"type": "array",
"items": {
"type": "object",
"properties": {
"subsection_title": {"type": "string"},
"content": {"type": "string"}
}
}
}
}
}
}
}
}
}
}
```
---
### 3. 音频概览生成TTS 播客)
#### 3.1 功能需求
- 🆕 **文字转语音**:将知识库内容转换为音频
- 🆕 **播客式对话**(类似 NotebookLM
- 双人对话形式(主持人 + 嘉宾)
- 自然的问答式讲解
- 语气生动,易于理解
#### 3.2 技术方案
##### 方案一:基础 TTS快速实现
**服务选型**
```python
# 1. 阿里云语音合成(推荐)
- 优势:已集成 DashScope音质自然支持多音色
- 成本:约 0.002 元/次100字符
- 特性:支持 SSML 标签控制语速、停顿
# 2. 微软 Azure TTS
- 优势:音质最佳,支持神经网络语音
- 成本:约 $4/百万字符
- 特性:支持情感控制、多语言
# 3. OpenAI TTS
- 优势:音质优秀,与 GPT 集成度高
- 成本:约 $15/百万字符
- 特性6 种不同音色可选
```
**实现流程**
```python
async def generate_basic_audio(kb_content: str) -> str:
"""
基础 TTS 实现
1. 文本预处理(分段、去除特殊字符)
2. 调用 TTS API
3. 音频文件合并
4. 上传到七牛云
"""
# 分段处理(避免单次请求过长)
segments = split_text_by_paragraphs(kb_content, max_length=500)
audio_files = []
for segment in segments:
audio = await tts_service.synthesize(
text=segment,
voice="zhichu", # 阿里云音色
rate=1.0, # 语速
pitch=0 # 音调
)
audio_files.append(audio)
# 合并音频
final_audio = merge_audio_files(audio_files)
audio_url = upload_to_qiniu(final_audio, "kb_audio")
return audio_url
```
**技术评估**
- ✅ **可行性**:高,实现简单
- ⚠️ **局限性**
- 单调朗读,无对话感
- 缺乏停顿和情感
- 💰 **成本**
- 阿里云 TTS约 0.02 元/千字
- 10 万字知识库:约 2 元/次
---
##### 方案二播客式对话NotebookLM 风格)
**技术架构**
```
输入: 知识库内容 (Markdown)
1. 内容理解与脚本生成
- 使用 LLM 将内容改写为对话脚本
- 双人角色:主持人(引导)+ 专家(讲解)
2. 对话脚本优化
- 添加开场白和结束语
- 插入自然的停顿和过渡
- 添加情感标记SSML
3. 多音色 TTS 合成
- 主持人音色:女声,温和亲切
- 专家音色:男声,稳重专业
4. 音频后处理
- 添加背景音乐(轻音乐)
- 音量均衡化
- 添加片头片尾
输出: 播客式音频文件 (MP3)
```
**LLM 脚本生成示例**
```python
PODCAST_SCRIPT_PROMPT = """
你是一个播客制作专家。请将以下知识库内容改写为一段双人对话脚本:
- 主持人Host提出问题引导话题语气轻松友好
- 专家Expert讲解内容回答问题语气专业自信
要求:
1. 开场白介绍今天的主题
2. 通过问答形式逐步展开知识点
3. 加入自然的过渡语("那么..."、"接下来..."
4. 结束时做简短总结
知识库内容:
{kb_content}
请输出 JSON 格式:
{{
"title": "播客标题",
"intro": {{
"host": "开场白...",
"expert": "回应..."
}},
"dialogues": [
{{"speaker": "host", "text": "问题1..."}},
{{"speaker": "expert", "text": "解答1..."}},
...
],
"outro": {{
"host": "总结...",
"expert": "结束语..."
}}
}}
"""
async def generate_podcast_script(kb_content: str) -> dict:
"""使用 LLM 生成播客脚本"""
response = await llm_service.call(
prompt=PODCAST_SCRIPT_PROMPT.format(kb_content=kb_content),
response_format={"type": "json_object"}
)
return json.loads(response)
async def synthesize_podcast(script: dict) -> str:
"""合成播客音频"""
audio_segments = []
# 片头音乐
audio_segments.append(load_intro_music())
# 开场白
for speaker, text in script["intro"].items():
voice = VOICES[speaker] # {"host": "xiaoyun", "expert": "zhichu"}
audio = await tts_service.synthesize(text, voice=voice)
audio_segments.append(audio)
audio_segments.append(silence(duration=0.5)) # 停顿 0.5 秒
# 主体对话
for dialogue in script["dialogues"]:
speaker = dialogue["speaker"]
text = dialogue["text"]
voice = VOICES[speaker]
audio = await tts_service.synthesize(text, voice=voice)
audio_segments.append(audio)
audio_segments.append(silence(duration=0.3))
# 结束语
for speaker, text in script["outro"].items():
voice = VOICES[speaker]
audio = await tts_service.synthesize(text, voice=voice)
audio_segments.append(audio)
# 片尾音乐
audio_segments.append(load_outro_music())
# 合并所有音频
final_audio = merge_with_background_music(audio_segments)
# 上传到七牛云
audio_url = upload_to_qiniu(final_audio, "kb_podcast")
return audio_url
```
**技术评估**
- ✅ **可行性**:中等
- LLM 脚本生成:成熟方案
- 多音色 TTS阿里云、Azure 均支持
- 音频后处理:需要 ffmpeg 或 pydub
- ⚠️ **挑战**
- 脚本质量依赖 LLM prompt 优化
- 音频合成时长较长(需要异步处理)
- 音频文件较大,存储成本增加
- 💰 **成本**(以 5000 字知识库为例):
- LLM 脚本生成(输入 5000 字 + 输出 3000 字):约 0.05 元
- TTS 合成(约 3000 字对话):约 0.06 元
- **总成本:约 0.11 元/次**
**音频处理库**
```python
# 新增依赖
ffmpeg-python==0.2.0 # 音频处理
pydub==0.25.1 # 音频编辑
```
---
##### 方案对比
| 特性 | 方案一:基础 TTS | 方案二:播客对话 |
|------|------------------|------------------|
| **实现难度** | 低1-2 天) | 中3-5 天) |
| **音频质量** | 单调朗读 | 自然对话 |
| **用户体验** | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| **成本** | 0.02 元/千字 | 0.11 元/5000 字 |
| **适用场景** | 快速阅读 | 深度学习 |
**推荐方案**
- 🚀 **Phase 2.1**:先实现方案一(基础 TTS快速上线
- 🎯 **Phase 2.2**:再实现方案二(播客对话),提升体验
---
### 4. NotebookLM 式交互
#### 4.1 功能需求
- 🆕 **知识库问答**:基于知识库内容的智能问答
- 🆕 **引用溯源**:回答时显示来源(段落、页码)
- 🆕 **相关内容推荐**:基于用户提问推荐相关知识点
- 🆕 **多轮对话**:支持上下文记忆的连续对话
#### 4.2 技术方案
##### 方案一:基于向量数据库的 RAG推荐
**技术架构**
```
知识库内容
1. 文本分块 (Chunking)
- 按段落或语义分块500-1000 字/块)
- 保留元数据(来源、章节、页码)
2. 向量化 (Embedding)
- 使用阿里云通义千问 Embedding API
- 或使用 OpenAI text-embedding-3-small
3. 存储到向量数据库
- Milvus开源功能强大
- 或 Qdrant轻量易部署
- 或 PostgreSQL + pgvector复用现有数据库
4. 用户提问
5. 向量检索
- 将问题向量化
- 检索 Top-K 相似内容块
6. LLM 生成回答
- 将检索结果作为上下文
- 生成准确回答 + 来源引用
```
**实现示例**
```python
from dashscope import TextEmbedding
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct
# 1. 向量化服务
class EmbeddingService:
def embed_text(self, text: str) -> List[float]:
"""将文本转换为向量"""
response = TextEmbedding.call(
model='text-embedding-v3',
input=text
)
return response.output['embeddings'][0]['embedding']
# 2. 向量数据库
class VectorStore:
def __init__(self):
self.client = QdrantClient(host="localhost", port=6333)
def create_collection(self, kb_id: int):
"""为知识库创建向量集合"""
self.client.create_collection(
collection_name=f"kb_{kb_id}",
vectors_config=VectorParams(size=1536, distance=Distance.COSINE)
)
def add_chunks(self, kb_id: int, chunks: List[dict]):
"""添加文本块到向量库"""
points = []
for i, chunk in enumerate(chunks):
embedding = embedding_service.embed_text(chunk['text'])
points.append(PointStruct(
id=i,
vector=embedding,
payload={
"text": chunk['text'],
"source": chunk['source'],
"section": chunk['section']
}
))
self.client.upsert(collection_name=f"kb_{kb_id}", points=points)
def search(self, kb_id: int, query: str, top_k: int = 3):
"""搜索相似内容"""
query_vector = embedding_service.embed_text(query)
results = self.client.search(
collection_name=f"kb_{kb_id}",
query_vector=query_vector,
limit=top_k
)
return results
# 3. RAG 问答
async def answer_question(kb_id: int, question: str, chat_history: List[dict] = None):
"""基于知识库回答问题"""
# 检索相关内容
results = vector_store.search(kb_id, question, top_k=3)
# 构建上下文
context = "\n\n".join([
f"[来源: {r.payload['section']}]\n{r.payload['text']}"
for r in results
])
# 构建 prompt
prompt = f"""
基于以下知识库内容回答用户问题。如果无法从内容中找到答案,请明确告知。
知识库内容:
{context}
用户问题:{question}
请提供准确的回答,并在回答中标注来源章节。
"""
# 调用 LLM
response = await llm_service.call(prompt, chat_history=chat_history)
# 返回回答 + 来源
return {
"answer": response,
"sources": [
{"section": r.payload['section'], "text": r.payload['text'][:200]}
for r in results
]
}
```
**技术评估**
- ✅ **可行性**:高
- 向量数据库Qdrant轻量级或 pgvector复用 MySQL
- Embedding阿里云通义千问 Embedding API0.0007 元/千 tokens
- 📊 **优势**
- 回答准确性高(基于实际内容)
- 支持引用溯源
- 检索速度快(毫秒级)
- 💰 **成本**(以 10 万字知识库为例):
- 向量化:约 0.07 元(一次性)
- 每次问答检索:免费(本地向量库)
- LLM 生成:约 0.01 元/次
---
##### 方案二:基于 LLM 长上下文(备选)
**技术方案**
```python
async def answer_with_full_context(kb_content: str, question: str):
"""直接将整个知识库作为上下文"""
prompt = f"""
你是一个知识库助手。请基于以下知识库内容回答用户问题。
知识库内容:
{kb_content}
用户问题:{question}
请提供准确的回答,并标注引用的段落。
"""
response = await llm_service.call(prompt)
return response
```
**技术评估**
- ✅ **可行性**:中等
- 通义千问支持 128K tokens 上下文
- 约 10 万字中文
- ⚠️ **局限性**
- 大文本上下文成本高
- 无法精确定位来源
- 不支持多知识库联合查询
- 💰 **成本**
- 每次问答10 万字上下文):约 0.15 元
- **比 RAG 方案贵 10 倍以上**
**推荐方案****方案一RAG** 为主,方案二作为小规模知识库的快速方案。
---
##### 数据库设计
```sql
-- 知识库对话历史表
CREATE TABLE kb_chat_history (
chat_id INT AUTO_INCREMENT PRIMARY KEY,
kb_id INT NOT NULL COMMENT '关联知识库ID',
user_id INT NOT NULL COMMENT '用户ID',
question TEXT NOT NULL COMMENT '用户提问',
answer TEXT NOT NULL COMMENT 'AI回答',
sources JSON COMMENT '回答来源JSON数组',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (kb_id) REFERENCES knowledge_bases(kb_id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE,
INDEX idx_kb_user (kb_id, user_id),
INDEX idx_created_at (created_at)
);
-- 知识库向量块表
CREATE TABLE kb_text_chunks (
chunk_id INT AUTO_INCREMENT PRIMARY KEY,
kb_id INT NOT NULL COMMENT '关联知识库ID',
chunk_text TEXT NOT NULL COMMENT '文本块内容',
chunk_metadata JSON COMMENT '元数据(章节、页码等)',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (kb_id) REFERENCES knowledge_bases(kb_id) ON DELETE CASCADE,
INDEX idx_kb_id (kb_id)
);
```
---
### 5. 前端交互升级
#### 5.1 新增页面/组件
```
知识库详情页
├── 📄 内容展示区
│ ├── Markdown 渲染(已有)
│ └── 音频播放器(新增)
│ ├── 播放/暂停
│ ├── 进度条
│ ├── 倍速调节
│ └── 下载音频
├── 💬 智能问答区(新增)
│ ├── 对话输入框
│ ├── 对话历史列表
│ ├── 来源引用卡片
│ └── 相关问题推荐
└── 📊 知识库信息
├── 来源文件列表(新增)
└── 标签、创建时间等(已有)
```
#### 5.2 技术实现
```jsx
// 音频播放器组件
import ReactAudioPlayer from 'react-audio-player';
const KnowledgeAudioPlayer = ({ audioUrl }) => {
return (
<div className="audio-player-container">
<h3>🎧 音频概览</h3>
<ReactAudioPlayer
src={audioUrl}
controls
autoPlay={false}
controlsList="nodownload"
/>
</div>
);
};
// 智能问答组件
const KnowledgeChatbot = ({ kbId }) => {
const [messages, setMessages] = useState([]);
const [input, setInput] = useState('');
const [loading, setLoading] = useState(false);
const handleAsk = async () => {
setLoading(true);
const response = await apiClient.post(`/knowledge-bases/${kbId}/ask`, {
question: input,
chat_history: messages
});
setMessages([
...messages,
{ role: 'user', content: input },
{
role: 'assistant',
content: response.data.answer,
sources: response.data.sources
}
]);
setInput('');
setLoading(false);
};
return (
<div className="chatbot-container">
<div className="chat-history">
{messages.map((msg, idx) => (
<div key={idx} className={`message ${msg.role}`}>
<div className="message-content">{msg.content}</div>
{msg.sources && (
<div className="message-sources">
<h4>📚 来源</h4>
{msg.sources.map((src, i) => (
<div key={i} className="source-card">
<strong>{src.section}</strong>
<p>{src.text}...</p>
</div>
))}
</div>
)}
</div>
))}
</div>
<div className="chat-input">
<input
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="向知识库提问..."
onKeyPress={(e) => e.key === 'Enter' && handleAsk()}
/>
<button onClick={handleAsk} disabled={loading}>
{loading ? '思考中...' : '发送'}
</button>
</div>
</div>
);
};
```
---
## Phase 2 技术依赖汇总
### 新增 Python 依赖
```txt
# 文档解析
PyPDF2==3.0.1
pdfplumber==0.10.3
python-docx==1.1.0
# 音频处理
ffmpeg-python==0.2.0
pydub==0.25.1
# 向量数据库(二选一)
qdrant-client==1.7.0 # 推荐:轻量级向量库
# 或
pgvector==0.2.3 # 备选PostgreSQL 扩展
# 阿里云 Embedding可选通义千问已集成
# 无需新增依赖,使用现有 dashscope
```
### 新增前端依赖
```json
{
"react-audio-player": "^0.17.0",
"react-markdown": "^9.0.0" // 已有
}
```
### 基础设施
- **向量数据库**QdrantDocker 部署)
```bash
docker run -p 6333:6333 qdrant/qdrant
```
- **音频处理**FFmpeg系统依赖
```bash
apt-get install ffmpeg # Ubuntu
brew install ffmpeg # macOS
```
---
## 成本预估Phase 2
### 开发成本
| 模块 | 工作量(人天) | 说明 |
|------|---------------|------|
| 文件上传与解析 | 3-5 天 | PDF、Word、音频解析 |
| 提示词升级 | 2-3 天 | 附加提示词、结构化输出 |
| 基础 TTS | 2-3 天 | 文字转语音 |
| 播客对话(可选) | 5-7 天 | LLM 脚本生成 + 多音色合成 |
| RAG 问答系统 | 5-7 天 | 向量化、检索、对话 |
| 前端交互升级 | 3-5 天 | 音频播放器、聊天界面 |
| **总计** | **20-30 天** | 约 1-1.5 个月 |
### 运营成本(月)
| 项目 | 预估用量 | 单价 | 月成本 |
|------|---------|------|--------|
| **阿里云 TTS** | 100 万字 | 0.02 元/千字 | 20 元 |
| **LLM 脚本生成** | 50 次5000 字/次) | 0.05 元/次 | 2.5 元 |
| **Embedding 向量化** | 100 万字 | 0.0007 元/千 tokens | 0.7 元 |
| **LLM 问答** | 1000 次 | 0.01 元/次 | 10 元 |
| **七牛云存储(音频)** | 10 GB | 0.148 元/GB/天 | 44 元 |
| **Qdrant 服务器** | 1 核 2G | - | 0 元(自建) |
| **总计** | - | - | **约 77 元/月** |
*注:基于中小规模使用场景(月活 100-500 用户)*
---
## 技术风险与缓解措施
### 风险 1向量数据库性能
- **风险**:大规模知识库检索延迟
- **缓解**
- 使用 Qdrant 的分片和副本
- 限制单次检索 Top-K 数量
- 增加缓存层Redis
### 风险 2播客生成质量
- **风险**LLM 生成的对话脚本不自然
- **缓解**
- 提供多个脚本模版供用户选择
- 支持用户编辑脚本后再合成
- 引入少样本学习Few-shot优化 prompt
### 风险 3文件解析准确性
- **风险**PDF、Word 解析失败或乱码
- **缓解**
- 提供预览功能,让用户确认提取结果
- 支持手动文本粘贴作为备选
- 增加 OCR 处理扫描件 PDF
### 风险 4成本控制
- **风险**TTS 和 LLM 调用费用超预算
- **缓解**
- 设置单用户每日调用限额
- 音频生成采用队列异步处理
- 提供缓存机制避免重复生成
---
## 实施建议
### Phase 2.1基础版2-3 周)
**优先级高**
1. 文件上传与解析PDF、Word、TXT
2. 基础 TTS 音频生成
3. 提示词附加功能
### Phase 2.2进阶版3-4 周)
🎯 **优先级中**
1. RAG 问答系统(向量检索)
2. 播客式对话生成
3. 前端聊天界面
### Phase 2.3优化版2-3 周)
🔧 **优先级低**
1. 音频后处理(背景音乐、片头片尾)
2. 多轮对话记忆
3. 相关问题推荐
---
## 总结
Phase 2 升级将把 iMeeting 知识库系统从"被动阅读"升级为"主动交互",核心亮点包括:
1. ✅ **多源输入**:会议 + 文件 + 音视频
2. 🎙️ **音频播客**:类 NotebookLM 的对话式音频
3. 💬 **智能问答**:基于 RAG 的精准问答
4. 📊 **结构化输出**:自动生成多级章节
**技术可行性**:高(基于成熟技术栈)
**成本可控性**:高(月运营成本 < 100
**开发周期**1-1.5 个月20-30 人天)
建议采用**分阶段迭代**方式,先上线基础版(文件上传 + 基础 TTS快速验证用户需求再逐步完善高级功能播客对话 + RAG 问答)。

1
backend 160000

@ -0,0 +1 @@
Subproject commit 61952852d72b8803072fa792eb61553c5986a01c

412
database.md 100644
View File

@ -0,0 +1,412 @@
# 数据库设计文档
本数据库采用 `MySQL 5.7+`
## 1. 表结构概览
- **users**: 用户信息表
- **roles**: 角色信息表
- **meetings**: 会议主表
- **attendees**: 参会人员关联表
- **tags**: 标签表
- **audio_files**: 会议音频文件表
- **attachments**: 会议附件表 (未来扩展)
- **transcript_tasks**: 语音转录任务表
- **transcript_segments**: 语音转录内容分段表
- **meeting_summaries**: AI 生成的会议纪要表(由llm_tasks替代)
- **llm_tasks**: AI总结任务表
- **prompts**: 提示词仓库表
- **knowledge_bases**: 知识库主表
- **knowledge_bases_task**: 知识库生成任务表
- **dict_data**: 字典/码表数据表
- **client_downloads**: 客户端下载管理表
---
## 2. 表结构详情
### 2.1. `users` - 用户表
存储用户信息和登录凭证。
| 字段名 | 类型 | 约束 | 描述 |
| :--- | :--- | :--- | :--- |
| `user_id` | INT | PRIMARY KEY, AUTO_INCREMENT | 用户唯一ID |
| `role_id` | INT | NOT NULL, FK | 角色ID (关联 `roles` 表) |
| `username` | VARCHAR(50) | UNIQUE, NOT NULL | 登录用户名 |
| `caption` | VARCHAR(50) | NOT NULL | 用户显示昵称 |
| `email` | VARCHAR(100) | UNIQUE, NOT NULL | 用户邮箱 |
| `password_hash` | VARCHAR(255) | NOT NULL | 哈希后的密码 |
| `created_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 账户创建时间 |
### 2.1.1 'user_voiceprint' - 用户声纹表
| 字段名 | 类型 | 说明 |
|--------|------|------|
| vp_id | INT | 主键自增ID |
| user_id | INT | 用户ID唯一索引 |
| file_path | VARCHAR(255) | 音频文件相对路径 |
| file_size | INT | 文件大小(字节) |
| duration_seconds | DECIMAL(5,2) | 音频时长(秒),如 10.25 |
| vector_data | TEXT | 声纹向量JSON数组如 [0.123, 0.456, ...] |
| collected_at | TIMESTAMP | 采集时间 |
| updated_at | TIMESTAMP | 更新时间 |
### 2.2. `roles` - 角色表
存储用户角色信息。
| 字段名 | 类型 | 约束 | 描述 |
| :--- | :--- | :--- | :--- |
| `role_id` | INT | PRIMARY KEY, AUTO_INCREMENT | 角色唯一ID |
| `role_name` | VARCHAR(50) | UNIQUE, NOT NULL | 角色名称 (e.g., "admin", "user") |
### 2.3. `meetings` - 会议表
存储会议的核心元数据。
| 字段名 | 类型 | 约束 | 描述 |
| :--- | :--- | :--- | :--- |
| `meeting_id` | INT | PRIMARY KEY, AUTO_INCREMENT | 会议唯一ID |
| `user_id` | INT | FK | 会议创建者ID (关联 `users` 表) |
| `title` | VARCHAR(255) | NOT NULL | 会议标题 |
| `meeting_time` | TIMESTAMP | NULL | 会议召开时间 |
| `user_prompt` | TEXT | NULL | 用户输入的提示词 (重复)|
| `summary` | TEXT | NULL | 会议摘要 (Markdown格式) |
| `tags` | VARCHAR(1024) | NULL | 以逗号分隔的标签字符串 |
| `created_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 记录创建时间 |
### 2.4. `attendees` - 参会人表
会议与用户的多对多关联表。
| 字段名 | 类型 | 约束 | 描述 |
| :--- | :--- | :--- | :--- |
| `attendee_id` | INT | PRIMARY KEY, AUTO_INCREMENT | 唯一ID |
| `meeting_id` | INT | FK | 会议ID (关联 `meetings` 表) |
| `user_id` | INT | FK | 用户ID (关联 `users` 表) |
| | | UNIQUE (`meeting_id`, `user_id`) | |
### 2.5. `tags` - 标签表
存储所有唯一的标签及其颜色,用于快速检索和维护。
| 字段名 | 类型 | 约束 | 描述 |
| :--- | :--- | :--- | :--- |
| `id` | INT | PRIMARY KEY, AUTO_INCREMENT | 标签唯一ID |
| `name` | VARCHAR(255) | UNIQUE, NOT NULL | 标签名称 |
| `color` | VARCHAR(7) | DEFAULT '#409EFF' | 标签颜色 (HEX) |
| `creator_id` INT NOT NULL, COMMENT '创建者用户ID (关联 `users` 表) ' |
| `created_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 创建时间 |
### 2.6. `audio_files` - 音频文件表
存储上传的会议音频文件信息。
| 字段名 | 类型 | 约束 | 描述 |
| :--- | :--- | :--- | :--- |
| `audio_id` | INT | PRIMARY KEY, AUTO_INCREMENT | 音频文件唯一ID |
| `meeting_id` | INT | FK | 关联的会议ID |
| `file_name` | VARCHAR(255) | | 原始文件名 |
| `file_path` | VARCHAR(512) | NOT NULL | 文件存储相对路径 |
| `file_size` | BIGINT | NULL | 文件大小 (bytes) |
| `upload_time` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 上传时间 |
### 2.7. `attachments` - 会议附件表
存储会议相关的其他附件如PPT、PDF等。
| 字段名 | 类型 | 约束 | 描述 |
| :--- | :--- | :--- | :--- |
| `attachment_id` | INT | PRIMARY KEY, AUTO_INCREMENT | 附件唯一ID |
| `meeting_id` | INT | FK | 关联的会议ID |
| `file_name` | VARCHAR(255) | NOT NULL | 原始文件名 |
| `file_path` | VARCHAR(512) | NOT NULL | 文件存储路径或URL |
| `file_type` | VARCHAR(100) | | 文件MIME类型 |
| `uploaded_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 上传时间 |
### 2.8. `transcript_tasks` - 转录任务表
记录语音转录任务的状态和元数据。
| 字段名 | 类型 | 约束 | 描述 |
| :--- | :--- | :--- | :--- |
| `task_id` | VARCHAR(100) | PRIMARY KEY | 业务任务唯一ID (UUID) |
| `paraformer_task_id`| VARCHAR(100) | NULL | 外部服务 (Dashscope) 的任务ID |
| `meeting_id` | INT | NOT NULL, FK | 关联的会议ID |
| `status` | ENUM(...) | DEFAULT 'pending' | 任务状态: 'pending', 'processing', 'completed', 'failed' |
| `progress` | INT | DEFAULT 0 | 任务进度百分比 (0-100) |
| `created_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 任务创建时间 |
| `completed_at` | TIMESTAMP | NULL | 任务完成时间 |
| `error_message` | TEXT | NULL | 错误信息记录 |
### 2.9. `transcript_segments` - 转录内容分段表
存储转录后的文字内容,按句子和发言人分段。
| 字段名 | 类型 | 约束 | 描述 |
| :--- | :--- | :--- | :--- |
| `segment_id` | INT | PRIMARY KEY, AUTO_INCREMENT | 分段唯一ID |
| `meeting_id` | INT | FK | 关联的会议ID |
| `speaker_id` | INT | | AI识别的原始发言人ID (e.g., 0, 1, 2) |
| `speaker_tag` | VARCHAR(50) | NOT NULL | 用户可编辑的发言人标签 (e.g., "张三") |
| `start_time_ms` | INT | NOT NULL | 在音频中的开始时间 (毫秒) |
| `end_time_ms` | INT | NOT NULL | 在音频中的结束时间 (毫秒) |
| `text_content` | TEXT | NOT NULL | 转录的文本内容 |
### 2.10. `meeting_summaries` - 会议纪要表(作废)
存储由LLM生成的会议纪要。
| 字段名 | 类型 | 约束 | 描述 |
| :--- | :--- | :--- | :--- |
| `id` | INT | PRIMARY KEY, AUTO_INCREMENT | 纪要唯一ID |
| `meeting_id` | INT | FK | 关联的会议ID |
| `summary_content` | TEXT | NULL | 生成的纪要内容 |
| `user_prompt` | TEXT | NULL | 用户输入的额外提示 |
| `prompt_id` | INT | FK | 关联的提示词模版ID |
| `created_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 生成时间 |
### 2.11. `llm_tasks` - AI总结任务表
记录异步生成AI总结的任务状态。
| 字段名 | 类型 | 约束 | 描述 |
| :--- | :--- | :--- | :--- |
| `task_id` | VARCHAR(100) | PRIMARY KEY | 业务任务唯一ID (UUID) |
| `meeting_id` | INT | NOT NULL, FK | 关联的会议ID |
| `prompt_id` | INT | NOT NULL, FK | 关联的提示词模版ID |
| `user_prompt` | TEXT | NULL | 用户输入的额外提示 |
| `status` | ENUM(...) | DEFAULT 'pending' | 任务状态: 'pending', 'processing', 'completed', 'failed' |
| `progress` | INT | DEFAULT 0 | 任务进度百分比 (0-100) |
| `result` | TEXT | NULL | 成功时存储生成的纪要内容 |
| `created_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 任务创建时间 |
| `completed_at` | TIMESTAMP | NULL | 任务完成时间 |
| `error_message` | TEXT | NULL | 错误信息记录 |
### 2.13. `knowledge_bases` - 知识库表
存储用户生成和管理的知识库条目。
| 字段名 | 类型 | 约束 | 描述 |
| :--- | :--- | :--- | :--- |
| `kb_id` | INT | PRIMARY KEY, AUTO_INCREMENT | 知识库条目唯一ID |
| `title` | VARCHAR(255) | NOT NULL | 标题 |
| `user_prompt` | TEXT | NULL | 用户输入的提示词(重复) |
| `content` | TEXT | NULL | 生成的知识库内容 (Markdown格式) |
| `creator_id` | INT | NOT NULL, FK | 创建者用户ID (关联 `users` 表) |
| `is_shared` | BOOLEAN | NOT NULL, DEFAULT FALSE | 是否为共享知识库 (TRUE: 共享, FALSE: 个人) |
| `source_meeting_ids` | TEXT | NULL | 内容来源的会议ID列表 (逗号分隔) |
| `tags` | VARCHAR(255) | NULL | 逗号分隔的标签 |
| `created_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 创建时间 |
| `updated_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 最后更新时间 |
### 2.14. `knowledge_base_tasks` - 知识库生成任务表
记录异步生成知识库内容的AI任务状态。
| 字段名 | 类型 | 约束 | 描述 |
| :--- | :--- | :--- | :--- |
| `task_id` | VARCHAR(100) | PRIMARY KEY | 业务任务唯一ID (UUID) |
| `user_id` | INT | NOT NULL, FK | 发起任务的用户ID (关联 `users` 表) |
| `kb_id` | INT | NOT NULL, FK | 关联的知识库条目ID (关联 `knowledge_bases` 表) |
| `prompt_id` | INT | NOT NULL, FK | 关联的提示词模版ID |
| `user_prompt` | TEXT | NULL | 用户输入的提示词 |
| `status` | ENUM('pending', 'processing', 'completed', 'failed') | NOT NULL, DEFAULT 'pending' | 任务状态 |
| `progress` | INT | DEFAULT 0 | 任务进度百分比 (0-100) |
| `error_message` | TEXT | NULL | 任务失败时的错误信息 |
| `created_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 任务创建时间 |
| `updated_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 任务状态更新时间 |
| `completed_at` | TIMESTAMP | NULL | 任务完成时间 |
### 2.12. `prompts` - 提示词仓库表
存储系统中各种任务使用的大模型提示词模板。每个任务类型(会议任务、知识库任务)可以有多个提示词,但只能有一个默认且启用的提示词。
| 字段名 | 类型 | 约束 | 描述 |
| :--- | :--- | :--- | :--- |
| `id` | INT | AUTO_INCREMENT, PRIMARY KEY | 提示词唯一ID |
| `name` | VARCHAR(255) | NOT NULL | 提示词名称 |
| `task_type` | ENUM('MEETING_TASK', 'KNOWLEDGE_TASK') | NOT NULL | 任务类型MEETING_TASK-会议任务, KNOWLEDGE_TASK-知识库任务 |
| `content` | TEXT | NOT NULL | 完整的提示词内容 |
| `is_default` | BOOLEAN | NOT NULL, DEFAULT FALSE | 是否为该任务类型的默认模板 |
| `is_active` | BOOLEAN | NOT NULL, DEFAULT TRUE | 是否启用(只有启用的提示词才能被使用) |
| `creator_id` | INT | NOT NULL, FK | 创建者用户ID (关联 `users` 表) |
| `created_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 创建时间 |
**约束说明:**
- 每个 `task_type` 同一时间只能有一个 `is_default=TRUE` 的提示词
- 业务逻辑需确保:设置新默认提示词时,自动取消同类型其他提示词的默认状态
### 2.15. `prompt_config` - 提示词配置表(已废弃)
**该表已废弃,功能整合到 `prompts` 表的 `task_type``is_default` 字段。**
### 2.16. `dict_data` - 字典/码表数据表
存储系统中的码表数据,支持树形结构和扩展属性,用于管理客户端平台类型等配置数据。
| 字段名 | 类型 | 约束 | 描述 |
| :--- | :--- | :--- | :--- |
| `id` | BIGINT | PRIMARY KEY, AUTO_INCREMENT | 主键ID |
| `dict_type` | VARCHAR(64) | NOT NULL, DEFAULT 'client_platform' | 字典类型(如 client_platform |
| `dict_code` | VARCHAR(64) | NOT NULL | 业务编码唯一Key如 WIN、IOS、ANDROID |
| `parent_code` | VARCHAR(64) | NOT NULL, DEFAULT 'ROOT' | 父级编码ROOT为顶级支持树形结构 |
| `tree_path` | VARCHAR(255) | NULL | 层级路径(辅助字段,如 0,1,10 |
| `label_cn` | VARCHAR(128) | NOT NULL | 中文名称 |
| `label_en` | VARCHAR(128) | NULL | 英文名称 |
| `sort_order` | INT | DEFAULT 0 | 排序权重 |
| `extension_attr` | JSON | NULL | 扩展属性JSON格式存储平台特有属性 |
| `is_default` | TINYINT | DEFAULT 0 | 是否默认选中0: 否, 1: 是) |
| `status` | TINYINT | DEFAULT 1 | 状态1: 正常, 0: 停用) |
| `create_time` | DATETIME | DEFAULT CURRENT_TIMESTAMP | 创建时间 |
| | | UNIQUE KEY (`dict_type`, `dict_code`) | 确保编码在同类型下唯一 |
**扩展属性示例extension_attr**
```json
{
"suffix": ".exe",
"arch_support": ["x86", "x64"],
"icon": "monitor"
}
```
**树形结构示例:**
- ROOT
- DESKTOP (桌面端)
- WIN (Windows)
- MAC (macOS)
- LINUX (Linux)
- MOBILE (移动端)
- IOS (苹果iOS)
- ANDROID (安卓)
- TERMINAL (专用终端)
- TERM_STD (通用终端)
- TERM_S100 (中兴终端)
### 2.17. `client_downloads` - 客户端下载管理表
存储各平台客户端版本信息,用于管理客户端下载和版本更新。
| 字段名 | 类型 | 约束 | 描述 |
| :--- | :--- | :--- | :--- |
| `id` | INT | PRIMARY KEY, AUTO_INCREMENT | 主键ID |
| `platform_code` | VARCHAR(64) | NOT NULL | 平台编码(关联 `dict_data.dict_code` |
| `version` | VARCHAR(50) | NOT NULL | 版本号(如 1.0.0 |
| `version_code` | INT | NOT NULL | 版本号数值(用于版本比较) |
| `download_url` | VARCHAR(512) | NOT NULL | 下载链接 |
| `file_size` | BIGINT | NULL | 文件大小bytes |
| `release_notes` | TEXT | NULL | 更新说明 |
| `is_active` | BOOLEAN | NOT NULL, DEFAULT TRUE | 是否启用 |
| `is_latest` | BOOLEAN | NOT NULL, DEFAULT FALSE | 是否为最新版本 |
| `min_system_version` | VARCHAR(50) | NULL | 最低系统版本要求 |
| `created_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 创建时间 |
| `updated_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 更新时间 |
| `created_by` | INT | NULL, FK | 创建者用户ID关联 `users` 表) |
| | | INDEX (`platform_code`) | 平台编码索引 |
**约束说明:**
- 同一 `platform_code` 同一时间只应有一个 `is_latest=TRUE` 的版本
- `platform_code` 关联 `dict_data` 表的 `dict_code` 字段client_platform类型
- 业务逻辑需确保:设置新最新版本时,自动取消同平台其他版本的最新状态
**相关API接口**
- `GET /api/clients/latest/by-platform` - 获取最新版本客户端
- 支持两种调用方式(兼容新旧版本,返回数据结构一致):
1. 旧版:传 `platform_type``platform_name` 参数
2. 新版:传 `platform_code` 参数(推荐)
- `POST /api/clients/upload` - 上传客户端安装包(管理员)
- 自动解析APK文件的版本信息
- 自动读取文件大小并生成下载URL
---
## 3. 关系图 (ERD)
```mermaid
erDiagram
users {
int user_id PK
varchar(50) username
varchar(50) caption
varchar(100) email
varchar(255) password_hash
int role_id FK
timestamp created_at
}
roles {
int role_id PK
varchar(50) role_name
}
meetings {
int meeting_id PK
int user_id FK
varchar(255) title
timestamp meeting_time
text summary
varchar(1024) tags
timestamp created_at
}
tags {
int id PK
varchar(255) name
varchar(7) color
}
attendees {
int attendee_id PK
int meeting_id FK
int user_id FK
}
audio_files {
int audio_id PK
int meeting_id FK
varchar(512) file_path
varchar(100) task_id
}
transcript_tasks {
varchar(100) task_id PK
int meeting_id FK
varchar(100) paraformer_task_id
enum status
int progress
}
transcript_segments {
int segment_id PK
int meeting_id FK
int speaker_id
varchar(50) speaker_tag
int start_time_ms
int end_time_ms
text text_content
}
meeting_summaries {
int id PK
int meeting_id FK
text summary_content
}
llm_tasks {
varchar(100) task_id PK
int meeting_id FK
enum status
int progress
}
users ||--o{ meetings : "creates"
users ||--o{ attendees : "attends"
users }|..|| roles : "has role"
meetings ||--|{ attendees : "has"
meetings ||--|{ audio_files : "has"
meetings ||--|{ transcript_tasks : "has"
meetings ||--|{ transcript_segments : "has"
meetings ||--|{ meeting_summaries : "has"
meetings ||--|{ llm_tasks : "has"
```

5
deploy.md 100644
View File

@ -0,0 +1,5 @@
# 环境
# 组件
+ 数据库 mysql 5.7+ 10.100.51.51:3306 root | Unis@123
+ 缓存 redis 6.2 10.100.51.51:6379 Unis@123

130
docker-compose.yml 100644
View File

@ -0,0 +1,130 @@
version: '3.8'
services:
# MySQL数据库
mysql:
image: mysql:8.0
container_name: imeeting-mysql
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-Unis@123}
MYSQL_DATABASE: ${MYSQL_DATABASE:-imeeting}
MYSQL_USER: ${MYSQL_USER:-imeeting}
MYSQL_PASSWORD: ${MYSQL_PASSWORD:-Unis@123}
TZ: Asia/Shanghai
# 仅在需要外部访问数据库时暴露端口
ports:
- "${MYSQL_PORT:-3306}:3306"
volumes:
- ./data/mysql:/var/lib/mysql
- ./backend/sql:/docker-entrypoint-initdb.d:ro
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
- --default-authentication-plugin=mysql_native_password
- --max_connections=1000
- --max_allowed_packet=256M
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD:-Unis@123}"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
networks:
- imeeting-network
# Redis缓存
redis:
image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/redis:7-alpineredis:7-alpine
container_name: imeeting-redis
restart: unless-stopped
environment:
TZ: Asia/Shanghai
# 仅在需要外部访问Redis时暴露端口
ports:
- "${REDIS_PORT:-6379}:6379"
volumes:
- ./data/redis:/data
command: >
redis-server
--appendonly yes
--requirepass ${REDIS_PASSWORD:-Unis@123}
--maxmemory 2gb
--maxmemory-policy allkeys-lru
healthcheck:
test: ["CMD", "redis-cli", "--raw", "incr", "ping"]
interval: 10s
timeout: 3s
retries: 5
start_period: 10s
networks:
- imeeting-network
# 后端服务
backend:
build:
context: ./backend
dockerfile: Dockerfile
container_name: imeeting-backend
restart: unless-stopped
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
env_file:
- ./backend/.env
environment:
# Python环境
TZ: Asia/Shanghai
PYTHONPATH: /app
PYTHONUNBUFFERED: 1
# 强制使用容器内部服务名,覆盖本地.env配置
DB_HOST: mysql
REDIS_HOST: redis
API_PORT: 8000
# 后端不直接暴露端口通过nginx代理访问
# ports:
# - "${BACKEND_PORT:-8000}:8000"
volumes:
- ./data/uploads:/app/uploads
- ./data/logs/backend:/app/logs
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
- imeeting-network
# 前端服务
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
container_name: imeeting-frontend
restart: unless-stopped
depends_on:
backend:
condition: service_healthy
environment:
TZ: Asia/Shanghai
# 前端不直接暴露端口通过nginx代理访问
# ports:
# - "${FRONTEND_PORT:-3001}:80"
volumes:
- ./data/logs/frontend:/var/log/nginx
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:80/"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
- imeeting-network
# 网络配置
networks:
imeeting-network:
driver: bridge

View File

@ -0,0 +1,292 @@
# 客户端下载管理模块
## 概述
本模块实现了一个完整的客户端下载管理系统,支持移动端(iOS/Android)和桌面端(Windows/Mac/Linux)的版本管理和下载。
## 功能特性
### 1. 管理员功能
- ✅ 创建/编辑/删除客户端版本
- ✅ 管理版本号和版本代码
- ✅ 设置最新版本标记
- ✅ 启用/禁用特定版本
- ✅ 添加更新说明和系统要求
- ✅ 平台分类管理(移动端/桌面端)
- ✅ 搜索和过滤功能
### 2. 用户功能
- ✅ 查看所有平台的最新客户端
- ✅ 按平台分类展示
- ✅ 显示版本信息和文件大小
- ✅ 一键下载
### 3. API功能
- ✅ 获取所有客户端列表(支持分页和过滤)
- ✅ 获取最新版本客户端
- ✅ 按平台获取最新版本(用于客户端版本检查)
- ✅ CRUD操作(仅管理员)
## 数据库设计
### 表结构: `client_downloads`
```sql
CREATE TABLE client_downloads (
id INT AUTO_INCREMENT PRIMARY KEY,
platform_type ENUM('mobile', 'desktop') NOT NULL,
platform_name VARCHAR(50) NOT NULL,
version VARCHAR(50) NOT NULL,
version_code INT NOT NULL DEFAULT 1,
download_url TEXT NOT NULL,
file_size BIGINT,
release_notes TEXT,
is_active BOOLEAN DEFAULT TRUE,
is_latest BOOLEAN DEFAULT FALSE,
min_system_version VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
created_by INT,
FOREIGN KEY (created_by) REFERENCES users(user_id) ON DELETE SET NULL,
INDEX idx_platform (platform_type, platform_name),
INDEX idx_version (version_code),
INDEX idx_active (is_active, is_latest)
);
```
### 字段说明
- `platform_type`: 平台类型(mobile/desktop)
- `platform_name`: 具体平台(ios/android/windows/mac_intel/mac_m/linux)
- `version`: 版本号字符串(如: 1.0.0)
- `version_code`: 版本代码数字(用于版本比较,如: 1000)
- `download_url`: 下载链接
- `file_size`: 文件大小(字节)
- `release_notes`: 更新说明
- `is_active`: 是否启用
- `is_latest`: 是否为最新版本
- `min_system_version`: 最低系统版本要求
## API接口
### 公开接口(无需认证)
#### 1. 获取客户端列表
```
GET /api/clients/downloads
Query参数:
- platform_type: mobile|desktop (可选)
- platform_name: ios|android|windows|mac_intel|mac_m|linux (可选)
- is_active: true|false (可选)
- page: 页码 (默认1)
- size: 每页数量 (默认50)
```
#### 2. 获取所有最新版本
```
GET /api/clients/downloads/latest
返回: { mobile: [...], desktop: [...] }
```
#### 3. 获取指定平台最新版本
```
GET /api/clients/downloads/{platform_name}/latest
示例: GET /api/clients/downloads/ios/latest
```
#### 4. 获取指定ID的客户端
```
GET /api/clients/downloads/{id}
```
### 管理员接口(需要管理员权限)
#### 5. 创建客户端版本
```
POST /api/clients/downloads
Body: {
"platform_type": "mobile",
"platform_name": "ios",
"version": "1.0.0",
"version_code": 1000,
"download_url": "https://...",
"file_size": 52428800,
"release_notes": "初始版本...",
"is_active": true,
"is_latest": false,
"min_system_version": "iOS 13.0"
}
```
#### 6. 更新客户端版本
```
PUT /api/clients/downloads/{id}
Body: {
"version": "1.0.1",
"version_code": 1001,
"is_latest": true,
...
}
```
#### 7. 删除客户端版本
```
DELETE /api/clients/downloads/{id}
```
## 前端组件
### 1. ClientManagement (管理员页面)
位置: `frontend/src/pages/ClientManagement.jsx`
功能:
- 客户端版本CRUD操作
- 平台筛选和搜索
- 版本状态管理
- 响应式卡片布局
### 2. ClientDownloads (用户下载组件)
位置: `frontend/src/components/ClientDownloads.jsx`
功能:
- 展示最新客户端版本
- 按平台分类
- 一键下载
- 可嵌入任何页面
## 安装和部署
### 1. 数据库初始化
```bash
# 执行SQL文件
mysql -u your_user -p your_database < backend/sql/client_downloads.sql
```
### 2. 后端启动
后端会自动加载新的路由,无需额外配置。
### 3. 前端使用
#### 在管理员页面添加客户端管理:
```jsx
import ClientManagement from './pages/ClientManagement';
// 在管理员路由中添加
<Route path="/admin/clients" element={<ClientManagement user={user} />} />
```
#### 在首页添加下载组件:
```jsx
import ClientDownloads from './components/ClientDownloads';
// 在Dashboard或任何页面中添加
<ClientDownloads />
```
## 使用示例
### 管理员创建新版本
1. 访问管理后台的"客户端管理"页面
2. 点击"新增客户端"按钮
3. 填写版本信息:
- 选择平台类型和具体平台
- 输入版本号和版本代码
- 填写下载链接
- 添加更新说明
- 勾选"设为最新版本"(如果是最新)
4. 点击"创建"保存
### 用户下载客户端
1. 在首页查看"下载客户端"区域
2. 选择对应平台
3. 点击卡片即可下载
### 客户端版本检查
客户端可以调用API检查是否有新版本:
```javascript
// 检查iOS最新版本
const response = await fetch('/api/clients/downloads/ios/latest');
const latest = await response.json();
if (latest.data.version_code > currentVersionCode) {
// 提示用户更新
showUpdateDialog(latest.data);
}
```
## 版本号规范
- **版本号**: 采用语义化版本(Semantic Versioning),格式: `主版本.次版本.修订号`
- 例如: 1.0.0, 1.2.3, 2.0.0
- **版本代码**: 纯数字,用于程序化比较
- 推荐格式: 主版本(2位) + 次版本(2位) + 修订号(2位)
- 例如: 1.0.0 -> 10000, 1.2.3 -> 10203, 2.0.0 -> 20000
## 平台支持
### 移动端
- **iOS**: App Store链接或企业分发链接
- **Android**: Google Play链接或APK直接下载
### 桌面端
- **Windows**: .exe安装包
- **Mac (Intel)**: Intel架构的.dmg安装包
- **Mac (M系列)**: Apple Silicon原生支持的.dmg安装包
- **Linux**: .AppImage或.deb/.rpm包
## 注意事项
1. **下载链接**: 确保下载链接长期有效,建议使用CDN或对象存储
2. **文件大小**: 建议填写准确的文件大小,方便用户了解下载时间
3. **版本管理**:
- 同一平台只能有一个"最新版本"
- 设置新版本为最新时,会自动将旧版本的最新标记<E6A087><E8AEB0>
4. **权限控制**: CRUD操作仅管理员可执行,查询接口公开访问
## 扩展建议
1. **统计功能**: 添加下载次数统计
2. **发布计划**: 支持定时发布新版本
3. **灰度发布**: 按百分比或用户组逐步推送新版本
4. **更新检查**: 提供SDK方便客户端集成版本检查
5. **更新强制**: 支持强制更新标记
## 文件清单
### 后端
- `backend/sql/client_downloads.sql` - 数据库表结构和初始数据
- `backend/app/models/models.py` - Pydantic数据模型
- `backend/app/api/endpoints/client_downloads.py` - API路由和业务逻辑
- `backend/main.py` - 路由注册
### 前端
- `frontend/src/pages/ClientManagement.jsx` - 管理员管理页面
- `frontend/src/pages/ClientManagement.css` - 管理页面样式
- `frontend/src/components/ClientDownloads.jsx` - 用户下载组件
- `frontend/src/components/ClientDownloads.css` - 下载组件样式
- `frontend/src/config/api.js` - API配置
## 技术栈
### 后端
- FastAPI
- MySQL
- Pydantic
### 前端
- React
- Lucide React Icons
- CSS3
## 作者
Generated with Claude Code

1
frontend 160000

@ -0,0 +1 @@
Subproject commit 6cbe02fbf637e8cd3004c7947be5706a8cb814d7

303
manage.sh 100755
View File

@ -0,0 +1,303 @@
#!/bin/bash
# iMeeting Docker 管理脚本
# 用于日常管理和维护
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
print_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 确定使用的命令
if docker compose version &> /dev/null; then
COMPOSE_CMD="docker compose"
else
COMPOSE_CMD="docker-compose"
fi
# 显示菜单
show_menu() {
echo ""
echo -e "${BLUE}==================================${NC}"
echo -e "${BLUE} iMeeting 管理菜单${NC}"
echo -e "${BLUE}==================================${NC}"
echo ""
echo "1) 查看服务状态"
echo "2) 查看实时日志"
echo "3) 重启所有服务"
echo "4) 重启单个服务"
echo "5) 进入容器终端"
echo "6) 备份数据库"
echo "7) 恢复数据库"
echo "8) 清理Redis缓存"
echo "9) 更新服务"
echo "10) 查看资源使用"
echo "11) 导出日志"
echo "0) 退出"
echo ""
read -p "请选择操作 (0-11): " choice
}
# 查看服务状态
view_status() {
print_info "服务状态:"
$COMPOSE_CMD ps
echo ""
read -p "按任意键返回菜单..." -n 1
}
# 查看实时日志
view_logs() {
echo "选择要查看的服务:"
echo "1) 所有服务"
echo "2) Nginx"
echo "3) 前端"
echo "4) 后端"
echo "5) MySQL"
echo "6) Redis"
read -p "请选择: " log_choice
case $log_choice in
1) $COMPOSE_CMD logs -f ;;
2) $COMPOSE_CMD logs -f nginx ;;
3) $COMPOSE_CMD logs -f frontend ;;
4) $COMPOSE_CMD logs -f backend ;;
5) $COMPOSE_CMD logs -f mysql ;;
6) $COMPOSE_CMD logs -f redis ;;
*) print_error "无效选择" ;;
esac
}
# 重启服务
restart_services() {
print_info "重启所有服务..."
$COMPOSE_CMD restart
print_success "服务已重启"
read -p "按任意键返回菜单..." -n 1
}
# 重启单个服务
restart_single_service() {
echo "选择要重启的服务:"
echo "1) Nginx"
echo "2) 前端"
echo "3) 后端"
echo "4) MySQL"
echo "5) Redis"
read -p "请选择: " service_choice
case $service_choice in
1) $COMPOSE_CMD restart nginx ;;
2) $COMPOSE_CMD restart frontend ;;
3) $COMPOSE_CMD restart backend ;;
4) $COMPOSE_CMD restart mysql ;;
5) $COMPOSE_CMD restart redis ;;
*) print_error "无效选择"; return ;;
esac
print_success "服务已重启"
read -p "按任意键返回菜单..." -n 1
}
# 进入容器
enter_container() {
echo "选择要进入的容器:"
echo "1) Nginx"
echo "2) 前端"
echo "3) 后端"
echo "4) MySQL"
echo "5) Redis"
read -p "请选择: " container_choice
case $container_choice in
1) $COMPOSE_CMD exec nginx sh ;;
2) $COMPOSE_CMD exec frontend sh ;;
3) $COMPOSE_CMD exec backend bash ;;
4) $COMPOSE_CMD exec mysql bash ;;
5) $COMPOSE_CMD exec redis sh ;;
*) print_error "无效选择" ;;
esac
}
# 备份数据库
backup_database() {
print_info "开始备份数据库..."
mkdir -p backups
backup_file="backups/imeeting_$(date +%Y%m%d_%H%M%S).sql"
source .env 2>/dev/null || true
MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-Unis@123}
$COMPOSE_CMD exec mysql mysqldump -uroot -p"${MYSQL_ROOT_PASSWORD}" \
--single-transaction \
--routines \
--triggers \
imeeting > "$backup_file"
print_success "数据库已备份到: $backup_file"
read -p "按任意键返回菜单..." -n 1
}
# 恢复数据库
restore_database() {
print_warning "警告: 这将覆盖当前数据库!"
if [ ! -d "backups" ] || [ -z "$(ls -A backups/*.sql 2>/dev/null)" ]; then
print_error "未找到备份文件"
read -p "按任意键返回菜单..." -n 1
return
fi
echo ""
echo "可用的备份文件:"
ls -lh backups/*.sql
echo ""
read -p "请输入备份文件名: " backup_file
if [ ! -f "$backup_file" ]; then
print_error "文件不存在: $backup_file"
read -p "按任意键返回菜单..." -n 1
return
fi
read -p "确认恢复? (yes/no): " confirm
if [ "$confirm" = "yes" ]; then
print_info "开始恢复数据库..."
source .env 2>/dev/null || true
MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-Unis@123}
$COMPOSE_CMD exec -T mysql mysql -uroot -p"${MYSQL_ROOT_PASSWORD}" imeeting < "$backup_file"
print_success "数据库已恢复"
else
print_info "操作已取消"
fi
read -p "按任意键返回菜单..." -n 1
}
# 清理Redis缓存
clear_redis() {
print_warning "这将清空所有Redis缓存"
read -p "确认清空? (yes/no): " confirm
if [ "$confirm" = "yes" ]; then
source .env 2>/dev/null || true
REDIS_PASSWORD=${REDIS_PASSWORD:-Unis@123}
$COMPOSE_CMD exec redis redis-cli -a "${REDIS_PASSWORD}" FLUSHALL
print_success "Redis缓存已清空"
else
print_info "操作已取消"
fi
read -p "按任意键返回菜单..." -n 1
}
# 更新服务
update_services() {
echo "选择更新方式:"
echo "1) 更新所有服务"
echo "2) 仅更新前端"
echo "3) 仅更新后端"
read -p "请选择: " update_choice
case $update_choice in
1)
print_info "更新所有服务..."
$COMPOSE_CMD build
$COMPOSE_CMD up -d
;;
2)
print_info "更新前端..."
$COMPOSE_CMD build frontend
$COMPOSE_CMD up -d frontend
;;
3)
print_info "更新后端..."
$COMPOSE_CMD build backend
$COMPOSE_CMD up -d backend
;;
*)
print_error "无效选择"
;;
esac
print_success "更新完成"
read -p "按任意键返回菜单..." -n 1
}
# 查看资源使用
view_resources() {
print_info "容器资源使用情况:"
docker stats --no-stream $(docker ps --format "{{.Names}}" | grep imeeting)
echo ""
read -p "按任意键返回菜单..." -n 1
}
# 导出日志
export_logs() {
print_info "导出日志..."
mkdir -p logs_export
timestamp=$(date +%Y%m%d_%H%M%S)
$COMPOSE_CMD logs --no-color > "logs_export/all_services_${timestamp}.log"
$COMPOSE_CMD logs --no-color nginx > "logs_export/nginx_${timestamp}.log"
$COMPOSE_CMD logs --no-color frontend > "logs_export/frontend_${timestamp}.log"
$COMPOSE_CMD logs --no-color backend > "logs_export/backend_${timestamp}.log"
$COMPOSE_CMD logs --no-color mysql > "logs_export/mysql_${timestamp}.log"
$COMPOSE_CMD logs --no-color redis > "logs_export/redis_${timestamp}.log"
print_success "日志已导出到: logs_export/"
read -p "按任意键返回菜单..." -n 1
}
# 主循环
main() {
while true; do
clear
show_menu
case $choice in
1) view_status ;;
2) view_logs ;;
3) restart_services ;;
4) restart_single_service ;;
5) enter_container ;;
6) backup_database ;;
7) restore_database ;;
8) clear_redis ;;
9) update_services ;;
10) view_resources ;;
11) export_logs ;;
0) print_info "退出管理脚本"; exit 0 ;;
*) print_error "无效选择"; sleep 1 ;;
esac
done
}
# 运行主程序
main

6
package-lock.json generated 100644
View File

@ -0,0 +1,6 @@
{
"name": "imeeting",
"lockfileVersion": 3,
"requires": true,
"packages": {}
}

1
package.json 100644
View File

@ -0,0 +1 @@
{}

218
project.md 100644
View File

@ -0,0 +1,218 @@
# 项目设计文档iMeeting (智慧会议)
## 1. 项目概述
**项目名称**: iMeeting (智慧会议)
**目标**: 为需要参加大量会议的专业人士、团队管理者和企业员工提供一个高效、智能的会议记录与内容管理平台。通过AI技术将非结构化的会议音视频内容转化为易于检索、回顾和分发的结构化信息从而节省用户整理会议纪要的时间提升信息流转效率。
**核心价值**:
- **解放生产力**: 自动化的会议转录和摘要,让用户从繁琐的记录工作中解放出来。
- **信息不丢失**: 精准记录每一次会议的细节,确保关键信息和决策得到妥善保存。
- **高效回顾**: 通过时间轴、发言人和关键词,快速定位会议内容。
- **便捷分享**: 轻松分享会议纪要、材料和关键节点给相关人员。
## 2. 核心功能
- **会议管理**: 创建、编辑、删除会议,管理参会人员。
- **音频上传与处理**: 上传会议音频,触发后台异步任务进行语音转文字和说话人分离。
- **智能转录内容**: 提供带时间轴、可编辑、可播放的会议文稿。
- **发言人管理**: 自动识别发言人并支持用户自定义标签。
- **AI会议纪要**: 异步生成会议摘要,支持用户自定义提示词,并可多次生成。
- **用户与权限管理**: 支持管理员对用户进行增删改查和密码重置。
## 3. 技术栈
- **后端**: Python 3.9+, FastAPI
- **数据库**: MySQL 5.7+
- **缓存与任务队列**: Redis
- **AI服务**: 阿里云通义千问 (语音识别、LLM)
- **前端**: React (Vite) + Ant Design
- **部署**: Docker, Nginx
## 4. 异步任务设计
项目包含两大核心异步任务:**语音转录**和**AI总结**均通过后台任务实现以避免长时间阻塞API请求。
### 4.1. 语音转录 (Async Transcription)
- **触发**: 用户上传音频文件 (`POST /meetings/upload-audio`) 成功后自动触发。
- **实现**: `AsyncTranscriptionService` 调用阿里云 `Dashscope``paraformer-v2` 模型进行异步语音识别。
1. **启动任务**: 调用 `Transcription.async_call`获取一个外部任务ID (`paraformer_task_id`)。
2. **创建内部任务**: 生成一个系统内部的业务ID (`business_task_id`)并将两个ID的映射关系及任务元数据存入 `transcript_tasks` 表和Redis缓存。
3. **状态查询**: 前端通过 `GET /transcription/tasks/{task_id}/status``GET /meetings/{meeting_id}/transcription/status` 轮询任务状态。
4. **获取结果**: 服务端在查询状态时,若发现外部任务已完成,则通过 `Transcription.fetch` 获取结果URL下载JSON格式的转录数据。
5. **数据入库**: 解析JSON数据将包含发言人ID、时间戳和文本的 `transcript_segments` 存入数据库。
- **关键代码**: `backend/app/services/async_transcription_service.py`
### 4.2. AI总结 (Async LLM Summary)
- **触发**: 用户在会议详情页点击“生成纪要” (`POST /meetings/{meeting_id}/generate-summary-async`)。
- **实现**: `AsyncLLMService` 利用 FastAPI 的 `BackgroundTasks` 实现轻量级异步处理。
1. **创建任务**: 生成一个任务ID (`task_id`)并将任务元数据会议ID、用户提示词等存入 `llm_tasks` 表和Redis缓存立即返回任务ID给前端。
2. **后台执行**: `_process_task` 函数在后台运行它按顺序执行获取转录稿、构建Prompt、调用LLM API、保存结果。
3. **状态与进度更新**: 在执行的每个关键步骤都会更新Redis中的任务状态和进度百分比 (`processing`, `10%`, `30%` ...)。
4. **状态查询**: 前端通过 `GET /llm-tasks/{task_id}/status` 轮询任务状态和进度。
5. **结果获取**: 任务完成后,状态变为 `completed`,结果会保存在 `llm_tasks` 表的 `result` 字段,并可通过状态查询接口获取。
- **关键代码**: `backend/app/services/async_llm_service.py`
### 4.3. 声纹采集
## 前端UI要素
### Dashboard 声纹状态显示
- **未采集**:显示"采集声纹"按钮(醒目样式,如橙色或主题色)
- **已采集**显示波纹图标可使用音频波形SVG或动画效果
### 声纹采集对话框
- 标题:"声纹采集"
- 朗读文本显示区域(滚动文本)
- 录制按钮:"开始录制" / "正在录制..."
- 进度显示:
- 圆形进度环(推荐)
- 或倒计时文字:"10s" → "9s" → ... → "0s"
- 提示信息:"请在安静环境下,用自然语速朗读上述文字"
- 操作按钮:"取消" / "重新录制"
### 音频波形图标示例
可以使用类似这样的SVG图标
```html
<svg viewBox="0 0 24 24" class="voice-wave-icon">
<path d="M12 2v20M8 6v12M16 6v12M4 9v6M20 9v6" />
</svg>
```
## 文件存储结构
```
uploads/
└── voiceprint/
└── {user_id}/
└── timestamp.wav # 采集时间为文件名。
```
**存储说明:**
- 每个用户只保留一个声纹文件
- 用户目录在首次采集时创建
## 声纹朗读模板配置
朗读模板配置在 `config/system_config.json` 中:
```json
{
"voiceprint": {
"template_text": "我正在进行声纹采集,这段语音将用于身份识别和验证。声纹技术能够准确识别每个人独特的声音特征,就像指纹一样独一无二。请保持自然的语速和音量进行朗读。",
"duration_seconds": 10,
"sample_rate": 16000,
"channels": 1
}
}
```
**配置说明:**
- `template_text`: 用户朗读的标准文本
- `duration_seconds`: 建议录制时长(秒)
- `sample_rate`: 音频采样率Hz
- `channels`: 声道数1=单声道)
## 5. API 接口文档
### 5.1. 认证接口 (`/auth`)
- `POST /auth/login`: 用户登录。
- **Request**: `LoginRequest` (username, password)
- **Response**: `LoginResponse` (user_info, token)
- `POST /auth/logout`: 用户登出使当前Token失效。
- `POST /auth/logout-all`: 登出该用户的所有设备。
- `GET /auth/me`: 获取当前登录用户的信息。
- `POST /auth/refresh`: 刷新当前用户的Token。
### 5.2. 用户管理接口 (`/users`)
> **权限**: 以下接口均需要管理员权限 (role_id=1)。
- `GET /roles`: 获取所有角色列表。
- `POST /users`: 创建新用户。
- **Request**: `CreateUserRequest`
- `GET /users`: 分页获取用户列表。
- `GET /users/{user_id}`: 获取指定用户的详细信息。
- `PUT /users/{user_id}`: 更新用户信息。
- **Request**: `UpdateUserRequest`
- `DELETE /users/{user_id}`: 删除用户。
- `POST /users/{user_id}/reset-password`: 重置用户密码为默认值。
- `PUT /users/{user_id}/password`: 修改用户密码 (管理员无需旧密码)。
### 5.3. 会议与转录接口 (`/meetings`)
- `GET /meetings`: 获取会议列表,可通过 `user_id` 过滤。
- `POST /meetings`: 创建新会议。
- **Request**: `CreateMeetingRequest`
- `GET /meetings/{meeting_id}`: 获取单个会议的详细信息,包含转录状态。
- `PUT /meetings/{meeting_id}`: 更新会议信息(标题、时间、参会人等)。
- `DELETE /meetings/{meeting_id}`: 删除会议及所有相关数据。
- `GET /meetings/{meeting_id}/edit`: 获取用于编辑页面的会议信息。
#### 音频与转录
- `POST /meetings/upload-audio`: 上传音频文件,并自动开始异步转录。
- **Form Data**: `audio_file`, `meeting_id`, `force_replace`
- `GET /meetings/{meeting_id}/audio`: 获取会议关联的音频文件信息。
- `GET /meetings/{meeting_id}/transcript`: 获取会议的完整转录稿 (`TranscriptSegment` 列表)。
- `POST /meetings/{meeting_id}/transcription/start`: 手动触发指定会议的转录任务。
- `GET /meetings/{meeting_id}/transcription/status`: 获取会议最新的转录任务状态。
- `GET /transcription/tasks/{task_id}/status`: 根据任务ID获取转录状态。
#### 内容编辑
- `PUT /meetings/{meeting_id}/speaker-tags`: 更新单个发言人的标签。
- `PUT /meetings/{meeting_id}/speaker-tags/batch`: 批量更新多个发言人的标签。
- `PUT /meetings/{meeting_id}/transcript/batch`: 批量更新转录内容文本。
#### AI 总结
- `POST /meetings/{meeting_id}/generate-summary-async`: **异步**生成会议纪要。
- **Request**: `GenerateSummaryRequest` (user_prompt)
- **Response**: 返回一个任务ID用于轮询状态。
- `GET /llm-tasks/{task_id}/status`: 获取AI总结任务的状态和进度。
- `GET /meetings/{meeting_id}/llm-tasks`: 获取指定会议的所有AI总结任务历史。
- `GET /meetings/{meeting_id}/latest-llm-task`: 获取会议最新的AI总结任务状态此方法被替代
#### 其他
- `POST /meetings/{meeting_id}/upload-image`: 上传图片用于在Markdown纪要中引用。
### 声纹采集功能 API
### 1. 获取用户声纹状态
- **GET** `/voiceprint/{user_id}`
- **描述**:获取指定用户的声纹采集状态
- **权限**:需要登录,只能查询自己的声纹状态(管理员可查询所有)
### 2. 获取朗读模板
- **GET** `/voiceprint/template`
- **描述**:获取声纹采集的标准朗读文本
- **权限**:需要登录
### 3. 上传声纹音频(同步处理)
- **POST** `/voiceprint/{user_id}`
- **描述**:上传声纹音频文件,同步处理并返回结果
- **权限**:需要登录,只能上传自己的声纹(管理员可操作所有)
### 4. 删除/重新采集声纹
- **DELETE** `/voiceprint/{user_id}`
- **描述**:删除用户的声纹数据,允许重新采集
- **权限**:需要登录,只能删除自己的声纹(管理员可操作所有)
## 6. 数据库设计
详细的数据库表结构、字段和关系图已被迁移到独立的文档中。
**[-> 点击查看数据库设计文档](./database.md)**
## 7. 未来展望
- **实时转录**: 支持对正在进行的会议进行实时语音转文字。
- **日历集成**: 与 Google Calendar, Outlook Calendar 集成,自动导入会议安排。
- **行动项提取**: AI自动识别会议中的待办事项 (Action Items)。
- **跨会议搜索**: 对用户的所有会议内容进行全文语义搜索。
- **移动端应用**: 开发 iOS 和 Android 版本的原生应用。

333
start.sh 100755
View File

@ -0,0 +1,333 @@
#!/bin/bash
# iMeeting Docker 快速启动脚本
# 使用方法: ./start.sh [选项]
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 打印带颜色的消息
print_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 打印banner
print_banner() {
echo -e "${BLUE}"
cat << "EOF"
_ __ __ _ _
(_) \/ | ___ ___| |_(_)_ __ __ _
| | |\/| |/ _ \/ _ \ __| | '_ \ / _` |
| | | | | __/ __/ |_| | | | | (_| |
|_|_| |_|\___|\___|\__|_|_| |_|\__, |
|___/
Docker Deployment Script
EOF
echo -e "${NC}"
}
# 检查依赖
check_dependencies() {
print_info "检查系统依赖..."
if ! command -v docker &> /dev/null; then
print_error "未安装 Docker请先安装 Docker"
exit 1
fi
if ! command -v docker-compose &> /dev/null && ! docker compose version &> /dev/null; then
print_error "未安装 Docker Compose请先安装 Docker Compose"
exit 1
fi
print_success "系统依赖检查通过"
}
# 检查环境变量文件
check_env_file() {
print_info "检查环境变量配置..."
if [ ! -f .env ]; then
print_warning ".env 文件不存在,从模板创建..."
cp .env.example .env
print_warning "请编辑 .env 文件配置必要的参数七牛云、LLM API等"
print_warning "按任意键继续,或 Ctrl+C 退出..."
read -n 1 -s
else
print_success "环境变量文件已存在"
fi
}
# 检查并创建后端环境变量文件# 创建必要的目录
create_directories() {
print_info "创建必要的目录..."
# MySQL和Nginx配置目录
mkdir -p mysql/conf.d
mkdir -p nginx/conf.d
# 数据持久化目录
mkdir -p data/mysql
mkdir -p data/redis
mkdir -p data/uploads
mkdir -p data/logs/backend
mkdir -p data/logs/frontend
mkdir -p data/logs/nginx
# 后端配置和备份目录
mkdir -p backend/config
mkdir -p backups
print_success "目录创建完成"
}
# 生成Nginx配置
generate_nginx_config() {
print_info "检查Nginx配置..."
if [ ! -f nginx/nginx.conf ]; then
print_warning "nginx/nginx.conf 不存在,正在生成默认配置..."
cat > nginx/nginx.conf <<EOF
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '\$remote_addr - \$remote_user [\$time_local] "\$request" '
'\$status \$body_bytes_sent "\$http_referer" '
'"\$http_user_agent" "\$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
}
EOF
print_success "nginx/nginx.conf 已生成"
fi
if [ ! -f nginx/conf.d/default.conf ]; then
print_warning "nginx/conf.d/default.conf 不存在,正在生成默认站点配置..."
cat > nginx/conf.d/default.conf <<EOF
upstream frontend_server {
server frontend:80;
}
upstream backend_server {
server backend:8000;
}
server {
listen 80;
server_name localhost;
# 增加上传文件大小限制
client_max_body_size 100M;
# 后端API直连
location /api/ {
proxy_pass http://backend_server;
proxy_http_version 1.1;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
# 增加API超时时间
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
# 上传文件直连
location /uploads/ {
proxy_pass http://backend_server;
proxy_http_version 1.1;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
# 静态资源缓存配置
expires 30d;
add_header Cache-Control "public, no-transform";
}
# 前端代理 (其他请求)
location / {
proxy_pass http://frontend_server;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host \$host;
proxy_cache_bypass \$http_upgrade;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
}
EOF
print_success "nginx/conf.d/default.conf 已生成"
fi
}
# 检查并创建后端环境变量文件
check_backend_env() {
print_info "检查后端环境变量配置..."
if [ ! -f backend/.env ]; then
print_warning "backend/.env 文件不存在,从模板创建..."
if [ -f backend/.env.example ]; then
cp backend/.env.example backend/.env
print_success "已创建 backend/.env"
else
print_warning "backend/.env.example 不存在,跳过"
fi
else
print_success "后端环境变量文件已存在"
fi
}
# 启动服务
start_services() {
print_info "启动 Docker 服务..."
# 使用 docker compose 或 docker-compose
if docker compose version &> /dev/null; then
COMPOSE_CMD="docker compose"
else
COMPOSE_CMD="docker-compose"
fi
$COMPOSE_CMD up -d
print_success "服务启动命令已执行"
}
# 等待服务健康
wait_for_health() {
print_info "等待服务启动..."
local max_wait=120
local waited=0
while [ $waited -lt $max_wait ]; do
if docker compose version &> /dev/null; then
COMPOSE_CMD="docker compose"
else
COMPOSE_CMD="docker-compose"
fi
local healthy_count=$($COMPOSE_CMD ps --format json 2>/dev/null | grep -c '"Health":"healthy"' || echo "0")
local total_count=5 # mysql, redis, backend, frontend, nginx
if [ "$healthy_count" -eq "$total_count" ]; then
print_success "所有服务已就绪"
return 0
fi
echo -ne "\r等待中... (${waited}s/${max_wait}s) 健康: ${healthy_count}/${total_count}"
sleep 5
waited=$((waited + 5))
done
echo ""
print_warning "服务启动超时,请手动检查状态: docker-compose ps"
return 1
}
# 显示服务状态
show_status() {
print_info "服务状态:"
if docker compose version &> /dev/null; then
docker compose ps
else
docker-compose ps
fi
}
# 显示访问信息
show_access_info() {
echo ""
print_success "==================================="
print_success " iMeeting 部署完成!"
print_success "==================================="
echo ""
echo -e "${GREEN}访问地址:${NC}"
echo -e " HTTP访问: ${BLUE}http://localhost${NC}"
echo -e " 或通过服务器IP访问${BLUE}http://服务器IP${NC}"
echo -e " API文档: ${BLUE}http://localhost/docs${NC}"
echo ""
echo -e "${YELLOW}域名访问HTTPS:${NC}"
echo -e " 需要在接入服务器配置Nginx代理"
echo -e " 参考文档: ${BLUE}GATEWAY_NGINX_CONFIG.md${NC}"
echo ""
echo -e "${YELLOW}数据目录:${NC}"
echo -e " 数据持久化: ${BLUE}./data/${NC}"
echo -e " - MySQL: ${BLUE}./data/mysql/${NC}"
echo -e " - Redis: ${BLUE}./data/redis/${NC}"
echo -e " - 上传文件: ${BLUE}./data/uploads/${NC}"
echo -e " - 日志: ${BLUE}./data/logs/${NC}"
echo ""
echo -e "${YELLOW}常用命令:${NC}"
echo -e " 管理菜单: ${BLUE}./manage.sh${NC}"
echo -e " 查看日志: ${BLUE}docker-compose logs -f${NC}"
echo -e " 停止服务: ${BLUE}./stop.sh${NC}"
echo -e " 重启服务: ${BLUE}docker-compose restart${NC}"
echo -e " 查看状态: ${BLUE}docker-compose ps${NC}"
echo ""
echo -e "${YELLOW}更多信息请查看: ${BLUE}DOCKER_DEPLOYMENT.md${NC}"
echo ""
}
# 主函数
main() {
print_banner
check_dependencies
check_env_file
check_backend_env
create_directories
generate_nginx_config
start_services
echo ""
wait_for_health
echo ""
show_status
show_access_info
}
# 执行主函数
main "$@"

72
stop.sh 100755
View File

@ -0,0 +1,72 @@
#!/bin/bash
# iMeeting Docker 停止脚本
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
print_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
# 确定使用的命令
if docker compose version &> /dev/null; then
COMPOSE_CMD="docker compose"
else
COMPOSE_CMD="docker-compose"
fi
# 显示当前状态
print_info "当前服务状态:"
$COMPOSE_CMD ps
echo ""
# 询问是否删除数据
echo -e "${YELLOW}是否保留数据?${NC}"
echo "1) 仅停止服务(保留所有数据)"
echo "2) 停止服务并删除容器(保留数据卷)"
echo "3) 停止服务并删除所有数据(包括数据库)"
read -p "请选择 (1/2/3): " choice
case $choice in
1)
print_info "停止服务..."
$COMPOSE_CMD stop
print_success "服务已停止,数据已保留"
;;
2)
print_info "停止并删除容器..."
$COMPOSE_CMD down
print_success "容器已删除,数据卷已保留"
;;
3)
print_warning "警告: 这将删除所有数据,包括数据库!"
read -p "确认删除所有数据? (yes/no): " confirm
if [ "$confirm" = "yes" ]; then
print_info "停止并删除所有数据..."
$COMPOSE_CMD down -v
print_success "所有服务和数据已删除"
else
print_info "操作已取消"
fi
;;
*)
print_warning "无效选择,仅停止服务"
$COMPOSE_CMD stop
;;
esac

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 MiB

BIN
资料/slogan.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

View File

@ -0,0 +1,317 @@
# iMeeting 产品介绍
> **AI 驱动的智能会议管理与知识库系统**
>
> 让每一次会议都产生价值,让知识自动沉淀与传播
---
## 📌 产品定位
iMeeting 是一款面向企业和团队的智能会议管理工具,通过 AI 技术自动将会议录音转化为结构化知识,帮助团队高效管理会议、沉淀知识、提升协作效率。
### 核心价值
- **⏰ 节省时间**:自动生成会议纪要,无需人工整理
- **🧠 知识沉淀**:从多次会议中提炼知识库,避免重复讨论
- **🎯 精准检索**AI 智能问答,快速找到需要的信息
- **🎙️ 音频播客**:将知识转化为播客音频,随时随地学习
---
## ✨ 核心功能Phase 1 - 已实现)
### 🎤 智能会议管理
#### 一键转录
- 上传会议录音,自动转写为文字
- 支持多种音频格式MP3、WAV、M4A
- 基于阿里云语音识别,识别准确率 > 95%
#### AI 自动总结
- 使用大语言模型(通义千问)生成会议纪要
- 支持自定义提示词模版,适配不同会议场景
- 一键生成结构化总结:会议主题、关键决策、待办事项
#### 灵活标签分类
- 为会议添加多个标签,方便分类管理
- 按标签快速筛选和检索历史会议
---
### 📚 智能知识库
#### 会议知识提炼
- 从多个会议纪要中自动提炼知识库内容
- 支持自定义分析角度和总结需求
- 生成 Markdown 格式的结构化知识文档
#### 知识共享
- 支持个人知识库和共享知识库
- 团队成员可协作构建组织知识资产
#### 标签与检索
- 知识库标签分类
- 全文搜索,快速定位内容
---
### 👥 权限与管理
#### 用户权限管理
- 基于角色的权限控制(普通用户/管理员)
- JWT 安全认证
- 动态菜单权限
#### 管理后台
- 用户管理:创建、编辑、权限配置
- 系统监控:在线用户、任务状态、资源监控
- 提示词仓库:集中管理 AI 提示词模版
---
## 🚀 未来规划Phase 2 - 开发中)
### 🌟 全新升级:从会议工具到 AI 知识助手
参考 Google NotebookLMiMeeting 即将升级为功能完整的 AI 知识助手,提供多维度的知识管理和智能交互能力。
---
### 📂 多源输入
不再局限于会议内容,支持更丰富的知识来源:
| 输入类型 | 支持格式 | 说明 |
|---------|---------|------|
| **文档** | PDF、Word、TXT、Markdown | 上传技术文档、报告、笔记 |
| **音频** | MP3、WAV、M4A | 讲座录音、播客、培训音频 |
| **视频** | MP4、AVI、MOV | 自动提取音频并转录 |
| **会议** | 已有功能 | 从会议纪要中提炼知识 |
**混合使用**:单个知识库可同时包含多种来源,全面汇总信息。
---
### 🎙️ 播客式音频概览
#### 文字转语音TTS
- 将知识库内容转换为音频,支持随时随地收听
- 多种音色可选,语速可调
#### NotebookLM 风格的播客对话
**创新功能**:自动生成双人对话式播客
- 🎭 **双人角色**:主持人(引导话题) + 专家(深度讲解)
- 💬 **自然对话**:通过问答形式展开知识点,生动易懂
- 🎵 **专业制作**:自动添加片头片尾、背景音乐、音量均衡
**使用场景**
- 上班通勤时听取项目汇报
- 运动时学习技术文档
- 团队培训音频分享
---
### 💬 NotebookLM 式智能问答
#### 基于知识库的对话
- **精准回答**基于向量检索RAG 技术),从知识库中精准定位答案
- **引用溯源**:回答时显示来源段落、章节、页码
- **多轮对话**:支持上下文记忆,连续提问
- **相关推荐**:基于提问智能推荐相关知识点
#### 交互示例
```
用户: "上次会议讨论的产品发布日期是什么时候?"
AI: "根据《产品规划会议纪要》2024-03-15第 2 章节,
产品发布日期定为 2024年6月1日。
📚 来源:
- 产品规划会议纪要 > 第二部分:时间规划 > 发布节点
- 原文:"经过讨论团队一致决定将正式发布日期定为6月1日..."
```
---
### 📊 结构化输出升级
#### 智能提示词组合
- **基础模版**:从提示词仓库选择预设模版
- **附加提示词**:在模版基础上追加自定义需求
- **输出格式控制**:自动生成多级章节结构(标题、章节、小节)
#### 示例
**输入**
- 基础模版:技术文档总结模版
- 附加提示词:"重点关注性能优化和安全性"
**输出**
```markdown
# XXX技术方案总结
## 1. 技术架构
### 1.1 整体架构
### 1.2 核心模块
## 2. 性能优化(重点)
### 2.1 数据库优化
### 2.2 缓存策略
## 3. 安全性设计(重点)
### 3.1 认证与授权
### 3.2 数据加密
...
```
---
## 🎯 应用场景
### 企业协作
- **项目管理**:自动记录项目会议,生成任务清单
- **知识传承**:新员工快速了解历史项目和决策背景
- **培训学习**:将培训内容转化为知识库和播客
### 研发团队
- **技术评审**:自动整理技术评审会议,生成方案文档
- **代码审查**:记录审查要点,形成最佳实践知识库
- **团队同步**:定期会议自动生成周报、月报
### 教育培训
- **课程记录**:将讲座、课程录音转化为文字和播客
- **知识问答**:学生可向课程知识库提问,获得精准答案
- **复习资料**:自动生成结构化复习材料
### 咨询与销售
- **客户会议**:自动记录需求和承诺,生成跟进任务
- **知识沉淀**:积累行业洞察和解决方案
- **快速响应**:从历史案例中快速找到相似场景
---
## 💡 技术亮点
### AI 能力
- **语音识别**:基于阿里云 DashScope识别准确率 > 95%
- **大语言模型**:通义千问驱动,智能总结与问答
- **向量检索**:基于 RAG 技术,精准定位知识
- **语音合成**:自然流畅的多音色 TTS
### 技术架构
- **前端**React 18 + Ant Design现代化交互体验
- **后端**FastAPIPython高性能异步处理
- **数据库**MySQL 8.0 + Redis稳定可靠
- **存储**:七牛云 OSS快速访问
### 安全与性能
- **数据安全**JWT 认证、角色权限控制
- **高可用**:异步任务处理、系统监控
- **可扩展**:模块化设计,支持功能灵活组合
---
## 📈 产品价值
### 效率提升
- **节省 80% 会议记录时间**:自动转录和总结
- **减少 50% 信息查找时间**AI 智能问答
- **提升 3 倍知识复用率**:知识库沉淀与共享
### 成本优势
- **月运营成本 < 100 元**(中小规模团队)
- **无需额外硬件**:云端部署,按需使用
- **灵活扩展**:根据团队规模调整
### 用户体验
- **一键操作**:上传音频即可,无需复杂配置
- **多端访问**Web 端随时随地访问
- **智能交互**:对话式问答,自然流畅
---
## 🎁 核心竞争力
### 与传统会议工具对比
| 特性 | 传统工具 | iMeeting |
|------|---------|----------|
| **录音转文字** | ✅ 支持 | ✅ 支持 |
| **AI 自动总结** | ❌ 不支持 | ✅ 支持 |
| **知识库提炼** | ❌ 不支持 | ✅ 支持 |
| **智能问答** | ❌ 不支持 | ✅ 支持Phase 2 |
| **播客生成** | ❌ 不支持 | ✅ 支持Phase 2 |
| **多源输入** | ❌ 仅会议 | ✅ 文档+音视频Phase 2 |
### 与 NotebookLM 对比
| 特性 | NotebookLM | iMeeting |
|------|-----------|----------|
| **文档上传** | ✅ 支持 | ✅ 支持Phase 2 |
| **音频播客** | ✅ 支持 | ✅ 支持Phase 2 |
| **智能问答** | ✅ 支持 | ✅ 支持Phase 2 |
| **会议管理** | ❌ 不支持 | ✅ 核心功能 |
| **团队协作** | ⚠️ 有限 | ✅ 完整支持 |
| **私有部署** | ❌ 不支持 | ✅ 可私有部署 |
---
## 🌟 适用对象
### 企业团队
- 10-500 人规模的中小企业
- 需要频繁开会和知识管理的团队
- 重视知识沉淀的创新型公司
### 个人用户
- 项目经理、产品经理
- 研发工程师、技术负责人
- 顾问、讲师、自媒体创作者
### 行业领域
- 科技互联网
- 咨询服务
- 教育培训
- 金融保险
- 医疗健康
---
## 📅 发展路线
### Phase 1已完成
- 会议录音转录
- AI 自动总结
- 基础知识库
- 用户权限管理
### Phase 2开发中🚀
- 多源输入(文档、音视频)
- 播客式音频生成
- NotebookLM 式智能问答
- 结构化输出升级
**预计上线时间**1-1.5 个月
### Phase 3规划中💡
- 实时会议转录
- 多语言支持
- 移动端 App
- 企业级功能SSO、审计
---
## 💬 联系我们
如果您对 iMeeting 感兴趣,或有任何问题和建议,欢迎联系我们:
- **产品咨询**[联系邮箱]
- **技术支持**[技术支持邮箱]
- **商务合作**[商务邮箱]
---
**iMeeting - 让每一次会议都产生价值** 🚀

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB