火影 发表于 2024-9-1 09:01:01

whisper+speaker.diarization.3.1实现根据说话人转文本

主要目标是复盘一下自己的第一个本地部署的代码。起因是老师部署的任务,想实现一个有关于教育场景的进行语音转录的模子。任务交给了本小白......好吧硬着头皮上,这篇博客也主要是记载自己的遇见的各种题目,以及对一些代码的改进。需要的小伙伴可以借鉴。
一,语音转文本模子的选择
最开始去搜刮语音转文本的模子主要是whisper、Kaldi、funASR。我主要是对whisper和funASR的代码进行实现。whisper模子有好几种,base、medium、large-v1、large-v2,large-v3.我选择的是large-v2,但着实medium的翻译就差不多了,可以满意日常的需要。(large-v3不知道为什么效果并不是很好,而且还会报错,当我看到各人普遍多以为v3没有v2好使,以是毅然决然选择了v2)。funASR也不错,同时还会自动增加一些标定符号,看各人自己的选择。
这是funASR模子的效果
https://i-blog.csdnimg.cn/direct/acde1711e7e74058a903b9efcdd3b945.png
这是whisper-largev2效果
https://i-blog.csdnimg.cn/direct/38d5054834f94eccab58e88de98becf0.png
(whisper和funASR之间的具体区别各人可以参考Python情况下的语音转文本:Whisper与FunASR-百度开辟者中心 (baidu.com))
这两个模子的实现比力简朴,主要就是按照要求把情况配置好,把改装的库装好,其他没有什么比力棘手的题目。此中在funASR中有一个题目耗了我有一段时间——办理funars中没有'rich_transcription_postprocess‘的题目。着实办理的办法就是是更新funasr模子进行安装,但是之前由于在github上直接下载的模子并不是最新版本,放在pycharm中从而导致更新也没有办法,把之前下载的模子删除之后再运行就可以了。
二.说话人分离-pyannote/speaker-diarization
这次的题目主要是在说话人分离的实现上遇见了许多题目。貌似大部分都是基于pyannote/speaker-diarizatin模子实现的,各人可以找找有没有其他模子仍旧可以实现这个功能。
至于pyannote/speaker-diarization模子主要是在huggingface上面进行下载。在实现这个模子的过程中就遇见比力多的题目,耗费的时间比力久。
1.下载的权限-huggingface中token的申请
首先你必须要去huggingface中注册一个相干的账号进行token的申请,切记这里申请的token一定要是write类型的,不然后面就会出现“huggingface_hub.utils._errors.LocalEntryNotFoundError: An error happened while trying to locate the file on the Hub and we cannot find the requested files in the local cache. Please check your connection”(一定要留意,在这里我不知道耗了多久时间才办理,而且办理的办法云云简朴)
https://i-blog.csdnimg.cn/direct/97d2928d0b334085af751105dbbbfcec.png
2.网络题目标办理
固然已经申请了token但是在网络下载上还是会出现题目。这里你可以参考以下这篇博客的内容。(其他的方法我大部分都试了,就这个比力好使)办理 huggingface下载毗连不稳定导致ConnectError题目 - 七三七3 - 博客园 (cnblogs.com)
3.测试的代码
可以直接在huggingface上复制粘贴代码,或者在魔塔里,反正代码大差不差。(魔塔的实当代码有点抽象,个人发起直接在huggingface上搞,反正魔塔也是调用的huggingface)
https://i-blog.csdnimg.cn/direct/f465867212994a908a39d0521b29e8e3.png
https://i-blog.csdnimg.cn/direct/60834dd6909e41bbbeab9925eb7f45fe.png
# instantiate the pipeline
from pyannote.audio import Pipeline
import os
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
pipeline = Pipeline.from_pretrained(
"pyannote/speaker-diarization-3.0",
use_auth_token="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")

# run the pipeline on an audio file
diarization = pipeline("./yinp.mp3")

print(type(diarization))
print(diarization)
# # dump the diarization output to disk using RTTM format
# with open("audio.rttm", "w") as rttm:
#      diarization.write_rttm(rttm)
三.whisper+pyannote/speaker-diarization的整合
这里的整合代码是在网上找的,各人可以参考这篇博客【ASR代码】基于pyannote和whisper的语音辨认代码_pyannoteai-CSDN博客
这段整合代码在有些博客中单独做了一个库叫pyannote_whisper,各人可以直接把那句导包注释掉,然后直接复制粘贴整合的代码就好了(主要就是导包的题目)
下面附上的代码是我自己改过的,各人可以根据自己的需要自己改。
from pyannote.core import Segment
import model.whispers.whisper as whisper
import pickle
import torch
import time
import os
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"

from zhconv import convert
from pyannote.audio import Pipeline
from pyannote.core import Annotation
file = "umz7m-x8yym.mp3"

def get_text_with_timestamp(transcribe_res):
    print(transcribe_res)
    timestamp_texts = []
    for item in transcribe_res["segments"]:
      start = item["start"]
      end = item["end"]
      # text = convert(item["text"],'zh-cn').strip()
      text = item["text"]
      timestamp_texts.append((Segment(start, end), text))
    return timestamp_texts


def add_speaker_info_to_text(timestamp_texts, ann):
    spk_text = []
    for seg, text in timestamp_texts:
      print(ann.crop(seg))
      spk = ann.crop(seg).argmax()
      spk_text.append((seg, spk, text))
    # print("spk_text是:",spk_text)
    return spk_text


