技术说明
约 1286 字大约 4 分钟
架构总览
┌──────────────────────────────┐
│ Vue 3 + VueFluentWidgets │ Tauri 2 (Rust) 桌面外壳
│ Vite 构建的前端界面 │
└──────────────┬───────────────┘
│ HTTP (仅 127.0.0.1)
┌──────────────▼───────────────┐
│ Python FastAPI 后端 │ 索引管理 / 匹配 / 音频流 / 导出 / 收藏 / 设置
│ fp_core 指纹核心 │ 指纹提取 / 索引加载 / 多段聚类匹配
│ build_index 并行构建 │ SQLite 分片 + .dat 二进制
└──────────────┬───────────────┘
│
SQLite / NumPy / soundfile / librosa / ffmpeg- 桌面外壳:Tauri 2(Rust),负责窗口、安装包、Python 运行时引导与后端进程生命周期管理。
- 后端:FastAPI + Python,仅监听本机回环地址,通过隐藏窗口的子进程方式运行。
- 前端:Vue 3 + Vite,采用 VueFluentWidgets 的 Fluent Design 组件。
- 音频解码:优先 librosa/soundfile;AAC、M4A、WMA 等格式自动使用内置 FFmpeg 兜底解码。
指纹算法
预处理
- 采样率统一重采样为 11025 Hz 单声道。
- STFT:窗长 1024、hop 256(每帧约 23ms),使用 511 个频率 bin。
频谱峰值选取
对 STFT 幅度谱(dB)执行两步峰值提取:
- 2D 局部极大值:5×5 邻域内的局部极大值。
- 逐帧秩选峰:每帧保留相对帧内峰值 12dB 窗口内、且高于绝对下限 -65dB 的峰,最多 3 个。
秩选策略保证峰值集合对整体音量差异与切片时间原点不敏感——这是短样本能稳定命中完整文件的关键。
峰值对哈希
每个锚点峰与其后 25 个峰组成峰值对 (f1, f2, dt),其中:
f1、f2:两个峰的频率 bin(各 9 bit);dt:帧时间差(12 bit,上限 4095 帧)。
组合为 30-bit 哈希值,最终得到每段音频的哈希序列。
索引结构与存储
SQLite 分片
每个索引段目录(seg_XXX 或索引根目录)内按 worker 数生成 shard_*.sqlite:
files表:fid / name / path / duration / status;hashes表:h / fid / t(哈希值、文件 ID、时间帧),建立ix_h索引。
fid 全局唯一:由分片编号与行号组合而成,跨分片不会冲突。
.dat 二进制
每个分片对应一个 .dat 二进制文件,内容为 (hash, fid, t) 三元组的紧凑数组(每行 12 字节)。加载时直接 mmap/读取为 NumPy 数组并排序,避免重新解析 SQLite,显著缩短大索引的加载时间。
分段与元数据
- 按目标段加载内存(MB)把文件列表分组:以估算哈希量(时长 × 经验速率)为代价,贪心分组到预算内。
- 索引根目录的
index_meta.json记录首次构建时的segment_size_mb,供增量构建复用默认值。 - 旧版或外部导入索引没有元数据时,
segment_size_mb视为0(单段)。
内存缓存
- 后端维护段级 LRU 缓存(默认最多 4 段),命中即返回,避免重复加载。
- 匹配对已加载的 ShardIndex 只读,可并发执行;加载过程加锁串行化,避免并发重复加载造成内存峰值。
- 设置中的「检索后卸载索引」开启后,每次匹配结束会释放本次使用的段;卸载带实例校验,避免并发请求误删重新加载的新实例。
匹配流程
- 按索引名与分段名解析段目录,从缓存加载(或重新加载)分片。
- 对样本做相同预处理与指纹提取(支持起止时间裁剪)。
- 对每个候选文件执行时间偏移对齐投票:同一偏移上的峰值对哈希匹配数量最多者胜出。
- 同一文件在不同时间多次出现会被聚成多个独立命中(支持混剪、拼接场景)。
- 置信度 = 对齐哈希数 / 样本哈希数,上限 100%;阈值按样本时长自适应。
构建流程
iter_library_files按扩展名收集音频文件(支持常见格式与混合目录),可选递归。process_files按 worker 并行解码、提取哈希、写入分片,逐文件提交进度事件。- 增量构建先读取所有分片中的已索引路径集合,过滤出未入库的新文件再处理。
- 完成后统计全部
hashes表行数作为索引总量。
导出拼接
按样本时间线,从各命中文件对应的偏移与时长(tq0/tq1)取出音频段,经 FFmpeg 重采样/转换后顺序拼接为 WAV 输出。
音频流播放
/api/audio 通过 FFmpeg 从指定偏移切出完整剩余音频并以 WAV 流返回;前端播放器加载完整源文件并在元数据就绪后 seek 到命中偏移,进度条显示完整文件时长。
目录结构
backend/
fp_core.py 指纹核心:指纹提取 / 索引加载 / 匹配聚类
build_index.py 并行构建 / 断点续建 / 分段 / 增量
server.py FastAPI:索引管理 / 构建任务 / 匹配 / 音频流 / 导出 / 收藏 / 设置
src/ Vue 3 前端
stores/ 跨页面状态与共享缓存
views/ 检索、构建、管理、收藏、设置、关于
src-tauri/ Tauri 2 (Rust):窗口 / 引导 / 后端进程管理相关链接
贡献者
更新日志
2026/8/12 08:16
查看所有更新日志
fcd5f-docs: in-site download page with mirror sources, expanded guides, hero fix于
