让视频里的声音“有个位置”:我用 C# 做了个离线热图工具

文章来源声明: 原文作者:天天代码码天天; 来源站点:掘金; 原文链接:https://juejin.cn/post/7701987815224164403; 本文基于上述来源整理/加工,觅优补充点评,仅供技术学习交流。版权归原作者所有。
觅优短评

亮点是把研究模型接成完整桌面流程:本地离线、CPU/GPU 可选、导出齐全,适合开发者做视听关联观察与演示;但热图是粗粒度关联,不能当声源定位结论。

看视频时,我们常常会下意识地把声音和画面联系起来。

听见琴声,就去看演奏的人;听见狗叫,就去找画面里的小狗;机器突然响起来,目光也会移向正在运转的部件。

这个过程对人很自然,但对程序来说,要同时理解声音和画面,并不简单。

最近,我把这个有意思的方向做成了一个 Windows 桌面小工具:视频声音来源可视化工坊。

导入一段带声音的视频,软件会结合画面和音频,在图像上叠加一层热图,让我们观察:哪些画面区域与当前声音更相关?

图片

视频声音来源可视化工坊实际运行界面

这是用 Blender 官方公开短片做的本地运行截图,用于展示软件界面与处理流程;没有人工声源标注,热点不代表已经找对发声对象。

先说清它能做什么:这是一个视听关联可视化工具。它不会测出声源离摄像头几米远,也不是用一个麦克风实现真实空间定位。红色区域表示模型给出的相对高值,不是“这里有百分之多少的概率正在发声”。

理解这个区别,再去观察热图,就很有意思了。

不只看一张效果图,把整个流程用起来

这一版已经把视频导入、片段分析、时间轴查看、音频试听和结果导出连了起来。

左边看原画面,右边看热图。分析完成后,可以拖动时间轴、查看前后采样,试听当前样本对应的声音窗口,再调整叠加效果。

如果想分享结果,可以导出带原片段声音的热图 MP4,也可以只保存当前画面的 PNG。需要继续研究的朋友,还可以导出时间轴 CSV,或者保留分析文件,以后重新打开查看。

整套流程在本地运行,视频不需要上传云端。

没有独立显卡也可以先用 CPU;有兼容的显卡和驱动,可以切换到 DirectML GPU。本版运行时不需要安装 Python、PyTorch 或 CUDA。

第一次使用,建议从十几秒的短片开始

完整解压运行包,启动 SoundSource.Workshop.exe,然后按下面几步操作:

  1. 点击“导入视频”,选择一段带音轨的本地视频。
  2. 设置片段起点和时长。默认分析 30 秒,每秒采样 1 次。
  3. 选择 CPU 或 GPU,点击“开始分析”。
  4. 分析完成后,拖动时间轴并松开鼠标,刷新对应画面。
  5. 点击“试听对应音频窗口”,对照声音观察热图。
  6. 调整显示参数,导出 MP4 或本帧 PNG。

初次体验,可以自己拍一段单件乐器演奏、狗叫或者机器运转的视频。尽量让发声对象清楚可见,先减少背景音乐和旁白的干扰。

这些是适合尝试的素材类型,不是对识别效果的保证。模型是否找对,仍然需要我们结合原视频判断。

当前支持每秒采样 1 次或 2 次,单次片段最长 10 分钟。长视频可以先选取感兴趣的片段,不必一上来就处理整部影片。

默认工作目录是程序旁边的 workspace 文件夹,业务路径以 EXE 所在目录为基准,方便整套软件拷贝使用。

热图有三种看法,可以来回比较

界面上的模式按钮可以循环切换三种结果:

模式看什么
EZ-VSL 融合热图把视听关联和图像对象先验结合起来,是默认模式。
仅视听关联 AVL看声音特征与不同画面区域的关联。
仅对象先验 OGL只看图像特征提供的对象先验,不使用声音判断。

第三种尤其值得单独看一看:一个区域很显眼,不等于它正在发声。 对象先验可以帮助模型关注物体,也可能把我们的注意力引到没有发声的对象上。

融合模式默认采用 40% 视听关联、60% 对象先验,可以在界面里调整。透明度控制热图遮住原图的程度,显示阈值控制哪些较低值区域不显示。

