项目概述
「吴话可说」是一个面向吴语戏剧(如越剧、瓯剧、温州鼓词等)的 AI 解析平台。用户上传音视频后,系统通过语音转写、机器翻译、文本情感分析与数据分析可视化,将吴语台词转化为带时间轴、发言人、普通话/英文对照、情感标签的结构化数据, 并自动生成场景、剧情梗概与角色表,降低非吴语观众与研究者理解地方戏曲的门槛。
关键指标
样例台词段数
66
场景数
4
样例时长
25:44
支持情感标签
3
positive / neutral / negative
关键技术应用
1. 机器翻译:吴语 → 普通话 + 英文
调用 qwen3.7-max 对转写后的吴语台词进行批量翻译,同时补充文化典故注释。 由于戏剧台词口语化、押韵且含大量地方俗语,模型被提示保留戏剧语境, 输出严格的 JSON 数组以便直接写入数据库。
def translate_segments(segments: List[Segment]) -> None:
batch_size = settings.translation_batch_size
for i in range(0, len(segments), batch_size):
batch = segments[i : i + batch_size]
lines_text = "\n".join(
f"{idx + 1}. {seg.speaker + ':' if seg.speaker else ''}{seg.wu_text}"
for idx, seg in enumerate(batch)
)
prompt = f"""你是一位资深的吴语戏剧翻译。...
3. 判断每句台词的情感倾向,只能取 positive / neutral / negative 之一。
4. 输出严格的 JSON 数组... 每项字段:mandarin, english, notes, sentiment。
..."""
content = _call_qwen([{"role": "user", "content": prompt}], max_tokens=8192)
translations = _extract_json(content)
for seg, trans in zip(batch, translations):
seg.mandarin_text = str(trans.get("mandarin", "")).strip() or None
seg.english_text = str(trans.get("english", "")).strip() or None
seg.notes = str(trans.get("notes", "")).strip() or None
raw_sentiment = str(trans.get("sentiment", "neutral")).strip().lower()
seg.sentiment = raw_sentiment if raw_sentiment in {"positive", "neutral", "negative"} else "neutral"2. 文本情感分析:逐句情感标注
在翻译阶段同步要求模型判断每句台词的情感倾向(positive / neutral / negative), 将结果写入 Segment.sentiment 字段。该设计不增加额外模型调用, 同时满足大作业对「文本情感分析」关键技术的要求。
positive
恩情、团圆、喜悦
neutral
叙述、场景描写
negative
冲突、磨难、拆散
3. 数据分析与可视化呈现
后端基于 Segment / Scene 数据计算发言者统计、情感分布、时间轴密度、场景情感走势; 前端使用 recharts 渲染为可交互图表,集成在作品详情页的「分析」Tab 中。
def compute_work_analytics(segments, scenes, duration_seconds):
total_segments = len(segments)
speaker_counter = Counter()
speaker_seconds = defaultdict(float)
for seg in segments:
speaker = seg.speaker or "未知"
speaker_counter[speaker] += 1
speaker_seconds[speaker] += seg.end_seconds - seg.start_seconds
sentiment_counter = Counter(_safe_sentiment(seg.sentiment) for seg in segments)
minutes = max(1, math.ceil(duration_seconds / 60))
timeline_density = [
{"minute": m + 1, "count": sum(
1 for seg in segments
if seg.start_seconds < (m + 1) * 60 and seg.end_seconds > m * 60
)}
for m in range(minutes)
]
return { ... }<ResponsiveContainer width="100%" height="100%">
<PieChart>
<Pie data={sentimentData} dataKey="count" nameKey="name" ...>
{sentimentData.map((entry, idx) => (
<Cell key={idx} fill={entry.fill} />
))}
</Pie>
<Tooltip /><Legend />
</PieChart>
</ResponsiveContainer>项目结构
wuhua-keshuo/
├── backend/
│ ├── app/
│ │ ├── main.py # FastAPI 入口
│ │ ├── models.py # SQLAlchemy ORM
│ │ ├── schemas.py # Pydantic 模型
│ │ ├── routers/works.py # 作品 API
│ │ └── services/
│ │ ├── audio.py # 音频提取/切片
│ │ ├── transcribe.py # mimo-v2.5 转写 + 解析
│ │ ├── translate.py # qwen 翻译 + 情感分析
│ │ ├── pipeline.py # 后台处理流程
│ │ └── analytics.py # 数据分析统计
│ └── scripts/
├── frontend/
│ ├── app/ # Next.js App Router
│ │ ├── page.tsx # 首页
│ │ ├── works/[id]/page.tsx # 作品详情
│ │ └── report/page.tsx # 项目汇报页(本页)
│ ├── components/ # React 组件
│ │ ├── analytics-panel.tsx # 数据可视化面板
│ │ ├── work-detail.tsx
│ │ └── ui/ # shadcn/ui
│ └── public/slides/ # HTML PPT
├── deploy/ # nginx / systemd 配置
├── REPORT.md # 供报告 Agent 使用的源文档
└── AGENTS.md # 项目约定与操作指南样例数据
| 时间 | 发言人 | 吴语原文 | 普通话翻译 | 情感 |
|---|---|---|---|---|
| 00:12 | 演唱者 | 白娘子,许仙,二人恩情重。 | 白娘子与许仙,两人的恩情深厚。 | 积极 |
| 03:45 | 演唱者 | 法海禅师心太狠,拆散鸳鸯。 | 法海禅师心肠太狠,拆散了一对恩爱夫妻。 | 消极 |
| 07:20 | 念白者 | 水漫金山,只为救夫。 | 水漫金山,只为救出丈夫。 | 中性 |
| 12:05 | 演唱者 | 夫妻二人,受尽磨难。 | 夫妻二人,受尽磨难。 | 消极 |
| 18:33 | 演唱者 | 天地有情,终得团圆。 | 天地有情,二人终得团圆。 | 积极 |
可视化结果
在作品详情页「分析」Tab 中,系统实时渲染以下图表:
- 情感分布饼图:展示积极 / 中性 / 消极台词的占比。
- 角色发言次数/时长柱状图:对比各角色戏份。
- 时间轴密度折线图:观察剧情节奏分布。
- 场景情感走势柱状图:揭示剧情情绪起伏。