def merge_cache(text_cache):
    sentence = ''.join( for item in text_cache])
    spk = text_cache
    start = round(text_cache.start, 1)
    end = round(text_cache[-1].end, 1)
    return Segment(start, end), spk, sentence


PUNC_SENT_END = ['.', '?', '!', "。", "?", "!"]


def merge_sentence(spk_text):
    merged_spk_text = []
    pre_spk = None
    text_cache = []
    for seg, spk, text in spk_text:
      if spk != pre_spk and len(text_cache) > 0:
            merged_spk_text.append(merge_cache(text_cache))
            text_cache = [(seg, spk, text)]
            pre_spk = spk
      elif spk == pre_spk and text == text_cache[-1]:
            print(text_cache[-1])
            # print(text)
            continue

            # merged_spk_text.append(merge_cache(text_cache))
            # text_cache.append((seg, spk, text))
            # pre_spk = spk
      else:
            text_cache.append((seg, spk, text))
            pre_spk = spk
    if len(text_cache) > 0:
      merged_spk_text.append(merge_cache(text_cache))
    return merged_spk_text


def diarize_text(transcribe_res, diarization_result):
    timestamp_texts = get_text_with_timestamp(transcribe_res)
    spk_text = add_speaker_info_to_text(timestamp_texts, diarization_result)
    res_processed = merge_sentence(spk_text)
    # print("res_processeds是:",res_processed)
    # res_processed = spk_text
    return res_processed



# def write_to_txt(spk_sent, file):
#   with open(file, 'w') as fp:
#         for seg, spk, sentence in spk_sent:
#             line = f'{seg.start:.2f} {seg.end:.2f} {spk} {sentence}\n'
#             fp.write(line)
# def format_time(seconds):
#   # 计算小时、分钟和秒数
#   hours = seconds // 3600
#   minutes = (seconds % 3600) // 60
#   seconds = seconds % 60

#   # 格式化输出
#   return f"{hours:02d}:{minutes:02d}:{seconds:02d}"
if __name__ == "__main__":
    sd_config_path = "./speaker-diarization-3.1/config.yaml"
    asr_model = whisper.load_model("large-v2")
    asr_model.to(torch.device("cuda"))

    speaker_diarization = Pipeline.from_pretrained(sd_config_path,
                                                   use_auth_token="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")
    speaker_diarization.to(torch.device("cuda"))
    # files = os.listdir("/root/autodl-tmp/Fun19/audios")

    # for file in files:
    start_time = time.time()
    print(file)

    dialogue_path = "./audios_txt/" + file.split(".") + ".pkl"
    audio = "./audios_wav/" + file
    asr_result = asr_model.transcribe(audio,
                                        initial_prompt="随便")
    asr_time = time.time()
    print("ASR time:" + str(asr_time - start_time))

    diarization_result: Annotation = speaker_diarization(audio)
    final_result = diarize_text(asr_result, diarization_result)


    dialogue = []
    for segment, spk, sent in final_result:
      content = {'speaker': spk, 'start': segment.start, 'end': segment.end, 'text': sent}
      dialogue.append(content)
      # print("_______________________________")
      print("[%.2fs -> %.2fs] %s %s" % (segment.start, segment.end, spk,sent))
      end_time = time.time()
      # print(file + " spend time:" + str(end_time - start_time))

    # with open(dialogue_path, 'wb') as f:
    #   pickle.dump(dialogue, f)
    # end_time = time.time()
    # print(file + " spend time:" + str(end_time - start_time)) 四、反思+写在最后
着实各人要是不想要这么贫苦可以直接调用科大讯飞的API,我感觉效果也挺好的,有各种选择,还能实现实时的转录,真的还不错。(但是老师不让我调用api,非得用开源的代码实现。)
具体实现可以参考基于讯飞接口的语音辨认(python)_python 用webapi调用讯飞语音辨认方法-CSDN博客
https://i-blog.csdnimg.cn/direct/554393fb5a4d41b5a518263b8b904dc3.png
着实效果最好的是通义听悟,毕竟是阿里做的效果真的非常好,他会对你上传的视频的语音进行分析,不光能根据说话人进行转录(翻译的准确度非常高)而且另有大模子的辅助,真的强。如果只是想要对视频语音进行分析并没有什么其他要求的,猛烈保举通义听悟,真的很强。通义 (aliyun.com)
https://i-blog.csdnimg.cn/direct/a83bf8bdf6c2485b9d1e7769b39cf748.png
如果是要进行语音分析这里主要是在huggingface(Models - Hugging Face)和魔塔(模子库首页 · 魔搭社区 (modelscope.cn))上去找模子。
至此,我的阶段性任务已经完成,主要是组里没有人搞语音,师兄师姐没法帮,只能自己摸索。老师说要慢慢优化,去搞懂他们是对语音的什么特性进行了提取。这就涉及到深度学习神经网络的相干知识了。我还不怎么会。慢慢学!
最后,告诉自己也勉励各人。心态要好,题目只要存在就一定能办理。并且信赖自己,可以有我们不会的,但是没有我们搞不会的!桥到船头天然直!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: whisper+speaker.diarization.3.1实现根据说话人转文本