Files
opencode-skills/videocut-clip-oral/tips/口误识别方法论.md
2026-02-11 22:02:47 +08:00

271 lines
6.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!--
input: 转录文本 (带时间戳的 JSON)
output: 审查稿
pos: 核心方法论,口误识别和删除决策
架构守护者:一旦我被修改,请同步更新:
1. ../README.md 文件清单
-->
# 口误识别方法论
## 一、识别方法
### ❌ 不要用正则匹配
### ✅ 逐段阅读,逐句检查
每句话问自己:
1. **句子完整吗?** - 残句 = 口误
2. **有重复吗?** - 词语/短语/句子重复
3. **通顺吗?** - 不通顺 = 说错了
### 口误特征
| 特征 | 判断 |
|------|------|
| 残句(没说完) | 一定是口误 |
| 同一内容说两遍 | 删前面保后面 |
| 语义不通顺 | 说错了重说 |
| 多余的字词 | 卡顿/口吃 |
---
## 二、口误类型与删除策略
| 类型 | 示例 | 删除策略 |
|------|------|----------|
| 重复型 | `拉满新拉满` | 只删差异部分("新" |
| 替换型 | `AI就是AI就会` | 删第一个完整版本("AI就是" |
| 卡顿型 | `听会会` | 删第一个重复字 |
### ⚠️ 精确处理步骤
当遇到 `🔴~~错误版本~~正确版本` 时:
**步骤1**:识别口误类型(重复/替换/卡顿)
**步骤2**逐token查时间戳
```python
for i in range(start_idx, end_idx):
gap = timestamps[i][0] - timestamps[i-1][1] if i > 0 else 0
print(f"[{i}] {tokens[i]} @ {timestamps[i][0]/1000:.2f}s" +
(f" ⚠️ gap={gap/1000:.1f}s" if gap > 500 else ""))
```
**步骤3**:确定精确删除边界
- 时间跨度 > 2秒 → 必有静音,需拆分
- 替换型:删第一个完整版本
- 重复型只删差异token
### 案例库
| 口误 | 错误处理 | 正确处理 |
|------|----------|----------|
| `拉满新拉满` | 删40.84-47.69s | 删41.35-47.69s(静音+新) |
| `AI就是AI就会` | 只删"就是" | 删"AI就是"(85.78-86.50s) |
| `听会会` | 删整个"听会会" | 只删第一个"会" |
---
## 三、微口误检测2026-01-15 新增)
### 什么是微口误
不成词的卡顿音,转录检测不到,但听起来不舒服。
| 类型 | 示例 | 特点 |
|------|------|------|
| 起音卡顿 | "呃...你以为" | 开头有杂音 |
| 吞字 | "钉钉A...钉钉AI" | 说到一半重来 |
| 气口声 | 吸气/呼气声 | 换气太重 |
### VAD 检测方法
用 FunASR 的 VAD语音活动检测找出所有发声片段
```python
from funasr import AutoModel
import subprocess
# 提取音频
subprocess.run(['ffmpeg', '-y', '-i', 'video.mp4', '-ss', '0', '-t', '5',
'-vn', '-acodec', 'pcm_s16le', '-ar', '16000', '-ac', '1',
'/tmp/check.wav'], capture_output=True)
# VAD 检测
vad_model = AutoModel(model="fsmn-vad", disable_update=True)
result = vad_model.generate(input="/tmp/check.wav")
for item in result:
if 'value' in item:
for start_ms, end_ms in item['value']:
print(f"[{start_ms/1000:.3f}s - {end_ms/1000:.3f}s] 语音活动")
```
### 输出示例
```
[0.000s - 0.430s] 语音活动 ← 微口误0.71s才是正式语音)
[0.710s - 4.980s] 语音活动 ← 正式语音
```
### 判断规则
| 模式 | 判断 |
|------|------|
| 短语音 + 长静音 + 长语音 | 第一个短语音是微口误 |
| 语音时长 < 0.5s 且后面有静音 | 可能是微口误 |
---
## 三.5、语气词检测2026-01-15 新增)
### 什么是语气词
转录能识别,但属于多余的过渡音,删除后更流畅。
| 类型 | 示例 | 特点 |
|------|------|------|
| 过渡词 | "嗯"、"啊" | 句子之间的填充 |
| 感叹词 | "哎"、"诶"、"唉" | 无意义感叹 |
| 犹豫音 | "呃"、"额" | 思考时发出 |
### 检测方法
```python
# 语气词列表
filler_words = ['', '', '', '', '', '', '', '', '', '', '']
# 扫描转录结果
for i, item in enumerate(all_chars):
if item['char'] in filler_words:
# 获取上下文
prev_char = all_chars[i-1] if i > 0 else None
next_char = all_chars[i+1] if i < len(all_chars)-1 else None
print(f"[{item['start']:.2f}s] \"{item['char']}\"")
print(f" 上下文: {prev_char['char']}{item['char']}{next_char['char']}")
```
### ⚠️ 删除边界要精确
```
错误:删语气词的时间戳 (语气词.start - 语气词.end)
→ 可能删掉前面字的尾音
正确:从前一个字的 end 到后一个字的 start
→ (前字.end - 后字.start) 包含静音+语气词
```
### 案例模式
| 上下文 | 错误删除 | 正确删除 |
|--------|----------|----------|
| "A [静音] 语气词 B" | 只删语气词时间戳 | 删 "A.end - B.start" |
| "A 语气词 B" | 删语气词时间戳 | 删 "A.end - B.start" |
---
## 四、静音段
### 阈值规则
| 静音长度 | 处理 |
|---------|------|
| < 1秒 | **忽略** - 自然停顿 |
| ≥ 1秒 | 建议删除 |
| 开头 > 1秒 | 建议删除 |
### 识别方法
```python
# 开头静音
if timestamps[0][0] > 1000:
print(f"开头静音 {timestamps[0][0]/1000:.1f}s")
# 句间静音
for i in range(len(timestamps) - 1):
gap = timestamps[i+1][0] - timestamps[i][1]
if gap >= 1000:
print(f"静音 {gap/1000:.1f}s @ {timestamps[i][1]/1000:.1f}s")
```
---
## 五、审查稿格式(时间戳驱动)
```markdown
# 口误审查稿
视频01-xxx-v1.mp4
---
【正文】
⏸️[1.36s @ 0.00-1.36]
🔴~~你以为今天a~~(1.36-2.54)你以为钉钉AI录音卡...
---
【删除任务清单】
**口误3处**
- [ ] 1. `(1.36-2.54)` 删"你以为今天a" → 保留"你以为钉钉"
- [ ] 2. `(47.55-47.69)` 删"新" → 保留"拉满"
- [ ] 3. `(85.78-86.50)` 删"AI就是" → 保留"AI就会"
**静音2处**
- [ ] 1. `(41.35-47.55)` 静音6.2s
- [ ] 2. `(0.00-1.36)` 开头静音
```
**关键**
- 删除项用 `(start-end)` 格式
- 剪辑脚本直接用时间戳,不搜索文本
---
## 六、FunASR 时间戳对齐
### Token规则
| 元素 | 时间戳 |
|------|--------|
| 中文字符 | 每字1个 |
| 英文单词 | 整词1个`agent` 算1个 |
| 标点/空格 | 无时间戳 |
### Token化函数
```python
def tokenize(text):
tokens = []
i = 0
while i < len(text):
char = text[i]
if '\u4e00' <= char <= '\u9fff': # 中文
tokens.append(char)
i += 1
elif char.isascii() and char.isalpha(): # 英文
word = ''
while i < len(text) and text[i].isascii() and text[i].isalpha():
word += text[i]
i += 1
tokens.append(word)
else:
i += 1
return tokens
```
---
## 七、验证清单
- [ ] 删的是前面版本?
- [ ] 保留的文本完整通顺?
- [ ] 删除后不会产生新的重复?
- [ ] 时间戳精确到小数点后两位?