# dspeech
**Repository Path**: iint/dspeech
## Basic Information
- **Project Name**: dspeech
- **Description**: DSpeech 是一个用于语音处理任务的高级工具包,支持任务包括语音转录、语音活动检测(VAD)、标点符号添加、情感分类、语音生成、语音克隆等等。该工具包基于最先进的模型构建,提供了简单易用的接口来处理各种语音处理任务。
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2024-10-14
- **Last Updated**: 2024-10-25
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# DSpeech:语音处理工具包
[English](README.md) | 中文
DSpeech 是一个用于语音处理任务的高级命令行工具包,支持任务包括语音转录、语音活动检测(VAD)、标点符号添加和情感分类。该工具包基于最先进的模型构建,提供了简单易用的接口来处理各种语音处理任务。
## 安装
### 依赖
- Python 3.6 或更高版本
- PyTorch 1.7 或更高版本
- torchaudio
- rich
- soundfile
- funasr(一个轻量级的语音处理自动模型库)
注意本工具基本只是针对funasr的封装,建议参考funasr的文档进行安装或直接使用funasr。
### 安装步骤
1. 克隆仓库:
```bash
git clone https://gitee.com/iint/dspeech.git
cd dspeech
```
2. 安装所需的依赖包:
```bash
pip install -r requirements.txt
```
或者直接通过pip安装dspeech:
```bash
pip install dspeech
```
3. 设置 `DSPEECH_HOME` 环境变量,指向存储模型的目录:
```bash
export DSPEECH_HOME=/path/to/dspeech/models
# 如果使用169服务器,可以设置为
# export DSPEECH_HOME=/models/dspeech_models
```
4. 下载所需模型并将其放置在 `DSPEECH_HOME` 目录中。可以使用以下命令下载模型(将 `` 替换为实际模型 ID):
```bash
export HF_ENDPOINT=https://hf-mirror.com
huggingface-cli download --resume-download --local-dir $DSPEECH_HOME/
```
6. (可选)如果需要进行说话人分离任务,可以安装 Dguard:
```bash
pip install dguard==0.1.20
export DGUARD_MODEL_PATH=
dguard_info
# 如果使用169服务器,可以设置为
# export DGUARD_MODEL_PATH=/models/dguard_model
```
7. 打印帮助信息以查看可用命令:
```bash
dspeech help
```
应该看到可用命令和选项的列表。
```
DSpeech: A Command-line Speech Processing Toolkit
Usage: dspeech
Commands:
help Show this help message
transcribe Transcribe an audio file
vad Perform VAD on an audio file
punc Add punctuation to a text
emo Perform emotion classification on an audio file
clone Clone speaker's voice and generate audio
clone_with_emo Clone speaker's voice with emotion and generate audio
Options (for asr and emotion classify):
--model Model name (default: sensevoicesmall)
--vad-model VAD model name (default: fsmn-vad)
--punc-model Punctuation model name (default: ct-punc)
--emo-model Emotion model name (default: emotion2vec_plus_large)
--device Device to run the models on (default: cuda)
--file Audio file path for transcribing, VAD, or emotion classification
--text Text to process with punctuation model
--start Start time in seconds for processing audio files (default: 0)
--end End time in seconds for processing audio files (default: end of file)
--sample-rate Sample rate of the audio file (default: 16000)
Options (for tts):
--ref_audio Reference audio file path for voice cloning
--ref_text Reference text for voice cloning
--speaker_folder Speaker folder path for emotional voice cloning
--text Text to generate audio
--audio_save_path Path to save the audio
--spectrogram_save_path * [Optional] Path to save the spectrogram
--speed Speed of the audio
--sample_rate Sample rate of the audio file (default: 16000)
Example: dspeech transcribe --file audio.wav
```
## 功能介绍
DSpeech 提供以下功能:
- **语音转录**:使用最先进的语音识别模型将音频文件转换为文本。
- **语音活动检测 (VAD)**:检测并分割音频文件中的语音片段。
- **标点符号添加**:为原始文本转录添加标点符号以提高可读性。
- **情感分类**:将音频文件的情感内容分类为不同类别。
- **声音克隆**:使用文本到语音 (TTS) 模型克隆指定音频的声音。
- **情感 TTS**:使用 TTS 模型生成带有情感的语音。
## dspeech.STT模块
在 Python 脚本中使用 DSpeech,可以导入 `STT` 类并使用所需的模型创建实例:
```python
from dspeech.stt import STT
# 使用指定模型初始化 STT 处理器
handler = STT(model_name="paraformer-zh", vad_model="fsmn-vad", punc_model="ct-punc", emo_model="emotion2vec_plus_large")
# 转录音频文件
transcription = handler.transcribe_file("audio.wav")
print(transcription)
# 对音频文件执行 VAD
vad_result = handler.vad_file("audio.wav")
print(vad_result)
# 为文本添加标点符号
punctuation_text = handler.punc_result("this is a test")
print(punctuation_text)
# 对音频文件进行情感分类
emotion_result = handler.emo_classify_file("audio.wav")
print(emotion_result)
```
## dspeech.TTS模块
### 初始化
要初始化 `TTS` 模块,创建一个 `TTS` 处理器对象,并指定目标设备(CPU 或 GPU)和生成音频的采样率。
```python
from dspeech import TTS
import torch
# 初始化 TTS 处理器
tts_handler = TTS(
device="cuda", # 如果没有 GPU 可用,使用 "cpu"
target_sample_rate=24000 # 定义生成音频的目标采样率
)
```
`device` 参数可以设置为 "cuda" 以使用 GPU,或者设置为 "cpu" 以使用 CPU。
### 基本声音克隆
在基本声音克隆中,你提供一个参考音频和文本,系统将生成一个新语音,该语音模仿参考音频中的声音,并且内容为提供的文本。
```python
import torchaudio
# 使用 torchaudio 加载参考音频
ref_audio, sample_rate = torchaudio.load("tests/a.wav")
# 基于参考音频和文本克隆声音
r = tts_handler.clone(
ref_audio=(ref_audio, sample_rate), # 参考音频,格式为 (Tensor, int) 或文件路径
ref_text="参考文本", # 参考音频的转录文本
gen_text_batches=["你好,我叫小明", "我是一名AI", "我会说中文"], # 需要生成语音的文本
speed=1, # 语速(1 为正常速度)
channel=-1, # 合并所有通道(-1)或指定一个通道
remove_silence=True, # 是否从参考音频中去除静音部分
wave_path="tests/tts_output.wav", # 生成的音频保存路径
spectrogram_path="tests/tts_output.png", # 生成的音频频谱图保存路径
concat=True # 是否将生成的所有音频合并为一个文件
)
```
**参数说明:**
- `ref_audio`:参考音频,格式为 `(Tensor, int)` 或文件路径。
- `ref_text`:参考音频的转录文本。
- `gen_text_batches`:要转为语音的一组文本列表。
- `speed`:调整生成语音的速度(默认值为 1,即正常速度)。
- `remove_silence`:是否去除参考音频中的静音(布尔值)。
- `wave_path`:生成的音频文件保存路径。
- `spectrogram_path`:生成的音频频谱图保存路径,用于进行可视化分析。
### 提取说话人信息
对于包含多个说话人和情感的复杂声音克隆任务,你需要从包含不同说话人和情感的音频文件目录中提取说话人信息。目录结构应如下所示:
```
/
├── speaker1/
│ ├── happy.wav
│ ├── happy.txt
│ ├── neutral.wav
│ ├── neutral.txt
```
每个子目录代表一个说话人,每个音频文件应有相应的文本文件。
```python
# 从目录中提取说话人信息
spk_info = tts_handler.get_speaker_info("tests/speaker")
print(spk_info)
```
该函数返回一个说话人信息的字典,用于高级克隆任务。
### 带情感的声音克隆
要生成带情感表达的声音克隆,可以使用 `clone_with_emo` 方法。生成的文本应包含情感标记,例如 `[[zhaosheng_angry]]`,其中 `zhaosheng` 是说话人,`angry` 是情感。
```python
r = tts_handler.clone_with_emo(
gen_text_batches=[
"[[zhaosheng_angry]] 你怎么能这样对我说话?太过分了!",
"[[zhaosheng_whisper]] 小心点,别让任何人听见,这是秘密。",
"[[zhaosheng_sad]] 我真的很难过,事情已经失控了。"
],
speaker_info=spk_info, # 说话人信息字典
speed=1, # 语速
channel=-1, # 合并所有通道
remove_silence=True, # 从生成的输出中去除静音
wave_path="tests/tts_output_emo.wav", # 带情感的生成音频保存路径
spectrogram_path="tests/tts_output_emo.png" # 带情感的生成频谱图保存路径
)
```
### 多说话人和多情感对话
要生成包含多个说话人和不同情感的对话,请确保 `tests/speaker` 目录中包含每个说话人的子目录,并且每个情感的音频和文本文件存在。
```python
# 提取多个说话人的信息
spk_info = tts_handler.get_speaker_info("tests/speaker")
# 生成多说话人和多情感对话
r = tts_handler.clone_with_emo(
gen_text_batches=[
"[[xieyukai_angry]] 你怎么能这样对我说话?太过分了!",
"[[duanyibo_whisper]] 我真的很难过,事情已经失控了。"
],
speaker_info=spk_info
, # 包含多个说话人的字典
speed=1, # 语速
channel=-1, # 合并所有通道
remove_silence=True, # 去除生成的静音
wave_path="tests/tts_output_emo_multi.wav", # 保存生成音频的路径
spectrogram_path="tests/tts_output_emo_multi.png" # 保存生成频谱图的路径
)
```
## 命令行界面
DSpeech 提供了命令行接口,便于快速访问其功能。要查看可用的命令,请运行:
```bash
dspeech help
DSpeech:命令行语音处理工具包
Usage: dspeech
Commands:
transcribe 转录音频文件
vad 对音频文件执行语音活动检测 (VAD)
punc 为文本添加标点符号
emo 对音频文件进行情感分类
Options:
--model 模型名称 (默认: sensevoicesmall)
--vad-model VAD 模型名称 (默认: fsmn-vad)
--punc-model 标点符号模型名称 (默认: ct-punc)
--emo-model 情感模型名称 (默认: emotion2vec_plus_large)
--device 运行模型的设备 (默认: cuda)
--file 用于转录、VAD 或情感分类的音频文件路径
--text 用于标点处理的文本
--start 处理音频文件的开始时间(以秒为单位,默认: 0)
--end 处理音频文件的结束时间(以秒为单位,默认: 文件末尾)
--sample-rate 音频文件的采样率 (默认: 16000)
Example: dspeech transcribe --file audio.wav
```
### 使用示例
- **转录音频文件**:
```bash
dspeech transcribe --file audio.wav
```
- **对音频文件执行语音活动检测 (VAD)**:
```bash
dspeech vad --file audio.wav
```
- **为文本添加标点符号**:
```bash
dspeech punc --text "this is a test"
```
- **对音频文件进行情感分类**:
```bash
dspeech emo --file audio.wav
```
## 许可
DSpeech 遵循 MIT 许可证。有关详细信息,请参阅 LICENSE 文件。
## 与Dguard的集成
### 实例一:利用`dspeech`和`dguard`实现电话转录(说话人标签+文本+情感)
```python
# coding = utf-8
# @Time : 2024-10-13 08:21:58
# @Author : zhaosheng@nuaa.edu.cn
# @Describe: Preprocess the media file.
# pip install dspeech==0.0.1 dguard==0.1.21
# export DGUARD_MODEL_PATH=/models/dguard_models
# export DSPEECH_HOME=/models/dspeech_models
from dspeech import STT
from dguard import DguardModel as dm
from rich.console import Console
console = Console()
# init asr model
stt_model = STT()
# init dguard model
dm_model = dm(
embedding_model_names=["eres2net_cn_common_200k", "campp_cn_common_200k"],
device="cuda",
length=10, # 每个片段10秒
channel=0, # 选择第一个通道
max_split_num=5, # 最多分割5个片段
start_time=0, # 每个音频从0秒开始处理
mean=True, # 返回所有片段特征的平均值
verbose=True, # 输出详细日志,默认在DGUARD_MODEL_PATH/logs/%Y%m%d-%H%M%S.log
apply_vad=True, # 声纹编码前自动应用VAD
vad_smooth_threshold=0.25, # VAD处理的平滑阈值,两个语音段之间的间隔小于该值时合并
vad_min_duration=0.3, # VAD处理的最小语音段持续时间,平滑后的语音段小于该值时被丢弃
save_vad_path=None, # 不自动保存VAD结果
diar_num_spks=None,
diar_min_num_spks=1,
diar_max_num_spks=4,
diar_min_duration=0.3,
diar_window_secs=1.5,
diar_period_secs=0.75,
diar_frame_shift=10,
diar_batch_size=4, # 聚类时进行子片段声纹编码的批处理大小
diar_subseg_cmn=True
)
def rich_print(content):
colors = ["red", "green", "blue", "yellow", "magenta", "cyan"]
for idx, line in enumerate(content.split("\n")):
if ":" not in line:
continue
spk_id = line.split(":")[0].split(" ")[-1]
console.print(f"[{colors[int(spk_id) % 6]}]{line}")
def get_diarization_content(file_path, emotion_time_threshold=2):
# Step 1: Speaker Diarization
r = dm_model.diarize(file_path)
# [('dguard', 0.322, 3.352, 0), ('dguard', 3.49, 6.36, 2), ('dguard', 7.298, 8.423, 3),
# ('dguard', 47.81, 48.19, 2), ('dguard', 48.578, 49.148, 2), ...]
# Step 2: Speech-to-Text
all_content = ""
last_spk = ""
for data in dm_model.diarize(file_path):
spk_label = data[3]
start_time = data[1]
end_time = data[2]
generate_text = stt_model.transcribe_file(file_path, start=start_time, end=end_time)
# generate_text is the transcribed text(not punctuated)
if end_time - start_time > emotion_time_threshold:
# We only classify the emotion when the duration is longer than seconds
# So, if you dont need the emotion, you can set emotion_time_threshold to a large number such as 1000. :)
# Next, get the speech emotion
emotion = stt_model.emo_classify_file(file_path, start=start_time, end=end_time)
# {'key': 'rand_key_2j1IfWqrAz2Kr',
# 'labels': ['生气/angry', '厌恶/disgusted', '恐惧/fearful', '开心/happy', '中立/neutral', '其他/other', '难过/sad', '吃惊/surprised', ''],
# 'scores': [3.02, 0.20, 1.07e-05, 0.01, 0.78, 2e-06, 7e-06, 8e-06, 6e-08]}
# get the emotion label
emotion_label = emotion["labels"][emotion["scores"].index(max(emotion["scores"]))]
emotion_score = max(emotion["scores"])
emotion_text = f"(emotion:{emotion_label} with score: {emotion_score:.2f})"
else:
emotion_text = ""
if spk_label != last_spk:
all_content += f"\nSpeaker {spk_label}: {generate_text} "+emotion_text
last_spk = spk_label
else:
all_content += f" {generate_text}"
return all_content
if __name__ == "__main__":
file1 = "/home/zhaosheng/Documents/dguard_project/test/data/1channel2person.wav"
content = get_diarization_content(file1)
rich_print(content)
```
您应该能在终端看到类似以下的输出(彩色输出):
```bash
Speaker 0: 工号一零
Speaker 1: 平平安
Speaker 0: 二为您服务 您好长安时代工号幺零零幺为您服务请问有需要帮您的
Speaker 1: 哎哎你好我想问一下我嗯啊我那那个网上买的那个呃注册卡嘛然后我 emotion:中立/neutral with score: 1.00 现在激活 啊 自助激活嘛然后是不是 我呃是不是不是那个什么 卡片加那个身份证是不是这样子
Speaker 0: 对是的
Speaker 1: 哦我你你帮我查一下这个号码呃这这这能不能通过哈 emotion:中立/neutral with score: 0.78
Speaker 0: 好的号码您说一下 唉幺七幺七幺
Speaker 1: 零八三九
Speaker 0: 八三九
Speaker 1: 一四四八
Speaker 0: 七四四八好的稍等啊帮您去看一下 emotion:中立/neutral with score: 1.00
Speaker 1: 嗯 看一下
Speaker 0: 等啊 问一下您的 可以的你这个应该可以通过审核的我这边稍后给您催促一下好吧
Speaker 1: 哦哦哦好哦行行行按呃我上面有一有一张那个尾号是七 emotion:开心/happy with score: 0.95 七四五五的那一张我弄错了能不能
Speaker 0: 稍等七四五五是吧 您是不是同时激活了好几张号码
Speaker 1: 啊对
Speaker 0: 那您记住姓名七四五五的告诉我呃记住姓名和身份证后六位嘞 emotion:开心/happy with score: 1.00
Speaker 1: 好好好好好 呃身份证后六位是 嗯 二二五二三幺
Speaker 0: 呃您的姓名
Speaker 1: 人轻有
Speaker 0: 好的跟您说一下啊您七四五五再充五块钱然后您这个七四是把我稍后让 emotion:开心/happy with score: 1.00 呃其他人员给您审一下好吧
Speaker 1: 啊行行行我知道我就是说我这张刚才那个呃激活弄错弄错了 emotion:中立/neutral with score: 0.57 弄错了然后呃呃现现在能不能通过
Speaker 0: 嗯跟您说一下啊七四五五已经通过审核了但是您欠费五块钱补上以后就可以用了 emotion:开心/happy with score: 1.00 然后刚刚那个号码因为您七四五五 呃欠费五块钱所以那个没有通过审核 然后您把七四五五的充上钱以后我再
嗯催促一下审核好吧
Speaker 1: 好好好好
Speaker 0: 哎好的您去操作一下七四五五的充值然后这边 emotion:开心/happy with score: 1.00 稍后看到了会给七四四八 给您催促一下好吧
Speaker 1: 啊好好好
Speaker 0: 好的还有其他需要帮助吗
Speaker 1: 啊没有没有啊嗯嗯哎好的感现在就现在就是七四四八已经通过审核通过了对吧 emotion:中立/neutral with score: 1.00
Speaker 0: 不是七十四 因为您七四五五的 欠费五块钱您先把这钱充上以后然后我再给您 安排他们去给您审核七四四八好吧
Speaker 1: 哦哦好行行行行行行行
Speaker 0: 好的你尽快去操作不然他们给你审又拒掉了 emotion:开心/happy with score: 1.00
Speaker 1: 嗯嗯嗯好的好的好的好的
Speaker 0: 唉好的还有其他需要帮助吗
Speaker 1: 啊没有没有嗯嗯
Speaker 0: 哎好的感谢来电
Speaker 1: 啊
```