EXP-06 · 第 2 章 · 综合性 · 4 学时

多模态语音情绪感知

EXP-05 让机器人听懂了"你说什么",本实验补上最后一块拼图——"你是怎么说的":文本情绪与语音韵律双通道并行分析、融合判情,让助手与客服应用具备情绪感知能力。

文本六分类情绪 韵律 · 音量 · 语速 双模态融合 情感助手 · 客服场景

01问题引入:听懂"字面"还要听懂"语气"

设想客服机器人收到这句话——ASR 识别正确、意图分类正确,但场景翻车了:

1
"呵呵,你们可真行。"
字面:中性偏夸;语气:愤怒讽刺。
→
2
机器人:"谢谢夸奖!"
火上浇油,用户挂断投诉。
→
3
缺的是情绪感知
人听话时,字面与语气同时解码。

再看三个只有"单通道"会翻车的例子:

用户表现只看文本加上语音韵律
"我没事"(哽咽、低音量、慢语速)判定:没事判定:悲伤,需安抚
"好的好的,快点吧!"(语速急、音量高)判定:配合判定:不耐烦/愤怒前兆
"太棒了……"(拖长、降调、无起伏)判定:开心判定:无奈/失望(反讽)
💡 本节要点情绪 ≠ 关键词命中。情绪分布在两个通道:文本说"内容情感",语音说"当下状态"。两条通道都到齐,才能接近人类的"听话听音"。

这套"多通道并行、汇入统一大脑"的思路在多模态模型里已经落地——下图是视觉语言模型(VLM)的两条输入路线:纯文字直接进语言模型,图片则先经预处理与视觉编码器提取特征,再与文本一起汇入语言模型生成回答。本实验把同样的架构换成"文本 + 语音韵律"双通道:

VLM 流程图解:纯文字路线与上传图片路线汇入语言模型
图 1-1:多模态输入的两条路线 —— 路线① 纯文字 prompt 直接进入语言模型(rkllm · NPU);路线② 上传图片先经预处理(补边到 448²)与视觉编码器(rknn · NPU)提取 196×2048 图像特征,再与文本汇合生成回答。与本实验同理:多一条通道,就多一份"言外之意"的证据。

02原理通俗讲解:品酒师的两条舌头

把情绪识别想成品酒:好品酒师同时用两条线索——看酒标(成分表:文字)与品味(单宁、酸度、回甘:韵律)。只看酒标会把"干红"当成"干",只凭味觉又抓不住年份品种。对应到技术:

生活比喻技术模块通俗解释
看酒标成分表文本情绪通道对 ASR 文本做六分类:积极 / 消极 / 中性 / 愤怒 / 开心 / 悲伤。入门用情感词典("太棒了"+2、"烦死"-2),进阶交给 NLP 分类器。
品味:酸度高=尖锐语音韵律通道音高 F0 高而抖→激动或紧张;音量(能量)大→愤怒/兴奋;语速快→焦虑不耐烦,慢且停顿多→低落。
调酒师按比例勾兑双模态融合两条通道各出一个分数,加权合并:置信度高的通道话语权更大;或决策级——两通道投票一致才输出。
最终给酒打的星级情绪标签 + 坐标输出六分类标签,同时落到"效价-唤醒度"二维坐标:开心=正效价高唤醒,悲伤=负效价低唤醒。

回到整条语音管线(最后一站):

1
拾音
16kHz 波形(韵律就藏在这里)
→
2
唤醒
会话起点
→
3
识别
ASR 文本 → 文本通道 ★
→
4
理解+回复
EXP-05 意图/槽位 + 情绪标签一起进上下文 ★
→
5
合成
TTS 按情绪调语速音高(呼应 EXP-03 参数)

语音通道的三个特征怎么算(都是"每句话一段统计量"):

特征生活读法典型信号
基频 F0(音高)嗓音"往上翘"还是"沉下去"均值升高 + 起伏大 → 激动/愤怒;压低变平 → 悲伤/压抑
音量 RMS(能量)说话"多大声"持续偏高 → 愤怒/兴奋;骤降 → 失落
语速(字率/停顿)说得多急、停多久字率高停顿短 → 焦急;字率低长停顿 → 低落或迟疑
🎯 核心直觉文本通道擅长"判类别"(哪个词刺痛了人),语音通道擅长"判强度"(此刻有多上头)。融合 = 用文本定性、用韵律定量。

03关联知识点

📝
文本六分类

积极 / 消极 / 中性 / 愤怒 / 开心 / 悲伤。可用情感词典+规则打分入门,也可接 NLP 分类器或让 LLM 按标签白名单输出。

🎵
韵律三件套

基频 F0、音量 RMS、语速/停顿——从波形直接统计,不依赖语义;对录音增益与麦克风距离敏感,需归一化。

📐
效价-唤醒度坐标

