it2023049/chat-screenshot-and-audio-to-csv-extractor
GitHub: it2023049/chat-screenshot-and-audio-to-csv-extractor
一个用于将聊天截图与音视频证据批量提取并转换为标准化 CSV 记录的数字取证工具。
Stars: 0 | Forks: 0
# KModelC-Griphia 聊天与音频转 CSV 提取器
一个 Python 工具包,用于从聊天截图、截图拼图、语音消息和通话录音中提取通讯证据,并将结果转换为标准化的 CSV 记录。
该流程支持:
- Facebook Messenger 截图和截图拼图
- Viber 截图和截图拼图
- MOSS 转录后端支持的音频和视频文件
- 用于集成处理的 ZIP 压缩包输入
- 用于本地开发的文件夹输入
- 单张图片聊天提取
- 独立音频转录与说话人归属
- 截图的自动平台路由
- 递归证据发现
- 压缩包内的自动案件报告发现
- 跳过不支持、非聊天或未知图片
- 结合案件意识的发送者和接收者归属
- 按时间顺序合并聊天记录,随后追加音频行
- 每个压缩包或文件夹生成一份合并的 CSV 记录
最终的记录格式为:
```
"Time","Sender","Receiver","Message"
"DD/MM/YYYY HH:MM:SS","Sender Name","Receiver Name","Message text"
"","Audio Sender","Audio Receiver","Transcribed audio text"
```
## 概述
该项目包含四个主要组件。
### 1. 共享聊天提取工具
`chat/extractor_utils.py` 提供以下共享功能:
- 案件报告解析
- 参与者提取
- 保守的参与者姓名验证
- 截图与拼图分割
- OCR 文本块解析
- 时间戳标准化
- 气泡侧边处理
- 消息清理
- 重复检测
- 发送者和接收者证据评分
- 对话级别的侧边映射验证
- CSV 生成与后处理
### 2. 特定平台的聊天提取器
特定平台的聊天处理流程包括:
- `chat/facebook_extract.py`
- `chat/viber_extract.py`
每个提取器读取一张截图或拼图,生成匿名的 `LEFT`/`RIGHT` 消息行,确定固定的参与者映射,并写入最终的发送者/接收者 CSV。
### 3. 音频转录与归属
音频处理流程包括:
- `speech/audio_diarize.py`
- `speech/audio_utils.py`
MOSS 用于转录和匿名说话人分离。随后,受限的 Ollama 模型会利用案件报告、转录证据、文件名来源以及验证过的案件上下文,分配发送者和接收者身份。
### 4. 批量编排
`chat/mass_extract.py` 提供集成的压缩包和文件夹处理功能。
它会:
- 发现案件报告
- 安全地解压 ZIP 压缩包
- 递归扫描支持的证据
- 将聊天截图分类为 Facebook Messenger 或 Viber
- 跳过不支持和非聊天的图片
- 运行匹配的聊天提取器
- 在存在音频证据时运行音频处理流程
- 按时间顺序合并带日期的聊天行
- 追加无日期的音频行
- 可选择写入 JSON 运行清单
## 归属策略
发送者和接收者归属是在对话级别执行的,而不是为每一行独立猜测姓名。
### 聊天归属
对于聊天截图,处理流程首先使用以下内容推导出临时的固定 `LEFT`/`RIGHT` 映射:
- 平台布局
- 气泡几何形状
- 气泡颜色(如果可用)
- 标题文本
- 联系人或电话证据
- 报告参与者
- 从提取的对话中获取的证据
然后,根据案件报告和从图片或拼图中提取的完整消息集,对该临时映射进行验证。
在接受 LLM 辅助的映射修正之前,会先评估确定性证据。
强证据的示例包括:
- 前导说话人标签,例如 `Casey Advisor: ...`
- 自我身份识别,例如 `This is Casey Advisor`
- 直接称呼,例如 `Hello Jordan`、`Jordan, ...` 或 `Oh Alex`
- 确切的联系人或标题证据
- 多条消息间一致的对话结构
第三方措辞将单独处理。例如:
```
I spoke with Alex.
Jordan told me about the payment.
```
这种措辞不会自动使 Alex 或 Jordan 成为当前消息的发送者或接收者。
参与者姓名只能从经过验证的人类姓名候选者中选出,这些候选者来自:
- 结构化的案件报告字段
- 基于报告的保守姓名提取
- 临时侧边映射
- 消息内明确的姓名自我识别
一旦接受,该参与者配对将在该图片或拼图中保持固定。发送者和接收者通常遵循已接受的 `LEFT`/`RIGHT` 映射。
仅当存在强确定性线索(如准确的前导说话人标签或明确的自我身份识别)证明该指定参与者是发送者时,单行记录的方向才可能被反转。此修正仅限于同一已接受的两人配对。
Ollama 模型被限制在预先排序的候选映射中。不允许其捏造组织作为参与者,将多个身份合并为一个值,或逐行随意选择不相关的参与者。
当证据不足时,将保留临时的几何形状和标题映射。
### 音频归属
对于音频证据,处理流程结合了:
- MOSS 生成的匿名说话人标签
- 明确的自我身份识别
- 直接称呼
- 案件报告中的确切参与者姓名
- 文件名来源
- 验证过的案件交互图谱
- 相关的时间线和通讯阶段上下文
- 受限的 LLM 归属
- 确定性后验证
对于单人语音消息,可以通过自我身份识别或文件名来源识别出发声者。未发声的接收者则根据直接称呼、交互证据和匹配的案件阶段保守推断。
仅仅作为第三方被提及的人,不会自动被选为接收者。
在写入 CSV 之前,最终身份会被规范化。完整的或被截断的尾部括号别名将被移除。例如:
```
Alex Example (A. Example
```
将被写入为:
```
Alex Example
```
## 前置条件
- Python 3.10 或更高版本
- 已安装 Ollama 并在 `PATH` 中可用
- Ollama 模型,例如 `gemma3:12b`
- 与所选 CPU 或 GPU 环境兼容的 PyTorch
- 用于聊天提取的 EasyOCR 和 OpenCV
- 用于本地音频处理的 MOSS Transcribe-Diarize 包
- 为了实现实用的视觉模型和本地 MOSS 推理,推荐使用 GPU
## 安装说明
克隆仓库并进入其根目录:
```
git clone https://github.com/it2023049/chat-screenshot-and-audio-to-csv-extractor.git
cd chat-screenshot-and-audio-to-csv-extractor
```
创建并激活虚拟环境:
```
python3 -m venv .venv
source .venv/bin/activate
```
对于 CUDA 环境,请安装与可用 CUDA 运行时兼容的 PyTorch 版本。
然后安装声明的项目依赖项:
```
python3 -m pip install --upgrade pip
python3 -m pip install -r requirements.txt
```
典型的聊天依赖项包括:
```
opencv-python-headless
easyocr
numpy
ollama
PyPDF2
```
典型的音频依赖项包括:
```
torch
transformers
accelerate
soundfile
requests
```
MOSS Transcribe-Diarize 包直接从其 GitHub 仓库通过 `requirements.txt` 安装。
如果由于特定环境的 PyTorch 或 CUDA 要求导致安装失败,请先安装兼容的 PyTorch 版本,然后重新运行:
```
python3 -m pip install -r requirements.txt
```
有关确切支持的包版本和模型要求,请遵循 MOSS 项目说明。
## Ollama 设置
拉取默认的 Ollama 模型:
```
ollama pull gemma3:12b
```
检查模型是否可用:
```
ollama list
```
启动 Ollama 服务器:
```
ollama serve
```
也可以通过以下方式提供 Ollama 主机:
```
export OLLAMA_HOST=http://127.0.0.1:11434
```
## 依赖检查
检查主要的聊天依赖项:
```
python3 -c "import cv2, easyocr, ollama, PyPDF2, numpy; print('chat dependencies ok')"
```
在不启动真实转录的情况下检查音频后端:
```
python3 speech/audio_diarize.py placeholder.wav \
--case-report placeholder.txt \
--check-deps
```
依赖项检查不会处理占位符输入。
## 项目结构
```
chat-screenshot-and-audio-to-csv-extractor/
├── README.md
├── LICENSE
├── requirements.txt
├── chat/
│ ├── mass_extract.py # Batch package/folder orchestrator
│ ├── facebook_extract.py # Facebook Messenger extraction pipeline
│ ├── viber_extract.py # Viber extraction pipeline
│ └── extractor_utils.py # Shared chat helper functions
└── speech/
├── audio_diarize.py # MOSS transcription and LLM attribution pipeline
└── audio_utils.py # Shared audio and identity utilities
```
以下文件必须保持在 `chat/` 目录内:
```
mass_extract.py
facebook_extract.py
viber_extract.py
extractor_utils.py
```
以下文件必须保持在 `speech/` 目录内:
```
audio_diarize.py
audio_utils.py
```
使用此仓库结构,`chat/mass_extract.py` 会自动解析:
```
chat/facebook_extract.py
chat/viber_extract.py
chat/extractor_utils.py
speech/audio_diarize.py
speech/audio_utils.py
```
因此,对于标准布局,不需要 `--facebook-script`、`--viber-script` 和 `--audio-script`。
仅当脚本存储在自定义位置时才需要使用它们。
## 输入数据
主要的集成输入是一个 ZIP 压缩包或文件夹,包含:
- PDF 或 TXT 格式的案件报告或案件概述
- 一张或多张 Facebook Messenger 或 Viber 截图
- 可选的音频或视频证据文件
### 支持的图片扩展名
```
.png
.jpg
.jpeg
.webp
.bmp
.tif
.tiff
```
### 支持的音频和视频扩展名
```
.mp3
.wav
.m4a
.aac
.flac
.ogg
.opus
.wma
.mp4
.mkv
.mov
```
### 支持的案件报告扩展名
```
.pdf
.txt
```
案件报告用于:
- 识别有效的人类参与者
- 恢复别名和联系方式
- 了解角色和通讯关系
- 约束发送者和接收者归属
- 提供时间线和案件阶段背景
- 生成转录热词
- 区分积极参与者和仅被提及的第三方
## 输出格式
所有最终合并的 CSV 记录均使用此表头:
```
"Time","Sender","Receiver","Message"
```
### 聊天时间戳
聊天时间戳格式:
```
DD/MM/YYYY HH:MM:SS
```
时间戳行为:
- Viber 记录保留可见的单条消息时间,并添加 `:00` 作为秒数。
- Facebook Messenger 记录使用可见的截图时间作为第一行的时间。
- 当 Messenger 不显示具体的秒数时,随后的记录将获得确定性递增的秒数,以保留可见的消息顺序。
示例:
```
"Time","Sender","Receiver","Message"
"12/03/2026 10:15:00","Alice Example","Bob Example","Hello Bob."
"12/03/2026 10:15:01","Bob Example","Alice Example","Hi Alice."
```
### 音频时间戳
音频行在最终合并的 CSV 中目前使用空的 `Time` 字段:
```
"","Alice Example","Bob Example","Transcribed voice-message text."
```
独立音频输出可能会保留时间、匿名说话人标签和详细的归属元数据。
## 快速开始
以下所有命令均假定当前工作目录为仓库根目录:
```
kmodelc-griphia-extractor/
```
### 推荐的压缩包模式
处理包含报告和证据的单个 ZIP 压缩包:
```
python3 chat/mass_extract.py case_name.zip
```
编排器将:
1. 在结果目录下安全地解压 ZIP
2. 搜索最可能的 PDF 或 TXT 案件报告
3. 发现支持的截图和音频文件
4. 按平台对截图进行分类
5. 运行相应的提取器
6. 处理音频证据
7. 写入一个合并的 CSV
默认输出布局:
```
results/
├── extracted/
└── _merged.csv
```
除非启用了保留或调试标志,否则每个图像和音频的中间文件都是临时的。
### 带有明确案件报告的压缩包模式
当压缩包包含多个报告候选项或报告单独存储时,请使用此模式:
```
python3 chat/mass_extract.py \
case_name.zip \
--case-report case_reports/case_report.pdf
```
### 文件夹模式
处理已解压的压缩包或包含可发现报告的证据文件夹:
```
python3 chat/mass_extract.py case_name/
```
### 明确报告模式
处理已知报告以及一个或多个证据文件、文件夹、通配符路径或 ZIP 压缩包:
```
python3 chat/mass_extract.py \
case_reports/case_report.pdf \
evidence/ \
--results-dir results \
--model gemma3:12b \
--langs en \
--classify-mode auto \
--emoji-mode omit \
--audio-device cuda
```
可以提供多个证据路径:
```
python3 chat/mass_extract.py \
case_reports/case_report.pdf \
evidence/facebook/ \
evidence/viber/ \
evidence/audio/
```
也可以通过 `--case-report` 提供明确的报告:
```
python3 chat/mass_extract.py \
evidence_package.zip \
--case-report case_reports/case_report.pdf
```
## 单张图片聊天提取
### Facebook Messenger
```
python3 chat/facebook_extract.py \
images/facebook/example_messenger_chat.png \
case_reports/case_report.pdf \
--model gemma3:12b \
--langs en \
--emoji-mode omit \
--output results/per_image/example_messenger_chat_extracted.csv \
--debug-dir results/per_image/example_messenger_chat_debug
```
### Viber
```
python3 chat/viber_extract.py \
images/viber/example_viber_chat.png \
case_reports/case_report.pdf \
--model gemma3:12b \
--langs en \
--emoji-mode omit \
--output results/per_image/example_viber_chat_extracted.csv \
--debug-dir results/per_image/example_viber_chat_debug
```
### 仅 OCR 聊天提取
禁用视觉模型图像输入,同时保留基于 OCR 的处理:
```
python3 chat/facebook_extract.py \
images/facebook/example_messenger_chat.png \
case_reports/case_report.pdf \
--no-vision
```
仅 OCR 模式可能会减少 GPU 使用,但可能会降低文本和气泡边界的准确性。
## 独立音频提取
### 处理单个音频文件
```
python3 speech/audio_diarize.py \
evidence/audio/example_voice_message.mp3 \
--case-report case_reports/case_report.pdf \
--output-dir results/per_audio/example_voice_message \
--backend moss-local \
--language en \
--device cuda \
--dtype bfloat16 \
--llm-backend ollama \
--ollama-model gemma3:12b
```
### 处理音频文件夹
```
python3 speech/audio_diarize.py \
evidence/audio/ \
--case-report case_reports/case_report.pdf \
--output-dir results/per_audio \
--backend moss-local \
--device cuda \
--llm-backend ollama \
--ollama-model gemma3:12b
```
### 处理音频 ZIP 压缩包
```
python3 speech/audio_diarize.py \
evidence/audio_package.zip \
--case-report case_reports/case_report.pdf \
--output-dir results/per_audio \
--backend moss-local \
--device cuda \
--llm-backend ollama \
--ollama-model gemma3:12b
```
### 仅生成匿名说话人轮次
禁用 LLM 身份归属:
```
python3 speech/audio_diarize.py \
evidence/audio/example_call.wav \
--case-report case_reports/case_report.pdf \
--output-dir results/per_audio/example_call \
--llm-backend none
```
### 手动说话人映射
提供一个 JSON 映射:
```
{
"S01": "Alice Example",
"S02": "Bob Example"
}
```
然后运行:
```
python3 speech/audio_diarize.py \
evidence/audio/example_call.wav \
--case-report case_reports/case_report.pdf \
--output-dir results/per_audio/example_call \
--speaker-map speaker_map.json
```
有用的独立音频输出包括:
```
.moss.raw.txt
.speaker_turns.txt
.llm_attribution.json
.diarized.csv
.diarized.txt
.speaker_map_template.json
diarization_manifest.json
```
使用 `--debug-json` 以保留额外的转录、prompt、案件上下文和归属产物。
## 平台分类
`chat/mass_extract.py` 支持自动路由到正确的聊天提取器。
| 模式 | 行为 |
| ---------- | ------------------------------------------------------------------------------------ |
| `auto` | 首先使用文件名和路径提示,然后在需要时回退到视觉模型。 |
| `filename` | 仅使用文件名和路径关键字,如 `facebook`、`messenger` 或 `viber`。 |
| `vision` | 首先使用视觉模型,然后回退到文件名和路径提示。 |
### 仅文件名分类
```
python3 chat/mass_extract.py \
case_name.zip \
--classify-mode filename
```
### 强制 Facebook Messenger 提取
```
python3 chat/mass_extract.py \
case_reports/case_report.pdf \
images/facebook/ \
--force-platform facebook
```
### 强制 Viber 提取
```
python3 chat/mass_extract.py \
case_reports/case_report.pdf \
images/viber/ \
--force-platform viber
```
仅当所有提供的候选图片均属于所选平台时,才应使用强制分类。
## 实用的批量标志
| 标志 | 用途 |
| ---------------------------------------- | --------------------------------------------------------------------------- |
| `--case-report PATH` | 覆盖自动报告发现功能。 |
| `--output PATH` | 设置合并后的 CSV 路径。相对路径在 `--results-dir` 下解析。 |
| `--results-dir PATH` | 设置根输出目录。 |
| `--manifest PATH` | 将 JSON 运行清单写入提供的路径。 |
| `--classify-mode {auto,filename,vision}` | 选择截图平台分类策略。 |
| `--force-platform {auto,facebook,viber}` | 强制候选图片使用选定的平台。 |
| `--model MODEL` | 设置用于聊天提取和图像分类的 Ollama 模型。 |
| `--langs LANGS` | 设置 EasyOCR 语言列表。 |
| `--cpu` | 强制 EasyOCR 使用 CPU 模式。 |
| `--no-vision` | 禁用聊天视觉模型的图像输入,仅使用 OCR 支持。 |
| `--emoji-mode omit` | 从最终聊天文本中省略表情符号。为提高可重复性推荐使用。 |
| `--emoji-mode vision` | 仅保留视觉模型判断为清晰可见的表情符号。实验性功能。 |
| `--debug` | 保留每个图像的调试目录。 |
| `--keep-per-image` | 保留每个图像的中间 CSV 文件。 |
| `--dump-ocr` | 保存 OCR 文本和定位的 OCR 文本块。 |
| `--dump-draft` | 保存中间模型生成的聊天 CSV 草稿。 |
| `--dump-side-map` | 保存临时和已验证的侧边映射。 |
| `--keep-audio-output` | 在 `results/per_audio` 下保留独立的音频产物。 |
| `--keep-duplicates` | 禁用确切的最终行去重。 |
| `--facebook-script PATH` | 覆盖 `facebook_extract.py` 的路径。 |
| `--viber-script PATH` | 覆盖 `viber_extract.py` 的路径。 |
| `--audio-script PATH` | 覆盖 `audio_diarize.py` 的路径。 |
| `--extra-extractor-arg VALUE` | 向两个聊天提取器传递附加参数。可以重复使用。 |
| `--extra-audio-arg VALUE` | 向 `audio_diarize.py` 传递附加参数。可以重复使用。 |
## 实用的集成音频标志
这些标志由 `chat/mass_extract.py` 接受并转发给音频处理流程。
| 标志 | 用途 |
| ----------------------------------------------- | ---------------------------------------------------------------- |
| `--audio-backend {moss-local,moss-api}` | 选择本地 MOSS 模型或 HTTP 转录 endpoint。 |
| `--audio-model-id MODEL` | 设置 MOSS 模型 ID 或本地模型路径。 |
| `--audio-language LANG` | 设置转录语言提示。 |
| `--audio-device {auto,cuda,cpu}` | 选择 MOSS 推理设备。 |
| `--audio-dtype {auto,bfloat16,float16,float32}` | 选择本地 MOSS 推理 dtype。 |
| `--audio-max-new-tokens N` | 设置最大 MOSS 生成长度。 |
| `--audio-hotwords VALUES` | 添加逗号分隔的转录热词。 |
| `--audio-max-hotwords N` | 限制生成的案件报告热词。 |
| `--audio-prompt TEXT` | 覆盖基础的 MOSS 转录 prompt。 |
| `--audio-api-url URL` | 使用 `moss-api` 时设置 MOSS API endpoint。 |
| `--audio-api-timeout SECONDS` | 设置 MOSS API 请求超时时间。 |
| `--audio-llm-backend {ollama,none}` | 启用或禁用发送者/接收者归属。 |
| `--audio-ollama-model MODEL` | 覆盖用于音频归属的 Ollama 模型。 |
| `--audio-ollama-host URL` | 覆盖用于音频归属的 Ollama 主机。 |
| `--audio-llm-timeout SECONDS` | 设置音频归属请求超时时间。 |
| `--audio-speaker-map PATH` | 提供手动说话人映射 JSON 文件。 |
| `--audio-participants VALUES` | 提供可选的逗号分隔参与者约束。 |
| `--audio-map-speakers-by-order` | 按首次出现顺序将说话人映射到提供的参与者。 |
| `--audio-no-merge-turns` | 保持连续的匿名说话人片段独立。 |
| `--audio-debug-json` | 保留原始和诊断音频 JSON 输出。 |
| `--keep-audio-output` | 保留每个音频的中间文件。 |
## 拼图处理
首先尝试自动拼图分割。
当自动分割不可靠时,对于独立的聊天提取,可以使用手动布局标志。
### 固定网格
```
--grid 2x1
```
示例:
```
python3 chat/facebook_extract.py \
images/facebook/collage.png \
case_reports/case_report.pdf \
--grid 2x1 \
--output results/per_image/collage_extracted.csv \
--debug-dir results/per_image/collage_debug
```
### 不均匀行布局
```
--layout 2,3
```
示例:
```
python3 chat/facebook_extract.py \
images/facebook/collage.png \
case_reports/case_report.pdf \
--layout 2,3 \
--output results/per_image/collage_extracted.csv \
--debug-dir results/per_image/collage_debug
```
使用 `--grid` 或 `--layout`,但不能同时使用两者。
## 内部运行缓存
集成的批量处理流程可能会在一次运行期间创建临时的内部缓存。
### 聊天对话状态缓存
聊天处理流程为每个平台和证据文件夹对话键存储最后接受的 `LEFT`/`RIGHT` 映射。
此映射仅用作后续看起来属于同一对话的截图的软连续性先验。
当前图像中的证据仍然具有权威性。示例包括:
- 不同的可见联系人
- 明确的自我身份识别
- 精确的前导说话人标签
- 强直接称呼证据
- 与缓存映射不兼容的参与者配对
编排器传递内部参数:
```
--conversation-state-cache
--conversation-key
```
用户通常不需要手动提供这些参数。
### 音频案件上下文缓存
音频处理流程可能会创建一个经过验证的案件上下文 JSON 图谱,包含:
- 参与者
- 角色
- 别名
- 联系信息
- 交互对
- 通讯渠道
- 时间线事件
- 简明的案件摘要
该图谱在同一次批处理运行期间处理的所有音频文件中重复使用,避免重复分析案件报告。
编排器传递内部音频参数:
```
--case-context-cache
```
这两个缓存都是内部的、运行本地的产物,不应提交到仓库中。
## 输出保留
默认情况下,集成流程优先考虑最终合并的 CSV,并删除临时的每个项目的工作空间。
在需要详细检查时,请使用以下标志:
```
--keep-per-image
--keep-audio-output
--debug
--dump-ocr
--dump-draft
--dump-side-map
--audio-debug-json
```
保留的典型输出树可能如下所示:
```
results/
├── extracted/
├── per_image/
│ ├── _extracted.csv
│ └── _debug/
├── per_audio/
│ ├──
标签:AI风险缓解, OCR, Python, 凭据扫描, 数字取证, 数据提取, 无后门, 系统调用监控, 自动化脚本, 语音转写, 逆向工具