根据音频中的不同讲述人声音进行分离音频 | 基于ai的说话人声音分离项目

news2025/2/23 14:35:08

0.研究背景

在实际的开发中可能会遇到这样的问题,老板让你把音频中的每个讲话人的声音分离成不同的音频片段。你可以使用au等专业的音频处理软件手动分离。但是这样效率太慢了,现在ai这么发达,我们能否借助ai之力来分离一条音频中的不同的说话人呢?答案是肯定可以的。
这里将利用声纹识别加上语音识别来对音频中不同的说话人进行语者分离。

1.技术选择

市面上开源的声纹识别和语音识别项目有很多,比如funasr,cam++就是两个不错的选择,并且funasr是国内大厂阿里巴巴旗下开源的一个集成了ASR和标点符号预测,声纹识别,声纹对比等众多模型的一个工具框架。那么本次项目就是基于funasr进行编程开发的。

2.项目源码

项目已经开源到我的代码仓库中,大家可以访问https://github.com/lukeewin/AudioSeparationGUI
如果国内的小伙伴们不方便访问github那么也可以访问gitee,https://gitee.com/lukeewin/AudioSeparationGUI

3.项目功能

改项目支持对音频中每个说话人进行分离,不限制说话人数量,比如你的音频中存在10个说话人,也是可以进行分离的。
同时改项目还支持对分离后的音频,把相同的说话人讲的声音合并在一个音频文件中。
除了支持音频的分离外,该项目还支持分隔视频片段,通过声音驱动分隔视频,形成视频片段。

4.项目部分核心功能代码

这里这粘贴部分核心功能代码,如果需要看详细代码,可以到上面提到的代码仓库中下载。

def trans():
    if len(selected_file_list) != 0 and save_path.get() != '' and save_path.get() is not None:
        for audio in selected_file_list:
            if os.path.exists(audio):
                audio_name = os.path.splitext(os.path.basename(audio))[0]
                _, audio_extension = os.path.splitext(audio)
                show_info_label.config(text=f'正在执行中,请勿关闭程序。{audio}')
                speaker_audios = {}  # 每个说话人作为 key,value 为列表,列表中为当前说话人对应的每个音频片段
                # 音频预处理
                try:
                    audio_bytes, _ = (
                        ffmpeg.input(audio, threads=0, hwaccel='cuda')
                        .output("-", format="wav", acodec="pcm_s16le", ac=1, ar=16000)
                        .run(cmd=["ffmpeg", "-nostdin"], capture_stdout=True, capture_stderr=True)
                    )
                    res = model.generate(input=audio_bytes, batch_size_s=300, is_final=True, sentence_timestamp=True)
                    rec_result = res[0]
                    asr_result_text = rec_result['text']
                    if asr_result_text != '':
                        sentences = []
                        for sentence in rec_result["sentence_info"]:
                            start = to_date(sentence["start"])
                            end = to_date(sentence["end"])
                            if sentences and sentence["spk"] == sentences[-1]["spk"]:
                                sentences[-1]["text"] += "" + sentence["text"]
                                sentences[-1]["end"] = end
                            else:
                                sentences.append(
                                    {"text": sentence["text"], "start": start, "end": end, "spk": sentence["spk"]}
                                )

                        # 剪切音频或视频片段
                        i = 0
                        for stn in sentences:
                            stn_txt = stn['text']
                            start = stn['start']
                            end = stn['end']
                            # tmp_start = to_milliseconds(start)
                            # tmp_end = to_milliseconds(end)
                            # duration = round((tmp_end - tmp_start) / 1000, 3)
                            spk = stn['spk']

                            # 根据文件名和 spk 创建目录
                            date = datetime.now().strftime("%Y-%m-%d")
                            final_save_path = os.path.join(save_path.get(), date, audio_name, str(spk))
                            os.makedirs(final_save_path, exist_ok=True)
                            # 获取音视频后缀
                            file_ext = os.path.splitext(audio)[-1]
                            final_save_file = os.path.join(final_save_path, str(i)+file_ext)
                            spk_txt_path = os.path.join(save_path.get(), date, audio_name)
                            spk_txt_file = os.path.join(spk_txt_path, f'spk{spk}.txt')
                            spk_txt_queue.put({'spk_txt_file': spk_txt_file, 'spk_txt': stn_txt, 'start': start, 'end': end})
                            i += 1
                            try:
                                if file_ext in support_audio_format:
                                    (
                                        ffmpeg.input(audio, threads=0, ss=start, to=end, hwaccel='cuda')
                                        .output(final_save_file)
                                        .run(cmd=["ffmpeg", "-nostdin"], overwrite_output=True, capture_stdout=True,
                                             capture_stderr=True)
                                    )
                                elif file_ext in support_video_format:
                                    final_save_file = os.path.join(final_save_path, str(i)+'.mp4')
                                    (
                                        ffmpeg.input(audio, threads=0, ss=start, to=end, hwaccel='cuda')
                                        .output(final_save_file, vcodec='libx264', crf=23, acodec='aac', ab='128k')
                                        .run(cmd=["ffmpeg", "-nostdin"], overwrite_output=True, capture_stdout=True,
                                             capture_stderr=True)
                                    )
                                else:
                                    print(f'{audio}不支持')
                            except ffmpeg.Error as e:
                                print(f"剪切音频发生错误,错误信息:{e}")
                            # 记录说话人和对应的音频片段,用于合并音频片段
                            if spk not in speaker_audios:
                                speaker_audios[spk] = []  # 列表中存储音频片段
                            speaker_audios[spk].append({'file': final_save_file, 'audio_name': audio_name})
                        ret = {"text": asr_result_text, "sentences": sentences}
                        print(f'{audio} 切分完成')
                        result_queue.put(f'{audio} 切分完成')
                        show_info_label.config(text=f'{audio} 切分完成')
                        print(f'转写结果:{ret}')
                        # 存入合并队列
                        audio_concat_queue.put(speaker_audios)
                    else:
                        print("没有转写结果")
                except Exception as e:
                    print(f"转写异常:{e}")
            else:
                print("输入的文件不存在")
                messagebox.showinfo("提醒", "输入的文件不存在")
    else:
        print("没有填写输入输出")
        messagebox.showinfo("提醒", "没有填写选择文件或保存路径")

