Python语音检索
这是一份音频检索代码根据一段查询语音在本地音频库中快速找出最相似的录音文件。python# -*- coding: utf-8 -*-voice_match.py —— 根据一段语音在本地音频库中检索最相似的音频原理与说话内容无关的通用声学匹配1. 每段音频切成 2s 滑窗每个窗口提取定长声学向量MFCC Δ ΔΔCMN 归一化分段池化2. 所有窗口向量 L2 归一化后堆成矩阵即声学指纹库3. 查询语音同样切窗提特征与库矩阵做余弦相似度4. 按文件聚合每个查询窗口取最佳命中再取 top-n 平均返回 Top-K用法python voice_match.py build ./audios -i ./indexpython voice_match.py search ./query.wav -i ./index -k 5from __future__ import annotationsimport argparseimport jsonfrom pathlib import Pathimport numpy as npimport librosaSR 16000N_MFCC 20N_PARTS 4 # 时间轴分几段池化AUDIO_EXTS {.wav, .mp3, .flac, .m4a, .ogg, .aac, .opus, .wma}# 特征维度 N_MFCC * 3(原ΔΔΔ) * N_PARTS * 2(meanstd) 480FEAT_DIM N_MFCC * 3 * N_PARTS * 2# --------------------------------------------------------------------------# 音频加载 / 切窗# --------------------------------------------------------------------------def load_audio(path: str | Path, sr: int SR) - np.ndarray:读音频 - 单声道 - 重采样 - 去静音 - 峰值归一化y, _ librosa.load(str(path), srsr, monoTrue)if y.size 0:return y.astype(np.float32)y, _ librosa.effects.trim(y, top_db30)peak float(np.abs(y).max())if peak 0:y y / peakreturn y.astype(np.float32)def make_windows(y: np.ndarray, win: float 2.0, hop: float 1.0,sr: int SR) - list[np.ndarray]:滑窗切分保证短音频也能返回至少一个窗口w, h int(win * sr), int(hop * sr)if y.size 0:return []if y.size w:return [y]out [y[s:s w] for s in range(0, y.size - w 1, h)]if (y.size - w) % h: # 补上尾部残留out.append(y[-w:])return out# --------------------------------------------------------------------------# 特征提取可替换为声纹模型见文末说明# --------------------------------------------------------------------------def embed(y: np.ndarray, sr: int SR) - np.ndarray | None:一段语音(建议 1~3s) - L2 归一化的 480 维向量if y.size sr * 0.25: # 太短丢弃return Nonemfcc librosa.feature.mfcc(yy, srsr, n_mfccN_MFCC, n_fft400,hop_length160, n_mels40, fmin20, fmax7600,)# 倒谱均值归一化(CMN)抑制麦克风/信道带来的整体偏移mfcc mfcc - mfcc.mean(axis1, keepdimsTrue)d1 librosa.feature.delta(mfcc)d2 librosa.feature.delta(mfcc, order2)feat np.vstack([mfcc, d1, d2]) # (60, T)# 时间轴均分 N_PARTS 段每段取 mean std保留粗时序信息parts np.array_split(feat, N_PARTS, axis1)pooled np.concatenate([np.concatenate([p.mean(axis1), p.std(axis1)]) for p in parts])norm float(np.linalg.norm(pooled))if norm 1e-9:return Nonereturn (pooled / norm).astype(np.float32)# --------------------------------------------------------------------------# 索引# --------------------------------------------------------------------------class VoiceIndex:def __init__(self, index_dir: str | Path):self.dir Path(index_dir)self.dir.mkdir(parentsTrue, exist_okTrue)self.vec_path self.dir / vectors.npyself.meta_path self.dir / meta.jsonself.vectors: np.ndarray | None Noneself.meta: list[dict] []def save(self) - None:np.save(self.vec_path, self.vectors)self.meta_path.write_text(json.dumps(self.meta, ensure_asciiFalse), encodingutf-8)def load(self) - VoiceIndex:if not self.vec_path.exists() or not self.meta_path.exists():raise FileNotFoundError(f索引不存在{self.dir}请先执行 build)self.vectors np.load(self.vec_path)self.meta json.loads(self.meta_path.read_text(encodingutf-8))return self# --------------------------------------------------------------------------# 建库# --------------------------------------------------------------------------def build(audio_dir: str | Path, index_dir: str | Path,win: float 2.0, hop: float 1.0) - VoiceIndex:audio_dir Path(audio_dir)files sorted(p for p in audio_dir.rglob(*) if p.suffix.lower() in AUDIO_EXTS)if not files:raise SystemExit(f在 {audio_dir} 下没找到音频文件)vecs: list[np.ndarray] []meta: list[dict] []for i, f in enumerate(files, 1):try:y load_audio(f)except Exception as e: # 损坏/不支持的格式print(f[skip] {f.name}: {e})continuekept 0for j, seg in enumerate(make_windows(y, win, hop)):v embed(seg)if v is None:continuevecs.append(v)meta.append({file: str(f), win: j})kept 1print(f[{i}/{len(files)}] {f.name} 窗口{kept})idx VoiceIndex(index_dir)idx.vectors (np.vstack(vecs).astype(np.float32)if vecs else np.zeros((0, FEAT_DIM), np.float32))idx.meta metaidx.save()print(f\n完成{len(files)} 个文件{len(meta)} 个窗口向量 - {index_dir})return idx# --------------------------------------------------------------------------# 检索# --------------------------------------------------------------------------def search(query: str | Path, index_dir: str | Path,top_k: int 5, win: float 2.0, hop: float 1.0) - list[tuple]:idx VoiceIndex(index_dir).load()if idx.vectors is None or idx.vectors.shape[0] 0:raise RuntimeError(索引为空请先 build)y load_audio(query)q_vecs [v for v in (embed(s) for s in make_windows(y, win, hop)) if v is not None]if not q_vecs:raise RuntimeError(查询语音太短或全是静音)Q np.vstack(q_vecs) # (nq, D)S Q idx.vectors.T # (nq, nv) 余弦相似度越大越像files np.array([m[file] for m in idx.meta])results []for f in np.unique(files):sub S[:, files f] # (nq, nf)best np.sort(sub.max(axis1))[::-1] # 每个查询窗口的最佳命中n min(3, best.size)score float(best[:n].mean()) # top-3 平均抗单点噪声hits int((sub 0.8).sum()) # 强命中窗口数参考results.append((f, score, hits))results.sort(keylambda x: -x[1])return results[:top_k]# --------------------------------------------------------------------------# CLI# --------------------------------------------------------------------------def main() - None:ap argparse.ArgumentParser(description基于语音的音频库检索)sub ap.add_subparsers(destcmd, requiredTrue)b sub.add_parser(build, help扫描目录建索引)b.add_argument(audio_dir)b.add_argument(-i, --index, defaultvoice_index)b.add_argument(--win, typefloat, default2.0, help窗口秒数)b.add_argument(--hop, typefloat, default1.0, help滑动步长秒数)s sub.add_parser(search, help用一段语音检索)s.add_argument(query)s.add_argument(-i, --index, defaultvoice_index)s.add_argument(-k, typeint, default5)s.add_argument(--win, typefloat, default2.0)s.add_argument(--hop, typefloat, default1.0)a ap.parse_args()if a.cmd build:build(a.audio_dir, a.index, a.win, a.hop)else:rows search(a.query, a.index, a.k, a.win, a.hop)print(f\n{相似度:8} {强命中:6} 文件)print(- * 60)for f, sc, hits in rows:print(f{sc:8.4f} {hits:6d} {f})if __name__ __main__:main()语音匹配检索的完整流程拆解从建立声学指纹到检索排序整个流程围绕几个关键步骤展开音频加载与预处理统一转为单声道、重采样到16kHz自动去除首尾静音并对音量做归一化让后续特征更稳定。滑窗切分与特征提取默认每2秒切一个窗口用1秒步长滑动。每个窗口提取MFCC及其一阶、二阶差分再做倒谱均值归一化和分段池化最终压缩成480维的L2归一化向量。索引构建与保存把所有音频的窗口向量堆成矩阵连同文件路径信息一起保存到索引目录。查询检索与排序对查询语音做同样的特征提取计算它与库中所有窗口向量的余弦相似度再按文件聚合每个查询窗口取最佳命中再取top-3平均返回相似度最高的结果。---优化建议 当前默认按说话人声学特征匹配若您更关注“同一段录音”的精确查找可以替换为音频指纹方案如pyacoustid并调整相似度计算方式。仅供参考学习用。

