用SenseVoice进行语音转文字的时候,发现模型不会生成时间戳,只会输出文本的情况。所以对文本的输出进行了修改,仅作参考。
最开始的时候,我想的是在模型里面进行修改,促使模型的输出自带一个时间戳,也尝试了他们给的方法:
alignment, scores = torchaudio.functional.forced_align(ctc_probs, preds.unsqueeze(0), None, None, blank=0)
也加在模型里面试了试,发现可以输出单个字的的时间戳,后续我想转成句子的时候,发现模型输出的时间戳是正序的,但是句子的顺序不是正序的。然后每个句子的起始时间都是0,反正错的很离谱,大概如下:
解决办法:
针对funasr推理(demo1.py)里面的内容进行修改,在进行模型推理前,先用模型fsmn-vad模型处理了音频,我们可以看一看fsmn-vad模型的介绍:models/speech_fsmn_vad_zh-cn-16k-common-pytorch/README.md · yuekai/paraformerX at main (huggingface.co)https://huggingface.co/yuekai/paraformerX/blob/main/models/speech_fsmn_vad_zh-cn-16k-common-pytorch/README.md
它可以有效的对时间戳进行处理,在我们得到了开始时间和结束时间以后,再最终的输出上可以进行打印或者保存。整体代码如下:
from funasr import AutoModel
from funasr.utils.postprocess_utils import rich_transcription_postprocess
import soundfile as sf # 用于读取和裁剪音频文件
import os
import pandas as pd
# 模型路径
model_dir = "iic/SenseVoiceSmall"
vad_model_dir = "fsmn-vad" # VAD模型路径
# 音频文件路径
audio_file_path = '音频路径'
# 加载VAD模型
vad_model = AutoModel(
model=vad_model_dir,
trust_remote_code=True,
remote_code="./model.py",
device="cuda:0",
disable_update=True
)
# 使用VAD模型处理音频文件
vad_res = vad_model.generate(
input=audio_file_path,
cache={},
max_single_segment_time=30000, # 最大单个片段时长
)
# 从VAD模型的输出中提取每个语音片段的开始和结束时间
segments = vad_res[0]['value'] # 假设只有一段音频,且其片段信息存储在第一个元素中
# 加载原始音频数据
audio_data, sample_rate = sf.read(audio_file_path)
# 定义一个函数来裁剪音频
def crop_audio(audio_data, start_time, end_time, sample_rate):
start_sample = int(start_time * sample_rate / 1000) # 转换为样本数
end_sample = int(end_time * sample_rate / 1000) # 转换为样本数
return audio_data[start_sample:end_sample]
# 加载SenseVoice模型
model = AutoModel(
model=model_dir,
trust_remote_code=True,
remote_code="./model.py",
device="cuda:0",
disable_update=True
)
# 对每个语音片段进行处理
results = []
for segment in segments:
start_time, end_time = segment # 获取开始和结束时间
cropped_audio = crop_audio(audio_data, start_time, end_time, sample_rate)
# 将裁剪后的音频保存为临时文件
temp_audio_file = "temp_cropped.wav"
sf.write(temp_audio_file, cropped_audio, sample_rate)
# 语音转文字处理
res = model.generate(
input=temp_audio_file,
cache={},
language="auto", # 自动检测语言
use_itn=True,
batch_size_s=60,
merge_vad=True, # 启用 VAD 断句
merge_length_s=10000, # 合并长度,单位为毫秒
)
# 处理输出结果
text = rich_transcription_postprocess(res[0]["text"])
# 添加时间戳
results.append({"start": start_time // 1000, "end": end_time // 1000, "text": text}) # 转换为秒
# 输出结果
for result in results:
print(f"Start: {result['start']} s, End: {result['end']} s, Text: {result['text']}")
另外附上阿里开源的SenseVoice模型的地址:
说明:该方法可能不是最佳方法,如果有更棒的方法,欢迎交流!!!