横轴效价(负→正),纵轴唤醒(低→高):开心=(+,高)、愤怒=(−,高)、悲伤=(−,低)、平静=(中,低),把离散标签连成连续空间。

🔗
双模态融合策略

分数级加权(w·text+(1−w)·voice)或决策级投票;冲突时(反话、反讽)可提高语音通道权重或标"低置信"交给人。

🗣
情绪感知的下游

情绪标签随 context 进 LLM,让回复语气随之调整;TTS 端呼应 EXP-03 的 --speed/音高参数改变播报风格。

💼
应用场景

情感助手(陪伴、提醒时察言观色)、智能客服(升级投诉预警、安抚话术切换)——情绪是服务类机器人的核心 KPI。

04实验目标

  • 掌握文本情绪分析:基于情感词典/规则对 ASR 文本输出积极/消极/中性/愤怒/开心/悲伤六类标签(分类实操)
  • 理解文本分类与实体抽取同源——都属于把自然语言映射到受控词表(概念关联)
  • 掌握语音情绪分析:从波形提取韵律、音量、语速特征并给出通道判情(特征实操)
  • 实现双模态情绪融合:分数级加权可调,能演示文本/语音冲突样例的融合差异(融合实操)
  • 能把情绪标签接入 EXP-05 的对话上下文,设计"情绪感知的助手/客服"应答策略(集成应用)
  • 理解情绪输出与 TTS 播报风格的联动(衔接 EXP-03),完成闭环设计(迁移应用)

05实验环境与准备

类别配置
硬件具身智能实验箱 B2(RK3576)+ 讯飞六麦阵列(复用 EXP-01~02 录音链路)
复用模块sherpa-onnx ASR(EXP-02 出文本)、llm_server/llm_test(EXP-05 出语义与标签)、Matcha-TTS(EXP-03 调风格)
文本通道情感词典(中文程度词/否定词/标点权重)+ 六分类白名单,Python 纯实现起步
语音通道16kHz 单声道波形窗口(约 2~4s/句),统计 F0 近似、RMS 能量、字率与静音比
素材courses/sheet1/speech_practice/ 下实验讲义与样例(exp06 为设计性素材,需按课堂场景修改)
# 0) 前置就绪检查(三站分别是 EXP-02 / EXP-05 主命令)
python3 asr_test.py --mic-array   # 文本通道原料:ASR 文本
python3 llm_test.py --prompt "你好"  # LLM 连通(可承担 text 分类器)
# 1) 录一段情绪样本(平静/愤怒/悲伤/开心 各 1 条)
arecord -D plughw:4,0 -r 16000 -f S16_LE -c 1 -d 3 angry.wav
✅ 准备检查语音通道统一在同一增益下录音——后续"音量"特征是相对比较,增益变了绝对 RMS 全变。先用 amixer(audio_utils.py 已有工具)固定采集增益再采样本。

06动画讲解:双模态情绪融合

观察一句话的两条命运线:文本通道连到词典/分类器,语音通道抽出韵律三特征,两路分数在融合器按权重合并,最终落点在右侧"效价-唤醒度"情绪坐标上(4 秒循环,看紫色融合点的迁移轨迹):

同一句 "我没事" 文本通道 情感词典 + 六分类 → 中性/积极 (+0.2) 语音通道 F0↓ RMS↓ 语速↓ → 悲伤/低落 (−0.6) 双模态融合器 w·text + (1−w)·voice w=0.5 冲突则降置信 效价 + 唤醒 + 愤怒 开心 悲伤 平静 冲突时输出"悲伤(低置信)"并将标签写入 LLM 上下文,回复语气随之下沉
动画 6-1:双模态情绪融合与效价-唤醒度落点(4 秒循环)——同一句"我没事",文本通道判中性偏正、语音通道判低落,融合器按权重合并后,紫色点从"开心/平静"象限滑向"悲伤"象限:韵律揭穿了字面的逞强。随后该情绪标签进入 LLM 上下文,决定回答的语气与 TTS 风格。

07互动讲解:情绪融合权重台

三个样例 + 两组权重,亲手复现"字面 vs 语气"冲突时融合结果如何翻转:

情绪融合权重台 · Fusion Mixer
$ 就绪:选择样例与文本通道权重 w(0=全听语气,1=全看字面)…
🔍 观察点同一句"我没事",w=0.5 时两通道拉锯输出"中性(低置信)";降到 w=0.2(更信语气)则翻转为"悲伤"。真实系统的自适应融合正是按通道置信度动态调 w——文本含明确情绪词时信文本,文本空泛("哦""嗯")时信韵律。

08实操步骤

1
采情绪样本 + 固定录音增益
→
2
实现文本六分类(词典打分起步)
→
3
实现韵律三特征与语音通道判情
→
4
融合输出 + 接入对话/TTS 闭环

步骤 1:采集四类样本(每类 3 条起,安静环境 + 远近各一条):

