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

打印 上一主题 下一主题

主题 848|帖子 848|积分 2544

主要目标是复盘一下自己的第一个本地部署的代码。起因是老师部署的任务,想实现一个有关于教育场景的进行语音转录的模子。任务交给了本小白......好吧硬着头皮上,这篇博客也主要是记载自己的遇见的各种题目,以及对一些代码的改进。需要的小伙伴可以借鉴。
一,语音转文本模子的选择
最开始去搜刮语音转文本的模子主要是whisper、Kaldi、funASR。我主要是对whisper和funASR的代码进行实现。whisper模子有好几种,base、medium、large-v1、large-v2,large-v3.我选择的是large-v2,但着实medium的翻译就差不多了,可以满意日常的需要。(large-v3不知道为什么效果并不是很好,而且还会报错,当我看到各人普遍多以为v3没有v2好使,以是毅然决然选择了v2)。funASR也不错,同时还会自动增加一些标定符号,看各人自己的选择。
这是funASR模子的效果

这是whisper-largev2效果

(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”(一定要留意,在这里我不知道耗了多久时间才办理,而且办理的办法云云简朴)

2.网络题目标办理
固然已经申请了token但是在网络下载上还是会出现题目。这里你可以参考以下这篇博客的内容。(其他的方法我大部分都试了,就这个比力好使)办理 huggingface下载毗连不稳定导致ConnectError题目 - 七三七3 - 博客园 (cnblogs.com)
3.测试的代码
可以直接在huggingface上复制粘贴代码,或者在魔塔里,反正代码大差不差。(魔塔的实当代码有点抽象,个人发起直接在huggingface上搞,反正魔塔也是调用的huggingface)


  1. # instantiate the pipeline
  2. from pyannote.audio import Pipeline
  3. import os
  4. os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
  5. pipeline = Pipeline.from_pretrained(
  6.   "pyannote/speaker-diarization-3.0",
  7.   use_auth_token="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")
  8. # run the pipeline on an audio file
  9. diarization = pipeline("./yinp.mp3")
  10. print(type(diarization))
  11. print(diarization)
  12. # # dump the diarization output to disk using RTTM format
  13. # with open("audio.rttm", "w") as rttm:
  14. #      diarization.write_rttm(rttm)
复制代码
三.whisper+pyannote/speaker-diarization的整合
这里的整合代码是在网上找的,各人可以参考这篇博客【ASR代码】基于pyannote和whisper的语音辨认代码_pyannoteai-CSDN博客
这段整合代码在有些博客中单独做了一个库叫pyannote_whisper,各人可以直接把那句导包注释掉,然后直接复制粘贴整合的代码就好了(主要就是导包的题目)
下面附上的代码是我自己改过的,各人可以根据自己的需要自己改。
  1. from pyannote.core import Segment
  2. import model.whispers.whisper as whisper
  3. import pickle
  4. import torch
  5. import time
  6. import os
  7. os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
  8. from zhconv import convert
  9. from pyannote.audio import Pipeline
  10. from pyannote.core import Annotation
  11. file = "umz7m-x8yym.mp3"
  12. def get_text_with_timestamp(transcribe_res):
  13.     print(transcribe_res)
  14.     timestamp_texts = []
  15.     for item in transcribe_res["segments"]:
  16.         start = item["start"]
  17.         end = item["end"]
  18.         # text = convert(item["text"],'zh-cn').strip()
  19.         text = item["text"]
  20.         timestamp_texts.append((Segment(start, end), text))
  21.     return timestamp_texts
  22. def add_speaker_info_to_text(timestamp_texts, ann):
  23.     spk_text = []
  24.     for seg, text in timestamp_texts:
  25.         print(ann.crop(seg))
  26.         spk = ann.crop(seg).argmax()
  27.         spk_text.append((seg, spk, text))
  28.     # print("spk_text是:",spk_text)
  29.     return spk_text
  30. def merge_cache(text_cache):
  31.     sentence = ''.join([item[-1] for item in text_cache])
  32.     spk = text_cache[0][1]
  33.     start = round(text_cache[0][0].start, 1)
  34.     end = round(text_cache[-1][0].end, 1)
  35.     return Segment(start, end), spk, sentence
  36. PUNC_SENT_END = ['.', '?', '!', "。", "?", "!"]
  37. def merge_sentence(spk_text):
  38.     merged_spk_text = []
  39.     pre_spk = None
  40.     text_cache = []
  41.     for seg, spk, text in spk_text:
  42.         if spk != pre_spk and len(text_cache) > 0:
  43.             merged_spk_text.append(merge_cache(text_cache))
  44.             text_cache = [(seg, spk, text)]
  45.             pre_spk = spk
  46.         elif spk == pre_spk and text == text_cache[-1][2]:
  47.             print(text_cache[-1][2])
  48.             # print(text)
  49.             continue
  50.             # merged_spk_text.append(merge_cache(text_cache))
  51.             # text_cache.append((seg, spk, text))
  52.             # pre_spk = spk
  53.         else:
  54.             text_cache.append((seg, spk, text))
  55.             pre_spk = spk
  56.     if len(text_cache) > 0:
  57.         merged_spk_text.append(merge_cache(text_cache))
  58.     return merged_spk_text
  59. def diarize_text(transcribe_res, diarization_result):
  60.     timestamp_texts = get_text_with_timestamp(transcribe_res)
  61.     spk_text = add_speaker_info_to_text(timestamp_texts, diarization_result)
  62.     res_processed = merge_sentence(spk_text)
  63.     # print("res_processeds是:",res_processed)
  64.     # res_processed = spk_text
  65.     return res_processed
  66. # def write_to_txt(spk_sent, file):
  67. #     with open(file, 'w') as fp:
  68. #         for seg, spk, sentence in spk_sent:
  69. #             line = f'{seg.start:.2f} {seg.end:.2f} {spk} {sentence}\n'
  70. #             fp.write(line)
  71. # def format_time(seconds):
  72. #     # 计算小时、分钟和秒数
  73. #     hours = seconds // 3600
  74. #     minutes = (seconds % 3600) // 60
  75. #     seconds = seconds % 60
  76. #     # 格式化输出
  77. #     return f"{hours:02d}:{minutes:02d}:{seconds:02d}"
  78. if __name__ == "__main__":
  79.     sd_config_path = "./speaker-diarization-3.1/config.yaml"
  80.     asr_model = whisper.load_model("large-v2")
  81.     asr_model.to(torch.device("cuda"))
  82.     speaker_diarization = Pipeline.from_pretrained(sd_config_path,
  83.                                                    use_auth_token="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")
  84.     speaker_diarization.to(torch.device("cuda"))
  85.     # files = os.listdir("/root/autodl-tmp/Fun19/audios")
  86.     # for file in files:
  87.     start_time = time.time()
  88.     print(file)
  89.     dialogue_path = "./audios_txt/" + file.split(".")[0] + ".pkl"
  90.     audio = "./audios_wav/" + file
  91.     asr_result = asr_model.transcribe(audio,
  92.                                         initial_prompt="随便")
  93.     asr_time = time.time()
  94.     print("ASR time:" + str(asr_time - start_time))
  95.     diarization_result: Annotation = speaker_diarization(audio)
  96.     final_result = diarize_text(asr_result, diarization_result)
  97.     dialogue = []
  98.     for segment, spk, sent in final_result:
  99.         content = {'speaker': spk, 'start': segment.start, 'end': segment.end, 'text': sent}
  100.         dialogue.append(content)
  101.         # print("_______________________________")
  102.         print("[%.2fs -> %.2fs] %s %s" % (segment.start, segment.end, spk,sent))
  103.         end_time = time.time()
  104.         # print(file + " spend time:" + str(end_time - start_time))
  105.     # with open(dialogue_path, 'wb') as f:
  106.     #     pickle.dump(dialogue, f)
  107.     # end_time = time.time()
  108.     # print(file + " spend time:" + str(end_time - start_time))
复制代码
四、反思+写在最后
着实各人要是不想要这么贫苦可以直接调用科大讯飞的API,我感觉效果也挺好的,有各种选择,还能实现实时的转录,真的还不错。(但是老师不让我调用api,非得用开源的代码实现。)
具体实现可以参考基于讯飞接口的语音辨认(python)_python 用webapi调用讯飞语音辨认方法-CSDN博客

着实效果最好的是通义听悟,毕竟是阿里做的效果真的非常好,他会对你上传的视频的语音进行分析,不光能根据说话人进行转录(翻译的准确度非常高)而且另有大模子的辅助,真的强。如果只是想要对视频语音进行分析并没有什么其他要求的,猛烈保举通义听悟,真的很强。通义 (aliyun.com)

如果是要进行语音分析这里主要是在huggingface(Models - Hugging Face)和魔塔(模子库首页 · 魔搭社区 (modelscope.cn))上去找模子。
至此,我的阶段性任务已经完成,主要是组里没有人搞语音,师兄师姐没法帮,只能自己摸索。老师说要慢慢优化,去搞懂他们是对语音的什么特性进行了提取。这就涉及到深度学习神经网络的相干知识了。我还不怎么会。慢慢学!
最后,告诉自己也勉励各人。心态要好,题目只要存在就一定能办理。并且信赖自己,可以有我们不会的,但是没有我们搞不会的!桥到船头天然直!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

火影

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表