相关新闻

AI测试Agent 25个全套Skill,直接搭建完整自动化测试流水线

AI测试Agent 25个全套Skill,直接搭建完整自动化测试流水线

文章目录前言一、需求与用例设计,6 个1. req-to-user-story2. review-user-stories3. generator-testcase-xmind4. generator-testcase-excel5. review-testcase6. safe-testcase二、接口自动化,10 个7. api-schema-parser8. api-testdata-generator9. a…

2026/10/2 20:49:14 阅读更多 →
jev-ultrafast爆火!毫秒级AI浏览器自动化,云平台配置再也不用手动点

jev-ultrafast爆火!毫秒级AI浏览器自动化,云平台配置再也不用手动点

文章目录前言1. 它到底解决了什么痛点2. 拆开看看:两大核心部件2.1 一号选手:ServBay 本地 AI 网关2.2 二号选手:Browser-Use 拟人化操作3. 环境搭建,三步走3.1 第一步:装依赖3.2 第二步:接入 ServBay AI 网…

2026/10/2 20:49:14 阅读更多 →
vscode和Visual Studio里利用cuda核函数进行加速简单例子讲解

vscode和Visual Studio里利用cuda核函数进行加速简单例子讲解

要让 .cpp 调用 .cu&#xff0c;核心原则只有一条&#xff1a;.cu 交给 nvcc 编译&#xff0c;.cpp 交给 cl&#xff08;MSVC&#xff09;或 g 编译&#xff0c;两者通过「公共头文件 普通 C 函数」对接&#xff0c;最后由链接器拼成一个 exe。<<<>>> 这种 …