这些参数都复用已经保存的模型输出,调整时无需重新推理。

程序是怎么把声音“画”出来的?

算法采用的是 EZ-VSL 作者公开的研究实现(github.com/stoneMo/EZ-… ONNX 转换、C# 前后处理和桌面应用。

它会同时走两条路。

一条路处理图像:把采样画面转成模型需要的尺寸,提取不同位置的视觉特征。

另一条路处理声音:取对应的 3 秒音频窗口,将声音变成频谱,再提取音频特征。

接下来,程序比较声音特征与各个画面位置的特征,得到一张粗粒度的关联图,再结合图像对象先验,生成最终热图。

因此,画面上虽然能看到平滑的彩色覆盖层,模型的原始空间输出实际是 7×7。显示时进行了放大和平滑,不能据此把热区边缘理解成精确的物体轮廓。

在工程里,FFmpeg 负责视频解码、抽帧、音频重采样和最后的视频编码;C# 负责音频频谱、图像归一化、模型调用、热图叠加与界面交互;ONNX Runtime 负责 CPU 或 DirectML GPU 推理。

这也是我很喜欢这类项目的地方:把研究代码里的模型,接到一个普通用户能操作的完整流程中。

速度和磁盘占用,也做了一些处理

这版没有把视频每一帧都拿来推理,而是每秒抽取 1~2 个样本;整段分析复用同一个模型会话,CPU 默认只用两线程,并关闭线程池自旋,减少空闲等待时的资源消耗。

在本机 Ryzen 7 7735H 的一次 7 样本短片测试中,包含 C# 频谱计算和模型 Run 的平均耗时,CPU 两线程约 67 毫秒/采样,DirectML GPU 约 19 毫秒/采样。

这个数字不包含模型加载、视频解码、文件摘要计算和视频编码,也不是整段视频的转换速度;不同电脑和素材需要实际测试。

磁盘方面,分析阶段暂存的是低分辨率采样帧和单声道音频,任务结束后会清理。导出时生成的小尺寸热图 PNG 也会清理,保留的是分析结果和用户导出的视频等文件。

导出的 MP4 使用 10 fps,但热图仍按每秒 1~2 次的分析结果更新,中间画面保持最近一次结果。输出帧率和模型采样率是两个不同的设置。

有趣,也要允许模型“看错”

给视频加一段背景音乐,画面中的物体不一定就是音乐的来源;旁白可能来自画外,镜头也可能已经切换到另一个场景。

这些情况都会影响热图。即便画面上出现了醒目的红色区域,也可能只是错误关联。

当前版本还不做声音分离、语音文字转录、多个同时发声物体的独立分轨,也没有摄像头实时模式。软件里的曲线是音频窗口 RMS,不是物理声压测量。

所以,我更愿意把它当作一个研究与观察工具:比较不同声音下模型关注的位置,看看背景音乐如何干扰结果,或者做一次“声音与画面如何关联”的小实验。

数值转换的一致性和视频处理链路已经验证;在各种真实场景里能找对多少声源,还需要带标注的数据来评估,不能靠几张好看的截图下结论。

给喜欢 C# 的朋友,也准备了完整工程

项目使用 C# + .NET Framework 4.8 + WinForms,保留 .Designer.cs 和 .resx,提供完整 VS2022 解决方案,方便继续调整界面和二次开发。

正常编译采用本地依赖引用,不需要联网还原 NuGet,也不需要先安装 Python。源码包含模型、前后处理、FFmpeg 调用、取消任务、错误日志和导出流程。

本次完整运行包约 211 MiB,完整源码包约 493 MiB。运行需要 Windows 10/11 x64 和 .NET Framework 4.8;GPU 模式还需要兼容的显卡与驱动。

EZ-VSL 的作者、模型来源和第三方组件说明都保留在项目里。应用代码、预训练权重、训练数据以及随包 FFmpeg 的许可条件需要分别看,二次分发请参阅包内许可文档。

如果你也喜欢这类“小而有意思”的桌面工具,欢迎一起试用、交流效果,也欢迎聊聊还有哪些算法值得做成普通人能用的软件。

QQ 群:天天代码码天天
群号码:264292622

你最想拿哪一段视频来试试?