版本:v2.0+ | 最后更新:2026年4月
本手册覆盖:项目功能介绍、架构说明、环境安装(手把手)、三种启动方式、页面功能详解、配置项说明、常见问题排查。
近期行为变更(v2.1+):
- 字幕优先(主页「转写引擎」下,需先「开启转写」):用 FFprobe/FFmpeg 先尝试从容器内解出内嵌文字幕轨(软字幕/常见封装)。成功则把字幕当「原文」基础(可再走通义断句补标点);若无字幕或提取失败,再按所选引擎做 FunASR 本地转写 或 百炼 API。适合「已有现成 SRT/ASS 等轨」的素材,可省转写时间;无字幕的纯口播仍依赖 ASR。结果中的
recognition_type为subtitle/funasr/dashscope等,便于区分来源。配置存 Redis,刷新后保留。详细说明见 §10.2.2。 - 设置 「本地路径与存储」 中可填 「文件名清洗正则」(Python 正则,作用于去掉扩展名后的主名)。用于从杂乱命名中抽出展示名;
title、JSON/source_files展示名、本地与 OSS 命名、Notion/飞书标题等均用清洗后名称,original_filename保留用户上传的原始全名。详细说明见 §10.2.1。默认空表示不清洗。 - OSS 对象键 采用
SHA-256(原始媒体文件) 前 8 位十六进制 + 下划线 + 清洗后文件名(FFmpeg/转写之前对上传原文件分块算哈希),在同一分类下实现同内容去重、覆盖幂等;键示例:{分类}/audios/a1b2c3d4_产品会议.mp3。上传前会打日志:哈希、目标 Key、直接覆盖上传。 - 记录唯一标识 (UUID) 采用
MD5(Hash+标题)生成的 32 位确定性字符串。非合并模式基于单文件,合并模式基于多文件 Hash 排序拼接。该 UUID 贯穿数据库、Notion 和飞书,确保全链路去重。 - Redis 缓存防抖:数据库保存成功后,将各平台 ID 映射存入 Redis(5分钟 TTL)。推送时优先查缓存,命中则直接 Update,未命中再 Search/Create,大幅减少 API 搜索请求。
- 历史记录表
records增加recognition_type。SQLite 启动时自动ALTER加列;Supabase 老库需执行docs/migrations/20260425_add_recognition_type.sql。 - 历史 「查看」 为 三 Tab(原文 / AI 总结 / 其它信息;其它信息中展示元数据、文件与链接等)。设置 弹窗为 固定视窗高度、内部滚动。
- 项目介绍
- 功能全览
- 技术架构
- 目录结构
- 环境准备(从零安装)
- 配置文件详解
- 启动方式一:纯本地开发模式
- 启动方式二:Docker 全栈模式
- 启动方式三:混合模式(推荐日常开发)
- 页面功能详解
- 输出数据格式说明
- Notion / 飞书集成指南
- OSS 配置指南
- 历史记录与二次处理
- 常见问题与排查
- 性能参考与建议
media2text 是一个运行在本地或云端的媒体文件转文本平台。