2026/10/2 20:49:14 阅读更多 →

最新新闻

ThreadLocal深入解析:从存储结构到线程池脏数据与内存泄漏

ThreadLocal深入解析:从存储结构到线程池脏数据与内存泄漏

先说个真实排查经历。前几天一个查询接口在压测时&#xff0c;日志里偶尔出现上一个请求的用户ID&#xff0c;查到最后才发现&#xff0c;问题出在一个没清理的ThreadLocal上。很多人对ThreadLocal有执念&#xff1a;既然它叫“线程局部变量”&#xff0c;那多线程访问同一个变…

2026/10/2 21:27:36 阅读更多 →
可视化搭建 keepAlive 模式:用 createPortal 分离 DOM 与 React 实例,根治拖拽跨父级移动的 Remount 卡顿

可视化搭建 keepAlive 模式:用 createPortal 分离 DOM 与 React 实例,根治拖拽跨父级移动的 Remount 卡顿

文档技术博客教程 【免费下载链接】weekly 前端精读周刊。帮你理解最前沿、实用的技术。 项目地址&#xff1a; https://gitcode.com/GitHub_Trending/we/weekly 点击查看 免费下载 在可视化搭建场景中&#xff0c;拖拽组件跨越不同容器、切换父级是高频操作&#xff0c;而 Re…

2026/10/2 21:27:36 阅读更多 →
如何把 Windows 11 任务栏找回经典快速启动工具栏?ExplorerPatcher 8 分钟配置完整指南

如何把 Windows 11 任务栏找回经典快速启动工具栏?ExplorerPatcher 8 分钟配置完整指南