5.运行效果

在这里插入图片描述

6.其它

该项目使用Python开发,这里推荐Python版本为3.8,同时该项目中还依赖于ffmpeg,因此你需要提前安装好ffmpeg,并且配置好环境变量,这里需要注意,安装的路径中不要出现中文或者空格或者特殊字符。
如果你是小白,不懂如何运行这个项目,你也可以点击这里。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2303950.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【单片机】【UDS】 (单帧与多帧) 数据传输

对于使用 CAN 的诊断通信系统,每个单帧 (SF)、 第一帧 (FF)、 连续帧 (CF) 或流控 制帧 (FC) 有 8 字节数据场;其中单帧的 CAN_DL≤8 且第一帧的 FF_DL≤4095;下表 中已定义 每个报文的类型。 CAN FD 帧的数据场支持最大 64 个字节&#xff0…

WebXR教学 02 配置开发环境

默认操作系统为Windows 1.VS Code VS Code 是一款轻量级、功能强大的代码编辑器,适用于多种编程语言。 下载 步骤 1:访问 VS Code 官方网站 打开浏览器(如 Chrome、Edge 等)。 在地址栏输入以下网址: https://code.v…

MySql数据库运维学习笔记

数据库运维常识 DQL、DML、DCL 和 DDL 是 SQL(结构化查询语言)中的四个重要类别,它们分别用于不同类型的数据库操作,下面为你简单明了地解释这四类语句: 1. DQL(数据查询语言,Data Query Langu…

宇树科技13家核心零部件供应商梳理!

2025年2月6日,摩根士丹利(Morgan Stanley)发布最新人形机器人研报:Humanoid 100: Mapping the Humanoid Robot Value Chain(人形机器人100:全球人形机器人产业链梳理)。 Humanoid 100清单清单中…

ARMS 助力假面科技研发运维提效,保障极致游戏体验

客户介绍与项目背景 假面科技成立于 2014 年,致力于打造创新的数字产品,火爆一时的“狼人杀”、“谁是卧底”、“足记相机”都是假面科技旗下产品,公司产品总数超过 40 款,覆盖用户数超过 2 亿人。 随着业务的持续发展&#xff…

趣味数学300题1981版-八个等式、五个5等于24

八个等式 分析:此问题的求解思路是按照最后一步运算的运算符号进行分类。示例中最后一步的运算是除法,只要被除数与除数相等且不为0,就可以得到结果1.因此我们还可以对于结果等于1的情况列出其他的算式。如果保持最后一步运算为除法运算&…

关闭超时订单和七天自动确认收货+RabbitMQ规范

关闭超时订单 创建订单之后的一段时间内未完成支付而关闭订单的操作,该功能一般要求每笔订单的超时时间是一致的 TTL(Time To Live)存活时间,只能被设置为某个固定的值,不能更改,否则抛出异常 死信&#…

【多模态处理篇一】【 深度解析DeepSeek图文匹配:CLIP模型迁移实战——从原理到落地的保姆级教程】

引言:当CLIP遇到DeepSeek,会发生什么化学反应? 如果说CLIP是OpenAI为多模态领域投下的"原子弹",那DeepSeek的迁移实战方案就是给这颗原子弹装上了精确制导系统。这个组合能让你用一张猫咪表情包搜到全网同类梗图,还能让电商平台自动生成百万级商品描述,甚至帮…

水果生鲜农产品推荐系统 协同过滤余弦函数推荐水果生鲜农产品 Springboot Vue Element-UI前后端分离 代码+开发文档+视频教程

水果生鲜农产品推荐系统 协同过滤余弦函数推荐水果生鲜农产品 Springboot Vue Element-UI前后端分离 【亮点功能】 1.SpringbootVueElement-UIMysql前后端分离 2.Echarts图表统计数据, 直观展示数据情况 3.发表评论后,用户可以回复评论, 回复的评论可以被再次回复, …

1.vue使用vite构建初始化项目

npm create vuelatest❯ npm create vuelatest> npx > create-vueVue.js - The Progressive JavaScript Framework✔ Project name: … vue3_test ✔ Add TypeScript? … No / Yes ✔ Add JSX Support? … No / Yes ✔ Add Vue Router for Single Page Application dev…

在PyCharm中运行Jupyter Notebook的.ipynb文件及其pycharm软件的基础使用

(注意需使用PyCharm专业版,学生、教师可以申请免费使用:https://www.jetbrains.com/shop/eform/students) 1. pycharm2024版汉化 https://blog.csdn.net/m0_74103046/article/details/144560999 2. pycharm中的python控制台和J…

深度体验通义灵码2.0 AI 程序员

通义灵码2.0 作为一名开发者,我去年就使用过1.0,近期有幸体验了 2.0,这是一款集成了 Deepseek 大模型的智能编码助手。在这次体验中,我深入探索了新功能开发、跨语言编程、单元测试自动生成、图生代码等多个场景,深刻…

Coroutine协程

cooperation 协作 routine 程序,常规 协程核心:函数能够被挂起suspend,当然也能被回复resume 内置函数:also 返回对象本身 扩展: 内置函数let、also、with、run、apply大大提高你的开发效率! 协程的作用:…

使用IDEA提交SpringBoot项目到Gitee上

登录Gitee并新建仓库 创建本地仓库 提交本地代码到本地仓库 提交本地代码到远程仓库

Windows安装MySQL指南

1.下载 下载地址:https://www.mysql.com/downloads/ 下载版本:MySQL Installer for Window 2.安装MySQL 以下只列出需要注意的一些界面,没出现的界面默认继续即可。 1.选择安装类型 提供了多种安装模式,包括默认开发版、仅…

汽车免拆诊断案例 | 2013 款奔驰 S300L 车起步时车身明显抖动

故障现象  一辆2013款奔驰S300L车,搭载272 946发动机,累计行驶里程约为15万km。车主反映,将挡位置于D挡,稍微释放一点制动踏板,车辆蠕动时车身明显抖动,类似气缸失火时的抖动,又类似手动变速器…

从0开始:OpenCV入门教程【图像处理基础】

图像处理基础 一、OpenCV主要功能及模块介绍 1、内置数据结构和输入/输出 OpenCV内置了丰富的与图像处理有关的数据结构,如Image、Point、Rectangle等。core模块实现了各种基本的数据结构。imgcodecs模块提供了图像文件的读写功能,用户使用简单的命令…

Scrum方法论指导下的Deepseek R1医疗AI部署开发

一、引言 1.1 研究背景与意义 在当今数智化时代,软件开发方法论对于项目的成功实施起着举足轻重的作用。Scrum 作为一种广泛应用的敏捷开发方法论,以其迭代式开发、快速反馈和高效协作的特点,在软件开发领域占据了重要地位。自 20 世纪 90 …

个人环境配置--安装记录

根据显卡下载对应的cuda和cudnn 我使用的是docker,首先拉取镜像,我用的是ubuntu20.04 加速:pull hub.1panel.dev/ devel是开发版本 sudo docker pull hub.1panel.dev/nvidia/cuda:11.6.1-devel-ubuntu20.04先测试一下cuda有没有安装好 nvcc -V更新,安装…

win10把c盘docker虚拟硬盘映射迁移到别的磁盘

c盘空间本身就比较小、如果安装了docker服务后,安装的时候没选择其他硬盘,虚拟磁盘也在c盘会占用很大的空间,像我的就三十多个G,把它迁移到其他磁盘一下子节约几十G 1、先输入下面命令查看 docker 状态 wsl -l -v 2、如果没有停止…