arecord -D plughw:4,0 -r 16000 -f S16_LE -c 1 -d 3 samples/angry_01.wav
arecord -D plughw:4,0 -r 16000 -f S16_LE -c 1 -d 3 samples/sad_01.wav
# 真实语料优先用 EXP-02 链路边说边存:唤醒 → 朗读情绪句 → 得 (wav, text) 对

步骤 2:文本通道——程度词/否定词加权的情感词典打分(课堂实现骨架):

LEX = {"棒": +2, "喜欢": +1.5, "烦": -2, "太": 1.5, "不": -1}
def text_score(s):
    # 遍历命中词 → 前置程度词加倍、前置否定词取反 → clip 到 [-3, +3]
    # 分数段映射六类: >1.5 开心, >0.3 积极, >-0.3 中性, >-1.5 消极, >=愤怒词 愤怒, 否则 悲伤

# 或直接委托 LLM(白名单约束,承接 EXP-05 的 system prompt 手法):
"你是情绪标注员,只输出: 开心|悲伤|愤怒|积极|消极|中性"

步骤 3:语音通道——对样本波形统计三特征并归一化打分:

# F0 均值/方差(基频轨迹近似)、RMS 平均能量、字率与静音占比
# 归一化到该说话人基线后映射: 高能量+高语速 → 愤怒(+强度)
#                             低能量+慢语速+F0平 → 悲伤; 温和起伏 → 开心

步骤 4:融合与闭环——分数级加权后与 EXP-05/03 打通:

final = w*text + (1-w)*voice   # 冲突(异号)则 confidence *= 0.5
# 标签写入 LLM 上下文 → 回复语气调整:
"用户当前情绪:悲伤。回复更温和简短,先安抚再解决。"
# 播报风格呼应 EXP-03 参数(稍慢、降增益):
python3 tts_test.py --text "别急,我们马上帮您处理。" --gain 1.5
⏱ 预期效果四类样本通道准确率各 ≥ 70%(词典起步水平);冲突样例(反话/逞强)在 w 调整后输出翻转;助手场景中情绪标签可见于 LLM 请求 messages[0]。

09重点与易错点

⚠️ 高频故障情绪是最"软"的任务,坑不在报错而在悄悄出错:增益没固定、基线没归一、标签不平衡——四条通道全绿但主观准确率很差时,先查下面这张表。
现象原因解决
音量特征全部偏高,区分不出愤怒录音增益/AGC 每次不同固定 amixer 增益采样;RMS 用相对说话人基线而非绝对值
"我没事"类逞强句全判中性只用文本通道文本空泛时提高语音权重;冲突即降置信并按韵律裁决
反讽"太棒了……"判成开心词典无语气感知结合降调/拖长(F0 下滑、语速↓)触发反讽规则或交给 LLM 综合裁决
否定句情感翻转错误("不喜欢")词典未处理否定窗口否定词作用域覆盖其后 2-3 个词;双重否定取反后再取反
愤怒/开心召回极低样本六类不平衡(中性占多数)每类等量采样;评测用 per-class 召回而非整体准确率
远近说话人分数不可比F0/能量未归一按说话人做 z-score 归一,或会话首轮先"校准 5 秒"采基线
标签接进 LLM 后回复更怪了system prompt 冲突或标签写错位置情绪标签放 messages[0] 人设之后,限定语气指引而非硬性台词
  • 先做单通道各自可信的评测,再谈融合——融合救不了两个都不准的通道。
  • 每个测试句固定"文本 + 波形"成对存档,回归测试时两通道一起复跑。
  • 输出永远带置信度;低置信交由澄清话术("听起来您有点着急,是吗?")比硬猜更稳。
  • 别忘了闭环:情绪的最终消费方是回复语气与 TTS 风格,而不是一张打印的表格。

10总结与思考

🏁
完成成果

四类情绪样本库;文本六分类 + 韵律三特征双通道流水线;可调权重的分数级融合器;情绪标签接入 LLM 上下文的助手/客服 demo。

🧠
原理收获

文本定类别、韵律定强度的互补关系;效价-唤醒度二维模型如何统一六标签;冲突降置信的融合安全观。

🛠
技能收获

情感词典构建与否定/程度处理、声学特征归一化评测、按说话人基线校准、低置信澄清式交互设计。

🎓
课程收官

至此 拾音→唤醒→识别→理解→回复→合成 六站全部点亮:机器人不仅听懂字面,还能听出语气、答得合时。

💭 思考题

1. 双模态"分数级加权"与"决策级投票"两种融合策略各有何代价?当文本与韵律结论冲突(反讽/逞强)时,你的融合器应该输出什么而不仅仅是一个标签?

2. 若把情绪标签注入 system prompt 让 LLM 改变回复语气,可能引入哪些新问题(如过度讨好、误判放大)?如何用置信度门槛与澄清话术缓解?结合作感助手/客服场景说明。