如何把 Windows 11 任务栏找回经典快速启动工具栏&#xff1f;ExplorerPatcher 8 分钟配置完整指南 【免费下载链接】ExplorerPatcher This project aims to enhance the working environment on Windows 项目地址: https://gitcode.com/GitHub_Trending/ex/ExplorerPatcher …

2026/10/2 21:26:36 阅读更多 →
Java 设计模式精讲:基于 Active Object 模式构建高效异步并发系统(附 java-design-patterns 源码剖析)

Java 设计模式精讲:基于 Active Object 模式构建高效异步并发系统(附 java-design-patterns 源码剖析)

示例工程教程 【免费下载链接】java-design-patterns Design patterns implemented in Java 项目地址&#xff1a; https://gitcode.com/GitHub_Trending/ja/java-design-patterns 点击查看 免费下载 导读&#xff1a;本文以开源仓库 java-design-patterns 中的 active-object…

2026/10/2 21:26:36 阅读更多 →
深耕计算机考研,助力码农突围 — 天任考研计算机科学与技术专项集训营正式启航

深耕计算机考研,助力码农突围 — 天任考研计算机科学与技术专项集训营正式启航

计算机科学与技术是近年来考研报考热度最高的专业之一。随着信息技术和人工智能产业快速发展&#xff0c;计算机类研究生就业薪资持续走高&#xff0c;吸引了大量本专业考生和跨专业考生报考。然而&#xff0c;计算机考研竞争异常激烈&#xff0c;408 计算机学科专业基础综合内…

2026/10/2 21:26:36 阅读更多 →
Candle 运行 XLM-RoBERTa 实战:Fill-Mask、Reranker 与文本分类三大任务指南

Candle 运行 XLM-RoBERTa 实战:Fill-Mask、Reranker 与文本分类三大任务指南

人工智能大模型机器学习深度学习本地部署模型推理服务 【免费下载链接】candle Minimalist ML framework for Rust 项目地址&#xff1a; https://gitcode.com/GitHub_Trending/ca/candle 点击查看 免费下载 本文基于 Candle 开源仓库中的 xlm-roberta 示例 与对应源码&#x…

2026/10/2 21:26:36 阅读更多 →

日新闻

从零搭建AI工程化:模型之外的完整闭环

从零搭建AI工程化:模型之外的完整闭环

先搞清楚一件事&#xff1a;从零开始做 AI 工程化&#xff0c;难的从来不是调模型、写提示词&#xff0c;而是把一套原型 Demo 变成长得像是“正经系统”的东西。你手里可能已经有了能跑通的代码&#xff0c;也可能刚读完一些概念&#xff0c;但真到了要把它变成可维护、可观测…

2026/10/2 0:00:20 阅读更多 →
大模型训练显存估计与混合精度训练实战指南

大模型训练显存估计与混合精度训练实战指南

1. 大模型训练显存估计与混合精度训练详解显存不够用&#xff0c;几乎是每个做大模型训练的人都会撞上的第一堵墙。你可能也经历过&#xff1a;模型代码写完了&#xff0c;数据管道跑通了&#xff0c;满心欢喜地按下训练启动脚本&#xff0c;结果几秒钟后终端弹出一行红字——C…

2026/10/2 0:00:20 阅读更多 →
小样本学习数据集选型指南:27个真正可用的高质量数据集

小样本学习数据集选型指南:27个真正可用的高质量数据集

1. 小样本学习的“弹药库”&#xff1a;为什么你总在找数据集&#xff0c;却总找不到真正能用的&#xff1f; 小样本、数据集——这两个词最近半年在我处理的200多个AI项目咨询里&#xff0c;出现频率排进前三。不是模型调不好&#xff0c;不是代码写不对&#xff0c;而是卡在…

2026/10/2 0:00:20 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集&#xff1a;Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/10/1 19:40:48 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/10/1 19:41:40 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/10/1 20:05:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 10:36:31 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 5:26:06 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 6:09:11 阅读更多 →