你可以把它理解为一个私有的、可灵活配置的"音视频内容提取器":
- 把会议录音、播客、课程视频、访谈音频等批量丢进来
- 系统自动把视频抽成音频,把音频转成文字
- 可选让大模型帮你总结成摘要
- 结果可以保存本地、存数据库、上传 OSS、同步到 Notion 或飞书
- 所有配置都在页面里点击完成,不需要改代码
| 人群 | 使用场景 |
|---|---|
| 内容创作者 | 批量处理播客/访谈,提取文字稿 |
| 知识工作者 | 会议录音转文字+AI总结,同步飞书 |
| 研究人员 | 课程视频批量转录,存入 Notion 知识库 |
| 开发者 | 本地部署,数据不出内网,自定义扩展 |
上传文件(视频/音频混合)
↓
自动识别文件类型
↓
视频 → FFmpeg 提取音频(mp3, 16kHz)
↓
音频 → 转写(本地 FunASR 或 阿里云百炼 API)
↓
文字 → Markdown 格式化
↓
可选:AI 大模型总结(通义千问)
↓
可选存储:本地文件 / OSS / SQLite / Supabase
↓
可选推送:Notion 多维表格 / 飞书多维表格
| 功能 | 默认 | 说明 |
|---|---|---|
| 保存音频到本地 | ✅ 开 | 提取的音频保存到本地目录 |
| 上传音频到 OSS | ❌ 关 | 上传至阿里云 OSS,获得公网 URL |
| 开启转写 | ❌ 关 | 音频 → 文字 |
| 字幕优先 | ❌ 关 | 开启转写时可用:先内嵌软字幕,失败再转写 |
| 保存文本到本地 | ❌ 关 | 转写结果保存为 .md 文件 |
| 上传文本到 OSS | ❌ 关 | 转写结果上传 OSS |
| 批量模式:分开/合并 | 分开 | 合并时多文件拼成一份文稿 |
| AI 大模型总结 | ❌ 关 | 调用大模型生成摘要 |
| 推送到 Notion | ❌ 关 | 同步一条记录到 Notion 数据库 |
| 推送到飞书 | ❌ 关 | 同步一条记录到飞书多维表格 |
| 保存到历史记录 | ❌ 关 | 存入本地 SQLite 或 Supabase |
| 引擎 | 费用 | 前置条件 | 中文效果 | 适用场景 |
|---|---|---|---|---|
| 本地 FunASR | 免费 | 首次自动下载模型(约 500MB) | ⭐⭐⭐⭐⭐ | 中文为主,追求免费离线 |
| 阿里云百炼 API | 按用量付费 | 需 OSS + DashScope Key | ⭐⭐⭐⭐⭐ | 不想本地跑模型,追求速度 |
⚠️ 重要:使用百炼 API 时,必须同时开启「上传音频到 OSS」,因为百炼只接受公网 URL,不支持直接上传本地文件。
┌─────────────────────────────────────────────────────────────┐
│ 浏览器 │
│ Vue3 + Vite + Ant Design Vue 4 + Pinia │
│ (三栏布局:文件区 | 配置区 | 结果区) │
└────────────────────────┬────────────────────────────────────┘
│ HTTP REST + SSE 实时进度
┌────────────────────────▼────────────────────────────────────┐
│ FastAPI 后端 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────┐ │
│ │ FFmpeg │ │ FunASR │ │ DashScope│ │ 通义千问 │ │
│ │ 视频转音频│ │ 本地ASR │ │ 云端ASR │ │ AI总结 │ │
│ └──────────┘ └──────────┘ └──────────┘ └────────────┘ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────┐ │
│ │ 阿里OSS │ │ Notion │ │ 飞书 │ │ Supabase │ │
│ │ 上传 │ │ 推送 │ │ 推送 │ │ 远程DB │ │
│ └──────────┘ └──────────┘ └──────────┘ └────────────┘ │
└────────────────────────┬────────────────────────────────────┘
│
┌────────────┴────────────┐
│ │
┌──────▼──────┐ ┌────────▼──────┐
│ Redis │ │ SQLite/Supabase│
│ 配置持久化 │ │ 历史记录存储 │
│ 分类/提示词 │ │ │
└─────────────┘ └───────────────┘
| 组件 | 作用 | 是否必须 |
|---|---|---|
| Redis | 存所有配置(开关/路径/API Key/分类/提示词) | ✅ 必须 |
| FFmpeg | 视频转音频 | ✅ 必须 |
| FunASR | 本地语音识别 | ⚡ 使用本地转写时必须 |
| DashScope | 百炼云端语音识别 | ⚡ 使用百炼API时必须 |
| OSS | 音频/文本云存储 + 为百炼提供公网URL | ⚡ 使用百炼/云存储时必须 |
| SQLite | 本地历史记录数据库 | 🔧 开启存储时必须 |
| Supabase | 云端历史记录数据库(可替代SQLite) | 🔧 选用时配置 |
| 通义千问 | AI 总结 | 🔧 开启总结时必须 |
| Notion / 飞书 | 推送转写结果 | 🔧 开启推送时必须 |
media2text/ ← 项目根目录(仓库根)
├── docker-compose.yml ← Docker 全栈启动配置
├── Makefile ← 快捷命令(make up / make dev 等)
├── .env ← 你的本地配置(从 .env.example 复制)
├── .env.example ← 配置模板(带注释说明)
├── README.md ← 项目说明(简要)
├── docs/
│ └── DEPLOYMENT.md ← 本完整使用手册
│
├── backend/ ← Python FastAPI 后端
│ ├── main.py ← 应用入口,lifespan 启动检查
│ ├── requirements.txt ← Python 依赖列表
│ ├── Dockerfile ← 后端 Docker 镜像
│ ├── .env ← 后端专属环境变量(可选)
│ ├── media2text.db ← SQLite 示例文件名(实际路径见 SQLITE_PATH / 设置)
│ ├── temp/ ← 上传文件临时目录(处理完自动清理)
│ ├── output/ ← 本地输出根目录
│ │ └── 默认分类/
│ │ ├── audios/ ← 提取的音频文件
│ │ └── captions/ ← 转写文本文件(.md 格式)
│ ├── core/
│ │ ├── logger.py ← 全链路日志(含 trace_id 追踪)
│ │ ├── redis_client.py ← Redis 连接单例 + 操作函数
│ │ ├── config_loader.py ← 从 Redis / 环境变量加载配置
│ │ ├── startup_checks.py ← 启动时环境自检(FFmpeg / Redis 等)
│ │ └── db_factory.py ← 数据库引擎工厂
│ ├── models/
│ │ └── schemas.py ← Pydantic 数据模型
│ ├── routers/
│ │ ├── upload.py ← 文件上传接口
│ │ ├── process.py ← 批量处理 + SSE 进度推送
│ │ ├── config.py ← 配置读写、分类、提示词管理
│ │ ├── history.py ← 历史记录 CRUD + 导出
│ │ ├── push.py ← Notion / 飞书推送 API
│ │ ├── integrations.py ← 集成字段说明(如 /api/integrations/schema)
│ │ └── asr.py ← FunASR 状态查询 + 按需加载
│ └── services/
│ ├── file_detector.py ← 文件类型判断
│ ├── video_converter.py ← FFmpeg 视频→音频
│ ├── oss_uploader.py ← 阿里云 OSS 上传
│ ├── asr_local.py ← FunASR 本地推理(单例+状态机)
│ ├── asr_dashscope.py ← 百炼 API 转写(含结果 URL 二次拉取)
│ ├── markdown_formatter.py ← 转写结果→Markdown 格式
│ ├── summarizer.py ← AI 总结(可扩展多模型)
│ ├── notion_push.py ← Notion 推送
│ ├── feishu_push.py ← 飞书多维表格推送
│ ├── push_common.py ← 推送共用(字段说明等)
│ ├── integration_payload.py ← 集成导出 / 推送统一字段
│ ├── history_ops.py ← 历史记录与推送辅助
│ ├── history_export.py ← 历史记录导出 Excel / CSV
│ ├── db.py ← 数据库入口(初始化 / 路由用)
│ ├── db_adapter.py ← 数据库抽象基类
│ ├── db_sqlite.py ← SQLite 实现
│ ├── db_supabase.py ← Supabase 实现
│ └── batch_mode_util.py ← 批量模式显示与存储规范化
│
└── frontend/ ← Vue3 前端
├── package.json
├── vite.config.js ← 开发时代理 /api → localhost:8000
├── Dockerfile ← 前端 Docker 镜像(Nginx 托管)
├── nginx.conf ← Nginx 配置(含 /api 反向代理)
├── index.html
└── src/
├── main.js
├── App.vue
├── api/index.js ← 所有后端 API 调用封装
├── stores/
│ ├── config.js ← 配置状态(watch + debounce 写 Redis)
│ ├── files.js ← 文件列表状态
│ └── task.js ← 任务进度状态
├── views/
│ └── Home.vue ← 三栏主页面
└── components/
├── layout/TopBar.vue
├── left/ ← 左侧:上传 + 文件列表
├── middle/ ← 中间:配置面板
├── right/ ← 右侧:进度 + 结果
└── modals/ ← 弹窗:设置/历史/提示词管理
按顺序操作,每步验证通过再继续下一步。
为什么是 3.11:部分依赖(FunASR / PyTorch)在 3.12 存在兼容问题,3.9/3.10 性能略低。
- 打开:https://www.python.org/downloads/release/python-3119/
- 下载 Windows installer (64-bit)
- 运行安装,关键:勾选底部 "Add python.exe to PATH",然后点 Install Now
# 新开 PowerShell 验证
python --version
# 期望输出:Python 3.11.x如果有多个 Python 版本,可以用:
py -3.11 --version# 用 Homebrew(推荐)
brew install python@3.11
# 加入 PATH(只需做一次)
echo 'export PATH="/opt/homebrew/opt/python@3.11/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
python3.11 --versionsudo apt update
sudo apt install -y python3.11 python3.11-venv python3.11-dev
python3.11 --version为什么要用 venv:隔离项目依赖,避免污染系统 Python 环境,不同项目互不影响。
# 进入后端目录
cd media2text/backend
# 创建虚拟环境(只需做一次)
python -m venv .venv
# ── 激活(每次新开终端都需要)──────────────────────────────────
# Windows PowerShell:
.\.venv\Scripts\Activate.ps1
# Windows CMD:
.venv\Scripts\activate.bat
# macOS / Linux:
source .venv/bin/activate
# ────────────────────────────────────────────────────────────────
# 激活后命令行前缀出现 (.venv),然后安装依赖
pip install --upgrade pip
# 先装 PyTorch CPU 版(体积约 800MB,必须先装)
pip install torch torchaudio --index-url https://download.pytorch.org/whl/cpu
# 再装其余依赖
pip install -r requirements.txt网络慢/超时? 加国内镜像参数:
pip install torch torchaudio --index-url https://download.pytorch.org/whl/cpu -i https://pypi.tuna.tsinghua.edu.cn/simple pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
安装完成验证:
python -c "import fastapi, funasr, redis, oss2, dashscope; print('✅ 所有依赖安装成功')"# 验证版本(18.x 或以上即可)
node -v # 期望:v18.x.x 或 v20.x.x
npm -v如果未安装:去 https://nodejs.org 下载 LTS 版,一路安装即可(会自动加入 PATH)。
# 进入前端目录
cd media2text/frontend
# 安装依赖(只需做一次,package.json 变化后重做)
npm install
# 网络慢时使用国内镜像
npm config set registry https://registry.npmmirror.com
npm installFFmpeg 是处理音视频的命令行工具,必须安装且在 PATH 中可用,否则后端启动时会报错并拒绝运行。
- 打开:https://www.gyan.dev/ffmpeg/builds/
- 下载 ffmpeg-release-essentials.zip(约 70MB)
- 解压到固定路径,例如
C:\ffmpeg\,解压后目录结构类似:C:\ffmpeg\ └── ffmpeg-7.x-essentials_build\ ├── bin\ │ ├── ffmpeg.exe ← 这个文件要加入 PATH │ ├── ffplay.exe │ └── ffprobe.exe └── ... - 添加到系统 PATH:
- 按
Win + R,输入SystemPropertiesAdvanced,回车 - 点「环境变量」→ 在「系统变量」找到
Path→ 点「编辑」→「新建」 - 输入
C:\ffmpeg\ffmpeg-7.x-essentials_build\bin(换成你的实际路径) - 一路确定
- 按
- 新开一个 PowerShell 窗口验证:
ffmpeg -version
# 期望输出首行类似:ffmpeg version 7.x ...brew install ffmpeg
ffmpeg -versionsudo apt install -y ffmpeg
ffmpeg -versionRedis 是本项目强依赖,用于存储所有配置。未启动则后端直接拒绝运行。
需要先安装 Docker Desktop:https://www.docker.com/products/docker-desktop/
# 在项目根目录(有 docker-compose.yml 的位置)
docker compose up -d redis
# 验证
docker ps | grep redis
# 看到 redis 容器 running 即可macOS:
brew install redis
brew services start redis
redis-cli ping # 返回 PONG 即成功Linux:
sudo apt install -y redis-server
sudo systemctl start redis-server
sudo systemctl enable redis-server
redis-cli pingWindows: 推荐使用 WSL2 安装 Linux 版 Redis,或使用上面的 Docker 方式,Windows 原生没有官方 Redis 安装包。
全部装完后,在新开的终端中逐一验证:
python --version # Python 3.11.x
node -v # v18.x.x 或更高
ffmpeg -version # ffmpeg version 7.x...
redis-cli ping # PONG(或通过 docker 验证)
docker compose version # Docker Compose version v2.x(如果用 Docker)# 在项目根目录
cp .env.example .env # macOS/Linux
# Windows: 直接复制 .env.example,改名为 .env# ── Redis ─────────────────────────────────────────────────────
# Redis 连接地址(支持变量引用)
REDIS_HOST=127.0.0.1
REDIS_DB_PORT=6379
REDIS_URL="redis://${REDIS_HOST}:${REDIS_DB_PORT}/0"
# Docker Compose 端口映射(可选,修改时调整)
REDIS_PUBLISH_PORT=6379
BACKEND_PORT=8000
FRONTEND_PORT=3000
# ── 后端服务 ──────────────────────────────────────────────────
APP_HOST=0.0.0.0
APP_PORT=8000
CORS_ORIGINS=*
# ── SQLite 数据库 ────────────────────────────────────────────
# 数据库目录和文件名(推荐放在 localdata 下便于管理)
SQLITE_DATA_DIR=./localdata/sqlite_data
SQLITE_FILENAME=media2text.db
# 完整路径(本机 Python 直接使用)
SQLITE_PATH="${SQLITE_DATA_DIR}/${SQLITE_FILENAME}"
# Supabase 配置(如使用 Supabase 替代 SQLite,在页面设置中填写)
# SUPABASE_URL=https://xxxxxxxxxxxx.supabase.co
# SUPABASE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxx
# SUPABASE_TABLE=media2text_records
# ── FunASR / ModelScope ──────────────────────────────────────
# 模型缓存目录(FunASR 模型下载位置,避免重复下载)
MODELSCOPE_CACHE=./localdata/modelscope_cache/hub
# 是否在应用启动后后台预加载 FunASR 模型(true/false)
# true:启动后台异步加载,不阻塞服务启动
# false:首次转写时按需加载(首次会等待约30秒)
PRELOAD_FUNASR=false
# ── 临时目录 ─────────────────────────────────────────────────
# 上传文件和处理过程中的临时存储目录
# 建议指定绝对路径或与 Docker Compose 挂载路径一致
TEMP_DIR=./localdata/temp注意:API Key(OSS、DashScope、Notion、飞书、Qwen 等)不在
.env里配置,全部在页面「设置」弹窗里填写,保存到 Redis,更安全也更方便。
v2.0+ 新增:支持将全部配置(含密钥、分类、提示词)导出为 JSON 文件,方便备份和迁移。
点击页面右上角 ⚙️ 设置 → 切换到 「配置快照」 Tab。
| 按钮 | 说明 | 适用场景 |
|---|---|---|
| 复制 Markdown(脱敏) | 生成 Markdown 格式,API Key 等敏感信息会被打码(如 LTAI****xxxx) |
分享配置给他人排查问题 |
| 复制 JSON(完整) | 复制完整 JSON 到剪贴板(含所有密钥) | 快速备份或粘贴到其他设备 |
| 下载 JSON 文件 | 下载 .json 文件到本地,文件名格式:media2text-config-{时间戳}.json |
长期备份、版本管理 |
导出的 JSON 结构示例:
{
"schema_version": 1,
"app": "media2text",
"exported_at": "2025-04-25T10:30:00.000Z",
"config": {
"category": "默认分类",
"save_audio_local": true,
"save_audio_oss": false,
"transcribe_enabled": false,
"asr_engine": "funasr",
"transcript_save_local": false,
"transcript_save_oss": false,
"batch_mode": "separate",
"merge_title": "",
"summary_enabled": false,
"summary_model": "qwen",
"summary_prompt_title": "默认总结",
"save_to_db": false,
"dashscope_api_key": "sk-xxxxxxxx",
"qwen_api_key": "",
"oss_access_key_id": "LTAI5xxxxxxxxx",
"oss_access_key_secret": "xxxxxxxxxxxx",
"oss_bucket_name": "your-bucket",
"oss_endpoint": "oss-cn-hangzhou.aliyuncs.com",
"audio_local_base_path": "./output",
"transcript_local_base_path": "./output",
"temp_dir": "./temp",
"push_notion_enabled": false,
"push_feishu_enabled": false,
"notion_integration_token": "secret_xxxxxxxxxxxx",
"notion_database_id": "a1b2c3d4e5f67890abcdef1234567890",
"feishu_app_id": "cli_xxxxxxxxxxxx",
"feishu_app_secret": "xxxxxxxxxxxx",
"feishu_bitable_app_token": "Hxxxxxxxxxxxx",
"feishu_table_id": "tblxxxxxxxxxxxx",
"db_engine": "sqlite",
"sqlite_path": "",
"supabase_url": "",
"supabase_key": "",
"supabase_table": "media2text_records"
},
"categories": ["默认分类", "会议", "课程"],
"prompts": [
{
"title": "默认总结",
"content": "请阅读以下转写文本,用中文输出:关键要点、行动项(如有)、时间线(如能推断),使用 Markdown 小标题分段。"
},
{
"title": "会议纪要",
"content": "请提取本次会议的核心决议、待办事项和责任人。"
}
]
}点击 [从 JSON 导入…] 按钮,选择之前导出的 .json 文件:
- 仅含
config段:只更新配置项(开关、API Key 等),分类和提示词不变 - 含
categories段:替换全部分类列表 - 含
prompts段:替换全部提示词列表 - 三段都有:完整恢复整个配置
⚠️ 安全提醒:JSON 文件包含所有 API Key 和密钥,请勿公开分享或上传到公共仓库。建议使用「复制 Markdown(脱敏)」来分享配置用于问题排查。
适合:想修改代码、热重载调试、不使用 Docker
前提:Redis 已在运行(Docker 或本机安装均可)
# 新开一个终端,进入 backend 目录
cd media2text/backend
# 激活虚拟环境
source .venv/bin/activate # macOS/Linux
# 或
.\.venv\Scripts\Activate.ps1 # Windows PowerShell
# 启动(热重载模式,修改代码自动重启)
uvicorn main:app --reload --host 0.0.0.0 --port 8000启动成功时,你会看到类似日志:
INFO | startup | ✅ FFmpeg 已安装:ffmpeg version 7.0...
INFO | startup | ✅ Redis 连接成功:redis://127.0.0.1:6379/0
INFO | startup | ✅ FunASR 已安装(版本:1.x.x)
WARNING | startup | ⚠️ DashScope API Key 未配置(百炼转写不可用)
WARNING | startup | ⚠️ OSS 未配置(上传功能不可用)
INFO | startup | ── 当前配置 ─────────────────────────────
INFO | startup | 当前分类:默认分类
INFO | startup | 保存音频到本地:开
INFO | startup | 转写引擎:本地 FunASR
INFO | startup | 批量模式:分开输出
INFO | uvicorn | Application startup complete.
INFO | uvicorn | Uvicorn running on http://0.0.0.0:8000
# 新开另一个终端,进入 frontend 目录
cd media2text/frontend
npm run dev启动成功后会看到:
VITE v5.x.x ready in xxx ms
➜ Local: http://localhost:5173/
➜ Network: http://192.168.x.x:5173/
打开浏览器,访问:http://localhost:5173
适合:生产部署、一键启动、不想配本地 Python/Node 环境
前提:安装了 Docker Desktop(Windows/macOS)或 Docker Engine(Linux)
# 在项目根目录(有 docker-compose.yml 的位置)
# ── 启动命令 ────────────────────────────────────────────────
# 首次启动(会拉取镜像、构建,需要较长时间)
docker compose up -d --build
# 非首次启动(已构建过镜像,直接启动)
docker compose up -d
# 启动全部服务(等价于 up -d)
make up
# ── 单独启动某个服务 ───────────────────────────────────────
# 仅启动 Redis
docker compose up -d redis
# 仅启动后端(会自动启动依赖的 Redis)
docker compose up -d backend
# 仅启动前端(会自动启动依赖的 backend)
docker compose up -d frontend
# ── 停止命令 ────────────────────────────────────────────────
# 停止全部服务(保留容器和数据卷)
docker compose stop
# 停止并删除全部容器(保留数据卷)
docker compose down
# 停止并删除全部容器 + 数据卷(⚠️ 会丢失所有数据)
docker compose down -v
# ── 单独停止某个服务 ───────────────────────────────────────
# 停止 Redis
docker compose stop redis
# 停止后端
docker compose stop backend
# 停止前端
docker compose stop frontend
# 停止并删除某个容器
docker compose down redis
# ── 重启命令 ────────────────────────────────────────────────
# 重启全部服务
docker compose restart
# 重启单个服务
docker compose restart backend
# ── 重新构建并启动(代码修改后) ───────────────────────────
# 重建全部镜像并启动
# 💡 注意:up -d --build 会自动停止旧容器、重建镜像、启动新容器,无需手动 stop/down
docker compose up -d --build
# 仅重建后端并启动
# 💡 会自动停止 backend 容器,重建镜像,然后启动(Redis 不受影响)
docker compose up -d --build backend
# 仅重建前端并启动
docker compose up -d --build frontend
# 或使用 Makefile(推荐)
make rebuild-backend # 重建后端镜像并重启
make rebuild-frontend # 重建前端镜像并重启
# 或使用 Makefile
make updocker compose ps期望看到三个服务都是 running:
NAME STATUS
media2text-redis running
media2text-backend running
media2text-frontend running
docker compose logs backend
# 或跟随实时日志
docker compose logs -f backend- 前端:http://localhost:3000
- 后端 API:http://localhost:8000
- API 文档(FastAPI 自动生成):http://localhost:8000/docs
# ── 启动/停止 ─────────────────────────────────────────────
make up # 启动全部服务
docker compose up -d # 同上(原生 Docker 命令)
make down # 停止全部服务
docker compose down # 同上
make dev # 仅启动 Redis(混合模式开发)
docker compose up -d redis # 同上
# ── 日志查看 ──────────────────────────────────────────────
make logs # 查看全部日志(跟随)
docker compose logs -f # 同上
docker compose logs -f backend # 仅查看后端日志
docker compose logs -f frontend # 仅查看前端日志
docker compose logs -f redis # 仅查看 Redis 日志
# ── 重建镜像 ──────────────────────────────────────────────
make rebuild-backend # 重建后端镜像并重启
make rebuild-frontend # 重建前端镜像并重启
docker compose up -d --build backend # 同上(原生命令)
docker compose up -d --build frontend # 同上
# ── 其他 ──────────────────────────────────────────────────
docker compose ps # 查看运行中的容器状态
docker compose down -v # 停止并删除全部容器和数据卷(⚠️ 数据会丢失)| 场景 | 说明 |
|---|---|
| 修改后端代码 | 需要 make rebuild-backend 重建镜像(无需先停止,会自动处理) |
| 修改前端代码 | 需要 make rebuild-frontend 重建镜像(无需先停止,会自动处理) |
| 数据持久化 | SQLite 文件和输出目录通过 volume 挂载到宿主机,数据不丢失 |
| FunASR 模型缓存 | 通过 funasr_cache volume 持久化,避免每次重建都重新下载 |
修改 .env |
需要重启服务 make down && make up |
| 重建是否需要先停止? | 不需要。docker compose up -d --build 会自动停止旧容器、重建、启动新容器 |
Redis 用 Docker,后端和前端跑在本机 → 可以热重载改代码,又不用本机装 Redis
# 第一步:仅启动 Redis
make dev
# 或
docker compose up -d redis
# 第二步:终端 A,启动后端(本机,支持热重载)
cd backend
source .venv/bin/activate
uvicorn main:app --reload --host 0.0.0.0 --port 8000
# 第三步:终端 B,启动前端(本机,Vite 热更新)
cd frontend
npm run dev┌─────────────────┬──────────────────────┬──────────────────────┐
│ 左侧 1/3 │ 中间 1/3 │ 右侧 1/3 │
│ │ │ │
│ ┌───────────┐ │ 当前分类 [默认▼] [+] │ 处理进度列表 │
│ │ 分类选择 │ │ ───────────────── │ (超10条滚动) │
│ └───────────┘ │ ▌音频存储 │ │
│ │ 保存本地 ●─ │ ───────────────── │
│ ┌───────────┐ │ 上传OSS ○─ │ │
│ │拖拽上传区 │ │ ───────────────── │ 识别结果预览 │
│ │ │ │ ▌转写设置 │ [原文Tab] [总结Tab] │
│ └───────────┘ │ 开启转写 ○─ │ │
│ │ 保存本地 ○─ │ [复制JSON] [下载] │
│ ┌───────────┐ │ 上传OSS ○─ │ │
│ │ 文件列表 │ │ ───────────────── │ │
│ │(可滚动) │ │ ▌批量模式 │ │
│ │序号 类型 │ │ ●分开 ○合并 │ │
│ │文件名 大小 │ │ ───────────────── │ │
│ │[删除] │ │ ▌AI总结 │ │
│ │... │ │ 开启总结 ○─ │ │
│ └───────────┘ │ ───────────────── │ │
│ │ ▌输出 │ │
│ │ 推送Notion ○─ │ │
│ │ 推送飞书 ○─ │ │
│ │ 存历史记录 ○─ │ │
│ │ │ │
│ │ ┌──────────────┐ │ │
│ │ │ 开始处理 │ │ │
│ │ └──────────────┘ │ │
└─────────────────┴──────────────────────┴──────────────────────┘
🎵 媒体转文本 [历史记录 🕐] [⚙️ 设置]
- 历史记录:查看所有处理过的记录(需开启「保存到历史记录」开关)
- ⚙️ 设置:配置转写引擎、OSS、API Key、数据库、文件名清洗正则、路径等不常改的参数
- 存 Redis,键为配置项
filename_clean_regex(字符串,默认空)。空表示不清洗,所有展示/落盘名均用原始主名(仅去后缀)。 - 作用范围:对主文件名(不含扩展名)做一次 Python
re处理,得到清洗后名称,用于:title、结果 JSON 与历史里的source_files[].filename、本地audios/与captions/文件名、OSS 键中可读段、Notion/飞书 标题与文件名字段。用户上传的完整原始名(含扩展名)始终写在source_files[].original_filename中,便于追溯。 - 规则摘要:若正则为空或清洗结果为空 → 用原始主名。若正则有捕获组且第一组非空 → 用第一捕获组。若无捕获组 → 将匹配段替换删除后取剩余。匹配失败或非法正则 → 回退原始主名,后端打 warning 日志。
示例(仅作说明,可自由改规则):
| 意图 | 思路 |
|---|---|
| 去掉第一个短横线前的前缀 | 如 ^[^-]*-\s*,UP主名- 视频标题 → 主名 视频标题 |
| 只取中间一段 | 使用带捕获组的表达式,由第一组作为清洗结果 |
- 何时打开:仅当已开启转写时选项可用。源文件为视频时,会先用 FFprobe/FFmpeg 检测并抽取内嵌字幕(如 mkv/mp4 中的文字轨);纯音频无容器字幕轨,将直接走转写。
- 成功时:以字幕为「原文」基础;可按配置再做通义断句与标点,
recognition_type为subtitle(写入结果 JSON 与历史库)。 - 失败或未检出字幕时:与未开「字幕优先」一样,走 FunASR 或 百炼,
recognition_type为funasr或dashscope等。
为了解决平台下载文件名杂乱的问题,系统提供了强大的可视化清洗流水线:
- 固定替换:输入
旧->新(如硬核读财->财务书籍),本次有效,不保存。 - 正则模板库:支持多选持久化模板,按选中顺序依次执行。
- 提取模式:只保留括号
()捕获的内容,其余丢弃。 - 替换模式:将匹配到的内容替换为空或删除。
- 提取模式:只保留括号
- 内置万能模板:提供“提取核心标题”、“删除开头前缀”、“清理末尾残留”、“删除话题标签”、“删除末尾时间戳”等预设。
- 实时日志追踪:后端打印
原文 -> 正则 -> 结果,让清洗过程透明可见。
💡 建议:在上传前先配置好清洗规则,这样生成的
title、OSS 路径和数据库记录都会非常干净。
- 拖拽上传:直接把文件(或多个文件)拖到上传区域松手
- 点击上传:点击上传区域,弹出文件选择框,可用
Ctrl/Cmd + 点击多选
✅ 支持同时上传多个文件,视频音频可以混合
支持的格式:
- 视频:
.mp4.mkv.avi.mov.flv.wmv.webm.ts - 音频:
.mp3.wav.m4a.aac.ogg.flac.opus.amr.wma
上传后文件列表显示:
序号 类型 文件名 大小 操作
1 [视频] 会议录像.mp4 256MB [🗑]
2 [音频] 播客ep12.mp3 45MB [🗑]
3 [音频] 访谈录音.m4a 23MB [🗑]
[清空列表]
在上传区上方选择分类,文件会保存到对应分类目录:
output/
└── 默认分类/
├── audios/ ← 音频文件存这里
└── captions/ ← 转写文本存这里
点 [+ 添加] 新建分类,分类名不可重复,新建后自动切换到新分类。
所有开关实时保存到 Redis,下次打开页面自动恢复上次的配置。
| 配置项 | 说明 | 注意事项 |
|---|---|---|
| 保存音频到本地 | 视频提取的音频(或音频文件)保存到本地 output/{分类}/audios/ |
— |
| 上传音频到 OSS | 上传音频到阿里云 OSS,获得公网 URL | 需在设置里配好 OSS 参数 |
| 开启转写 | 将音频转为文字 | 关闭则只做视频转音频 |
| 保存文本到本地 | 转写结果保存为 .md 文件 |
需先开启「开启转写」 |
| 上传文本到 OSS | 转写的 .md 文件上传 OSS |
需先开启「开启转写」 |
| 批量模式:分开 | 每个文件输出一条记录 | 默认 |
| 批量模式:合并 | 所有文件合并成一条记录 | 需手动填写合并标题 |
| 开启 AI 总结 | 调用大模型生成摘要 | 需先开启「开启转写」,需配置 API Key |
| 推送到 Notion | 处理完成后自动推送到 Notion 数据库 | 需在设置里配置 Notion Token 和 Database ID |
| 推送到飞书 | 处理完成后自动推送到飞书多维表格 | 需在设置里配置飞书参数 |
| 保存到历史记录 | 结果存入数据库,可在历史记录中查看 | — |
选择「合并为一条」时,会出现标题输入框:
批量模式:○ 分开输出 ● 合并为一条 [输入合并标题...]
合并后的文稿格式(Markdown):
# 第一个文件名
第一个文件的转写内容...
---
# 第二个文件名
第二个文件的转写内容...总结时对合并后的全文总结一次(而非每个文件单独总结)。
开启「AI 总结」后出现:
选择模型:[通义千问 ▼]
选择提示词:[默认总结 ▼] [💡 管理提示词]
点击 [💡 管理提示词] 打开提示词管理弹窗:
- 查看所有提示词(标题 + 内容预览)
- 新增提示词:填写标题和内容,
{text}是转写文本的占位符 - 编辑已有提示词
- 删除(「默认总结」不可删除)
内置提示词模板示例:
| 标题 | 适用场景 |
|---|---|
| 默认总结 | 通用摘要 |
| 会议纪要 | 会议录音,提炼决议和待办 |
| 课程笔记 | 课程视频,整理知识点 |
| 播客精华 | 播客节目,提取金句和观点 |
处理过程中,进度列表实时更新:
序号 文件名 当前步骤 进度 状态
1 会议录像.mp4 正在提取音频... ████░ [处理中]
2 播客ep12.mp3 正在转写音频... ██░░░ [处理中]
3 访谈录音.m4a 等待处理... ░░░░░ [等待]
处理步骤说明:
| 步骤 | 说明 |
|---|---|
| 检测文件类型 | 判断视频还是音频 |
| 正在提取音频 | FFmpeg 视频→mp3(视频文件才有此步骤) |
| 保存音频到本地 | 复制到 output 目录 |
| 上传音频到 OSS | 上传并获取公网 URL |
| 正在转写音频 | ASR 识别(可能较慢) |
| 上传文本到 OSS | 上传 .md 文件 |
| AI总结中 | 调用大模型 |
| 推送到 Notion | 写入 Notion 数据库 |
| 推送到飞书 | 写入飞书多维表格 |
| ✅ 处理完成 | 全部步骤完成 |
处理完成后,结果在下方展示(分 Tab):
[会议录像] 字数:2,341字
[原文 Tab] ──────────────────────────────────────
# 会议录像
这里是转写的文字内容,带标点符号...
[复制原文]
[总结 Tab] ──────────────────────────────────────
## 核心内容摘要
- 要点一:...
- 要点二:...
[复制总结]
🔗 音频链接:https://...oss.../audios/xxx.mp3
🔗 文本链接:https://...oss.../captions/xxx.md
顶部工具栏:[复制JSON] [下载JSON文件] [清除结果]
所有结果统一输出为 JSON 数组,每个元素格式如下:
[
{
"title": "产品会议",
"source_files": [
{
"filename": "产品会议.mp4",
"original_filename": "某UP主- 产品会议.mp4",
"audio_oss_url": "https://your-bucket.oss-cn-hangzhou.aliyuncs.com/默认分类/audios/a1b2c3d4_产品会议.mp3",
"caption_oss_url": "https://your-bucket.oss-cn-hangzhou.aliyuncs.com/默认分类/captions/a1b2c3d4_产品会议_transcript.md"
}
],
"captions": "# 产品会议\n\n这里是转写的内容,带有标点符号...",
"summary": "## 摘要\n\n- 核心要点一\n- 核心要点二",
"record_uuid": "a1b2c3d4e5f6789012345678abcdef01",
"recognition_type": "funasr"
}
]| 字段 | 类型 | 说明 |
|---|---|---|
title |
string | 清洗后主名(无扩展名),或合并模式下的合并标题 |
source_files |
array | 来源文件列表 |
source_files[].filename |
string | 清洗后展示用文件名(含扩展名,与 title 所对应主名一致) |
source_files[].original_filename |
string? | 用户上传时的原始全名(含扩展名),用于追溯 |
source_files[].audio_oss_url |
string? | 音频 OSS 公网 URL(开启上传才有值;路径含内容 hash 前 8 位) |
source_files[].caption_oss_url |
string? | 文本 OSS 公网 URL(开启上传才有值) |
captions |
string | Markdown 格式原文 |
summary |
string? | AI 总结内容(开启总结才有值) |
record_uuid |
string | 32 位 UUID,全局唯一标识 |
recognition_type |
string | 识别来源:subtitle(内嵌字幕)/ funasr / dashscope 等;合并记录时由多文件合并规则汇总 |
# 文件一名称
文件一的转写内容...
---
# 文件二名称
文件二的转写内容...- 打开:https://www.notion.so/my-integrations
- 点 New integration
- 填写名称(如
media2text),关联你的工作区 - 复制 Internal Integration Token(格式:
secret_xxxx...)
- 在 Notion 中新建一个全页数据库(Full Page → Database)
- 点右上角 ... → Connections → 添加你刚创建的 Integration
- 从浏览器地址栏复制数据库 ID:
https://www.notion.so/你的工作区/【这里就是数据库ID,32位】?v=xxx
在 Notion 数据库中,按以下顺序创建字段:
| 字段名 | 类型 | 说明 |
|---|---|---|
title |
Title(默认已有,改名即可) | 标题 |
record_uuid |
Rich Text | 唯一标识 |
created_at |
Date | 创建时间 |
updated_at |
Date | 更新时间 |
category |
Select | 分类 |
batch_mode |
Select | 单数据/批数据 |
captions |
Rich Text | 原文(Markdown) |
summary |
Rich Text | AI总结 |
source_files |
Rich Text | 来源文件(JSON) |
💡 快捷方式:启动后端后,访问 http://localhost:8000/api/integrations/schema,会返回所有需要创建的字段和类型,同时在启动日志里也会打印一次。
点页面右上角 ⚙️ 设置 → 找到 Notion 配置:
Notion Token: [secret_xxxxxxxxxxxxx]
Database ID: [a1b2c3d4e5f67890abcdef1234567890] ← 32位无连字符
⚠️ 常见错误:Database ID 必须是 32 位 UUID,不能填数据库名称。
- 打开:https://open.feishu.cn/
- 进入「开发者后台」→「创建应用」
- 填写应用名称,创建完成后记录 App ID 和 App Secret
- 在「权限管理」中开启:
bitable:app(多维表格读写权限)
- 在飞书中新建一个多维表格
- 从 URL 中获取 App Token:
https://feishu.cn/base/【App Token 在这里】?table=tblXXXX - 从 URL 中获取 Table ID:
https://feishu.cn/base/xxx?table=【Table ID 在这里】 - 将应用添加到多维表格的协作者(点右上角「...」→「添加文档应用」)
在飞书多维表格中创建以下字段:
| 字段名 | 飞书类型 | 说明 |
|---|---|---|
title |
文本(主字段) | 标题 |
record_uuid |
文本 | 唯一标识 |
created_at |
日期时间 | 创建时间 |
updated_at |
日期时间 | 更新时间 |
category |
单选 | 分类 |
batch_mode |
单选 | 单数据/批数据 |
captions |
文本 | 原文 |
summary |
文本 | AI总结 |
source_files |
文本 | 来源文件 |
飞书 App ID: [cli_xxxxxxxxxxxx]
飞书 App Secret: [xxxxxxxxxxxxxxxxxxxxxx]
Bitable App Token: [Hxxxxxxxxxxxxxxxxxxxxxx]
Table ID: [tblxxxxxxxxxxxxxx]
| 需求 | 是否需要 OSS |
|---|---|
| 使用本地 FunASR 转写 | ❌ 不需要 |
| 使用阿里云百炼 API 转写 | ✅ 必须(百炼只接受公网 URL) |
| 音频/文本云端备份 | ✅ 需要 |
| 在 Notion/飞书 里显示音频链接 | ✅ 需要 |
- 登录阿里云控制台:https://oss.console.aliyun.com
- 创建 Bucket(选你最近的地域,如
华东1(杭州)) - 将 Bucket 的读权限设为「公共读」(这样百炼 API 才能访问)
- 进入「访问控制 RAM」创建子账号,赋予 OSS 读写权限,生成 AccessKey ID 和 AccessKey Secret
Access Key ID: [LTAI5xxxxxxxxxxxxxxxxxx]
Access Key Secret: [xxxxxxxxxxxxxxxxxxxxxxxxxxxx]
Bucket Name: [your-bucket-name]
Endpoint: [oss-cn-hangzhou.aliyuncs.com]
Endpoint 常用值:
| 地域 | Endpoint |
|---|---|
| 华东1(杭州) | oss-cn-hangzhou.aliyuncs.com |
| 华东2(上海) | oss-cn-shanghai.aliyuncs.com |
| 华北2(北京) | oss-cn-beijing.aliyuncs.com |
| 华南1(深圳) | oss-cn-shenzhen.aliyuncs.com |
填写完成后点 [测试连接] 验证是否配置正确。
- 哈希对象:对用户上传的原始文件在任何 FFmpeg 转码或转写之前计算 SHA-256,取前 8 个十六进制字符(
content_hash8),采用分块读取,大文件不一次性读入内存。 - 可读名段:清洗后的主名经安全化(去除路径危险字符等)后作为显示名。
- Key 模式(
{分类}为当前分类名)- 音频:
{分类}/audios/{content_hash8}_{清洗后主名}.mp3 - 转写稿(合并模式):
{分类}/captions/{组合Hash8}_{合并标题}_transcript.md
- 音频:
- 去重与覆盖:相同原始字节内容 → 相同
content_hash8;若与当前清洗主名组合后的 Key 一致,则多次上传直接覆盖同一对象,不堆积重复文件。上传前日志会包含:计算的哈希、最终 Key。
- 确定性 UUID:系统根据
MD5(Hash+标题)生成 32 位唯一标识。- 单文件:
MD5(单文件Hash8 + 清洗后标题) - 合并模式:
MD5(排序后的多文件Hash拼接 + 合并标题)
- 单文件:
- 数据库 Upsert:保存时先查 UUID,存在则更新,不存在则插入。
- 第三方平台同步:Notion 和飞书均使用该 UUID 作为唯一键,防止产生重复卡片。
- Redis 缓存防抖:处理完成后将各平台 ID 存入 Redis(5分钟)。再次推送时优先查缓存,命中则直接 Update,极大提升速度并规避限流。
点顶部 [历史记录 🕐] 打开弹窗。
前提:处理文件时开启了「保存到历史记录」开关。
[多选框] UUID 时间 分类 标题 模式 类型 原文(截断) 文本OSS AI总结 Notion 飞书 操作
[□] a1b2c3d4 2025-04-24 默认 会议录像 单数据 funasr 这是内容... 已上传|[上传] 已总结|[总结] 已推送|[推送] 未推送|[推送] [查看][复制]
[□] e5f6g7h8 2025-04-23 会议 产品讨论 批数据 subtitle 讨论了... 未上传|[上传] 未总结|[总结] 未推送|[推送] 未推送|[推送] [查看][复制]
顶部操作栏:
[批量删除] [清空历史] [导出Excel(选中/全部)]
所有操作按钮永远显示,可以重复点击:
| 按钮 | 已处理时 | 动作 |
|---|---|---|
| 上传 | 状态显示「已上传」 | 重新上传,覆盖 OSS 原文件 |
| 总结 | 状态显示「已总结」 | 重新调用大模型,覆盖原总结 |
| 推送(Notion) | 状态显示「已推送」 | 根据 UUID 在 Notion 中更新记录 |
| 推送(飞书) | 状态显示「已推送」 | 根据 UUID 在飞书中更新记录 |
点 [查看] 按钮打开详情弹窗,采用 三 Tab:
| Tab | 内容 |
|---|---|
| 原文 | 转写 Markdown 全文、字数与复制;若有多个来源文件,可按文件分块展示。 |
| AI 总结 | 大模型总结(若有),支持复制。 |
| 其它信息 | 元数据(UUID、时间、识别类型 recognition_type、分类、合并模式等)、来源文件列表;每个文件可展示清洗后文件名、原始文件名 original_filename、本地路径、音频 inline 播放与 OSS/文本链接。 |
结构示意(实际以页面为准):
┌──────────────── 记录详情 ──────────────── [ 原文 | AI 总结 | 其它信息 ] ─┐
│ [原文 Tab] # 会议录像 ... [📋 复制原文] │
├──────────────────────────────────────────────────────────────────────┤
│ [其它信息 Tab] 识别类型:funasr | 分类:默认 | 模式:单数据 │
│ 来源:会议录像.mp4 | 原始:某渠道_会议录像.mp4 [▶ 音频] 链接... │
└──────────────────────────────────────────────────────────────────────┘
支持导出选中记录或全部记录为 Excel 文件,字段按以下顺序:
record_uuid → created_at → updated_at → title → category → batch_mode → captions → summary → source_files
Q: 后端启动时报 FFmpeg not found
ERROR | startup | ❌ FFmpeg 未安装,请按以下步骤安装:
Windows: 下载 https://www.gyan.dev/ffmpeg/builds/ 并加入 PATH
macOS: brew install ffmpeg
Linux: sudo apt install ffmpeg
→ 按提示安装 FFmpeg,然后新开终端再启动后端(PATH 变化需要新终端才生效)
Q: 后端启动时报 Redis 连接失败
ERROR | startup | ❌ Redis 连接失败:redis://127.0.0.1:6379/0
请启动 Redis,可使用 Docker:docker compose up -d redis
→ 确认 Redis 是否运行:redis-cli ping,应返回 PONG;检查 .env 中 REDIS_URL 是否正确
Q: FunASR 模型首次下载很慢
→ 模型需从 ModelScope 下载(约 500MB)。可以:
- 等待下载完成(只需一次,缓存在
~/.cache/modelscope/) - 如果网络不好,设置环境变量使用镜像:
export MODELSCOPE_ENVIRONMENT=CN - 临时改用百炼 API,等网络好时再切回本地
Q: 前端启动后访问显示空白页面
→ 检查:
- 后端是否正常运行(访问 http://localhost:8000/docs 是否能打开)
vite.config.js中代理配置是否正确(/api→http://localhost:8000)- 浏览器控制台(F12)是否有报错
Q: 百炼 API 转写失败,返回"无文本内容"
最常见原因:OSS Bucket 未设置公共读权限,百炼无法访问音频文件。
检查步骤:
- 登录阿里云 OSS 控制台
- 进入 Bucket → 权限管理 → Bucket ACL
- 确认读写权限为「公共读」
- 复制一个已上传音频的 URL,在浏览器中直接访问,能下载则权限正确
Q: 百炼 API 返回有数据但 chars=0
→ 这是结果解析问题。百炼 API 返回的是一个 transcription_url(结果文件的下载链接),真正的文字在这个链接的 JSON 文件里,需要二次 GET 请求才能拿到。
检查后端日志,如果看到类似:
INFO | asr_dashscope | task_id=xxx status=SUCCEEDED
INFO | asr_dashscope | chars=0
→ 说明没有正确拉取 transcription_url,检查 asr_dashscope.py 中是否有 GET 下载 JSON 并解析 transcripts[0].text 的逻辑
Q: FunASR 转写结果没有标点符号
→ 检查 asr_local.py 中模型初始化是否包含 punc_model="ct-punc":
# 示例代码(仅供参考,实际代码在 backend/services/asr_local.py 中)
from funasr import AutoModel
model = AutoModel(
model="paraformer-zh",
vad_model="fsmn-vad",
punc_model="ct-punc", # ← 这行不能少
device="cpu"
)Q: FunASR 转写很慢
R7 6800H CPU 的大致速度参考:
| 音频时长 | 大约转写时间 |
|---|---|
| 10 分钟 | 2~5 分钟 |
| 30 分钟 | 5~15 分钟 |
| 1 小时 | 10~30 分钟 |
→ 这是正常现象,CPU 推理比 GPU 慢约 5~10 倍。如果需要更快速度,考虑使用百炼 API。
Q: Notion 推送报错 body.parent.database_id should be a valid uuid
→ Database ID 填写错误。正确的 ID 是 32 位纯 hex 字符,从 Notion 数据库页面 URL 中复制:
https://notion.so/workspace/【32位ID在这里,不包含 ? 后面的部分】?v=xxx
注意:只取 ? 前面的那 32 位,不含 -(系统会自动转换格式)
Q: Notion 推送报错 401 Unauthorized
→ Token 填写错误,或者数据库没有给这个 Integration 授权。
检查:在 Notion 数据库页面 → 右上角 ... → Connections → 确认你的 Integration 在列表中
Q: 飞书推送成功但多维表格里看不到数据
→ 检查:
- 应用是否已添加到多维表格协作者(点右上角「...」→「添加文档应用」→ 选你的应用)
- App Token 和 Table ID 是否正确(从 URL 复制,区分大小写)
- 字段名称是否与推送的 key 完全一致
Q: Docker 全栈模式,后端连不上 Redis
→ 检查 docker-compose.yml 中后端的环境变量是否设置了 REDIS_URL=redis://redis:6379/0(注意不是 127.0.0.1,在 Docker 网络里 Redis 服务名是 redis)
Q: 修改了代码,但 Docker 里没有生效
→ Docker 打包时会 build 镜像,修改代码后需要重建:
make rebuild-backend # 重建后端
make rebuild-frontend # 重建前端Q: FunASR 模型在 Docker 里每次重启都要重新下载
→ 检查 docker-compose.yml 中是否有 volume 挂载模型缓存:
volumes:
- funasr_cache:/root/.cache # 这行必须存在| 场景 | 配置建议 | 预计速度 |
|---|---|---|
| 日常少量转写 | FunASR 本地,PRELOAD_FUNASR=false | 首次慢30秒加载,后续正常 |
| 批量处理(每天数小时音频) | FunASR 本地,PRELOAD_FUNASR=true | 无加载等待 |
| 对速度要求高 | 百炼 API(需 OSS) | 云端处理,速度快 |
| 隐私数据 | FunASR 本地,不开 OSS/Notion/飞书 | 数据不出本地 |
场景一:处理会议录音,存飞书
- 设置弹窗:配置飞书参数
- 主页开关:开启转写 + 开启总结 + 推送飞书 + 存历史记录
- 提示词选择:会议纪要
- 批量上传所有录音文件 → 开始处理
场景二:批量处理课程视频,本地存档
- 主页开关:保存音频到本地 + 开启转写 + 保存文本到本地
- 批量模式:分开输出
- 上传所有视频文件 → 开始处理
- 结果保存在
output/默认分类/下
场景三:处理敏感会议,数据不出内网
- 不配置 OSS、不配置 Notion/飞书、不使用百炼 API
- 转写引擎选本地 FunASR
- 开启保存本地 + 存历史记录
- 一切数据留在本机
如遇文档与实际代码不一致,以代码和启动日志为准。欢迎提 Issue 反馈问题。