FunASR语音识别(解决-高并发线程问题)

文章目录

  • 一、FunASR
  • 二、上代码(队列解决线程并发问题)
  • 三、测试

一、FunASR

在我的另一个博客有介绍FunASR,并且进行了语者分离,不过最近FunASR自带了语者分离,挺好挺好,但是一直看社区就是大家都用python写,会出现线程不安全问题,群里有大佬说使用多态服务器,感觉很浪费

二、上代码(队列解决线程并发问题)

import osimport uuidimport copyimport jsonimport loggingimport queueimport threadingimport numpy as npimport torchfrom flask import Flaskfrom flask import request, jsonifyfrom modelscope.pipelines import pipelinefrom modelscope.utils.constant import Tasksapp = Flask(__name__)# 创建一个队列pipeline_queue = queue.Queue()# 实例对象的计数器来存储实例的数量created_instances = 0# logging.basicConfig(filename='app.log', level=logging.INFO)# logger = logging.getLogger('info')# # 再创建一个handler,用于输出到控制台# ch = logging.StreamHandler()# ch.setLevel(logging.INFO)# # 定义handler的输出格式# formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')# ch.setFormatter(formatter)# # 给logger添加handler# logger.addHandler(ch)def flask_content_type(req) -> dict:"""根据不同的content_type来解析数据"""if req.method == 'POST' or req.method == "PUT":if 'application/x-www-form-urlencoded' == req.content_type or 'form-data' in req.content_type:data = req.formelse:  # 无法被解析出来的数据if req.data:data = json.loads(req.data)else:raise Exception('无法解析')elif req.method == 'GET':data = req.argselse:raise Exception('不支持的请求方式')return copy.copy(data)def create_pipelines(num_pipelines):"""@Description:num_pipelines:创建pipeline实例的数量,根据你的显存大小创建,一个实例需要占用2GB"""for _ in range(num_pipelines):global created_instancesinference_pipeline = pipeline(task=Tasks.auto_speech_recognition,model='/root/autodl-tmp/models_from_modelscope/damo/speech_paraformer-large-vad-punc-spk_asr_nat-zh-cn',model_revision='v0.0.2',vad_model='/root/autodl-tmp/models_from_modelscope/damo/speech_fsmn_vad_zh-cn-16k-common-pytorch',punc_model='/root/autodl-tmp/models_from_modelscope/damo/punc_ct-transformer_cn-en-common-vocab471067-large')pipeline_queue.put(inference_pipeline)print("=========成功创建实例=========")# 更新已创建实例的数量created_instances += 1print(f"=====队列现有空闲实例数量为{pipeline_queue.qsize()}========")print(f"=====实例总数量数量为{created_instances}========")print("============================")def create_pipelines_thread(num_pipelines):# 创建线程thread = threading.Thread(target=create_pipelines, args=(num_pipelines,))# 启动线程thread.start()return threaddef default_dump(obj):"""Convert numpy classes to JSON serializable objects."""if isinstance(obj, (np.integer, np.floating, np.bool_)):return obj.item()elif isinstance(obj, np.ndarray):return obj.tolist()else:return obj@app.route('/queue_size', methods=['GET'])def get_queue_size():# 获取队列数量queue_size = pipeline_queue.qsize()# 构建响应response = {'queue_size': queue_size}# 返回响应return jsonify(response), 200@app.route('/created_instances', methods=['GET'])def get_created_instances():# 获取已创建的实例数量response = {'created_instances': created_instances}# 返回响应return jsonify(response), 200@app.route('/add_pipeline/<int:num>', methods=['GET'])def add_pipeline_queue(num):global created_instancesif (created_instances >= 10):return jsonify({'error': f"现有实例数量为{created_instances},无法再添加"})print("=========开始创建实例=========")print(f"=====队列现有空闲实例数量为{pipeline_queue.qsize()}========")thread = create_pipelines_thread(num)# 等待线程结束thread.join()print("=========实例创建结束=========")print(pipeline_queue.qsize())return jsonify({'success': f"队列现有空闲实例数量为{pipeline_queue.qsize()}!现有实例数量为{created_instances}"})@app.route('/', methods=['POST'])def result_test():dates = flask_content_type(request).copy()print(dates)return jsonify({'success': dates})@app.route('/transcribe', methods=['POST'])def transcribe():print("======队列剩余======")print(pipeline_queue.qsize())# 第一步,获取请求体if 'audio_file' in request.files:audio_file = request.files['audio_file']file_ext = os.path.splitext(audio_file.filename)[1]if file_ext.lower() not in ['.wav', '.mp3']:return jsonify({'error': str('Error: Audio file must be either .wav or .mp3')}), 500else:try:# 将音频文件保存到临时文件夹中temp_dir_path = 'temp'if not os.path.exists(temp_dir_path):os.makedirs(temp_dir_path)# 保存上传的临时文件file_extension = os.path.splitext(audio_file.filename)[1]unique_filename = str(uuid.uuid4()) + file_extensiontemp_file_path = os.path.join(temp_dir_path, unique_filename)audio_file.save(temp_file_path)return start_asr(temp_file_path)except Exception as e:return jsonify({'error': str(e)}), 500finally:# 删除临时文件os.remove(temp_file_path)else:dates = flask_content_type(request).copy()return start_asr(dates['file_url'])def start_asr(temp_file_path):import time# 记录开始时间start_time = time.time()inference_pipeline = pipeline_queue.get()# 使用 inference pipeline 进行语音转写asr_result = inference_pipeline(audio_in=temp_file_path, batch_size_token=5000,batch_size_token_threshold_s=40,max_single_segment_time=6000)try:transform = time.time() - start_timeasr_result["transform_time"] = transform# 将语音识别结果转换为json格式result = json.dumps(asr_result, ensure_ascii=False, default=default_dump)return resultexcept Exception as e:print(str(e))# 返回错误信息return jsonify({'error': str(e)}), 500finally:pipeline_queue.put(inference_pipeline)def start_flask_app(port):"""启动 Flask 应用程序并运行在指定端口上在调用 Flask 的 app.run 方法后,应用会进入监听状态,等待客户端发起请求。这意味着应用会一直停留在 app.run() 这一行,不会继续执行后续的 Python 代码。启动 Flask 应用程序前,使用多线程的方式创建:我这里是32G显存所以默认创建10个实例"""print("============================")print("======开始异步创建实例=========")print("============================")try:# 清除显卡torch.cuda.empty_cache()except Exception as e:# 返回错误信息print(e)create_pipelines_thread(5)app.run(port=port)if __name__ == '__main__':start_flask_app(9501)

三、测试

二已经给你完整的示例了,所以我就不测了,我都上生产了,你们自己用postman或者代码试一下把!有问题再联系我18956043585(微信同号)
兄弟们,这是我的解决方案,欢迎交流

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

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

相关文章

Codeforces Round #911 (Div. 2)

A.Cover in Water 题意&#xff1a; 有一个 1 n 1 \times n 1n的水池&#xff0c;里面有些格子可以加水&#xff0c;有些格子是被堵上的&#xff0c;你可以进行以下两种操作&#xff1a; 1.往一个空的格子里加水 2.移除一个有水的格子中的水&#xff0c;并将这些水添加到另…

合并区间[中等]

一、题目 以数组intervals表示若干个区间的集合&#xff0c;其中单个区间为intervals[i] [starti, endi]。请你合并所有重叠的区间&#xff0c;并返回一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间。 示例 1&#xff1a; 输入&#xff1a;intervals […

【笔记】小白学习电路维修

学习视频&#xff08;b站&#xff09;&#xff1a;从0开始学电路 从0开始学电路维修 p1 黄色长方体元件P2 故障率最高的元件p3带芯铜丝线圈是什么区分电感和变压器接入电路分析&#xff1a; p4 交流和直流分界线整流桥接线整流桥故障判断 带色环的不一定是电阻 p1 黄色长方体元…

Windows10-用户账户控制、Windows远程桌面

Windows10用户账户控制怎么设置白名单 问题引出&#xff1a; 安装低版本搜狗输入法后经常弹出用户账户控制 解决方案&#xff1a; 全局模式&#xff1a; UAC控制最早出现在Windows Vista中&#xff0c;用户帐户控制&#xff08;UAC&#xff09;是一项旨在防止对您的计算机…

Django视图层

一、请求与响应 视图函数 视图函数&#xff0c;简称视图&#xff0c;属于Django的视图层&#xff0c;默认定义在views.py文件中&#xff0c;是用来处理web请求信息以及返回响应信息的函数&#xff0c;所以研究视图函数只需熟练掌握两个对象即可&#xff1a;请求对象(HttpRequ…

web:[ZJCTF 2019]NiZhuanSiWei1

题目 点进题目&#xff0c;网页显示如下&#xff0c;需要代码审计 $_GET["text"]和$_GET["file"]来获取传入的两个参数text和file。使用isset()函数来检查$text变量是否已设置并且不为null。如果设置了并且不为null&#xff0c;则执行下面的逻辑。在下面的…

贪心算法(新坑)

贪心入门 概述&#xff1a; 贪心算法是一种在每一步选择中都采取当前最优解的策略&#xff0c;希望最终能够得到全局最优解的算法。简单来说&#xff0c;它会不断地做出局部最优的选择&#xff0c;相信通过这种选择最终能够达到全局最优。 举个例子来说明。假设你要从一个迷…

CCFCSP试题编号:202206-2试题名称:寻宝!大冒险!

一、题目 二、分析 因为藏宝图左下角位置一定是一棵树&#xff0c;所以只要把所有绿化图中每一棵树&#xff0c;与之相匹配&#xff0c;然后判断&#xff0c;是否整个藏宝图都是绿化图的一部分&#xff0c;如果是那就计数count1。所以来看&#xff0c;结果count最大也就是n(绿…

js 函数的防抖(debounce)与节流(throttle)

目录 序言&#xff1a; 防抖&#xff08;debounce&#xff09; 节流&#xff08;throttle&#xff09; 代码示例 附录&#xff1a; 关于节流/防抖函数中 context&#xff08;this&#xff09; 的指向解析&#xff1a; 防抖函数中的 this 指向 节流函数中的 this 指向 序…

进程和线程的关系

⭐ 作者&#xff1a;小胡_不糊涂 &#x1f331; 作者主页&#xff1a;小胡_不糊涂的个人主页 &#x1f4c0; 收录专栏&#xff1a;JavaEE &#x1f496; 持续更文&#xff0c;关注博主少走弯路&#xff0c;谢谢大家支持 &#x1f496; 进程&线程 1. 什么是进程PCB 2. 什么是…

高等数学零基础篇复习笔记

预备章 零基础高等数学入门知识 第一节 集合、运算与关系 第二节 三角函数与反三角函数 三角函数的公式 反三角函数 第三节 常见不等式及数列 划重点 第一章 函数、极限与连续 第一节 函数及函数的初等特性 特殊函数 反函数 函数的初等特性 ①有界性 ②奇偶性 偶函数图像…

高中生分科考试--座位编排系统

这个系统是帮我一同学的哥哥的做的座位编排系统&#xff0c;他是某个学校的教育从事者 基本需求&#xff1a;就是能够根据他提供的各个分科班级同学的成绩单来选择相同分科的考场编排&#xff08;按成绩高低&#xff09;&#xff0c;同时输入相应的考场数&#xff0c;和每个考…

OpenJudge NOI 1.8 16:矩阵剪刀石头布 c语言

描述 Bart的妹妹Lisa在一个二维矩阵上创造了新的文明。矩阵上每个位置被三种生命形式之一占据&#xff1a;石头&#xff0c;剪刀&#xff0c;布。每天&#xff0c;上下左右相邻的不同生命形式将会发生战斗。在战斗中&#xff0c;石头永远胜剪刀&#xff0c;剪刀永远胜布&#…

解决git action发布报错:Input required and not supplied: upload_url

现象&#xff1a; 这个问题死活都找不到原因&#xff0c;后来打了一段调试的代码 - name: Debug Create Release Output run: | echo "Release ID: ${{ env.RELEASE_ID }}" echo "Release Upload URL: ${{ env.RELEASE_UPLOAD_URL }}" env: RELEASE_ID: ${…

05-鸿蒙学习之State、Prop、Link用法

05-鸿蒙学习之State、Prop、Link用法 Entry Component struct StateMangement {// State 必须初始化State name: string Hello Worldbuild() {Row() {Column() {Text(this.name).StateMangement_textStyle()Button(点击).StateMangement_btnStyle(() > {this.name this.n…

JAVA技术栈JVM

**Java虚拟机&#xff08;JVM&#xff09;详细概述** Java虚拟机&#xff08;Java Virtual Machine&#xff0c;简称JVM&#xff09;是Java平台的关键组成部分&#xff0c;负责在不同操作系统上执行Java字节码。它提供了内存管理、垃圾回收、安全性等关键功能&#xff0c;使得…

[nlp] 多语言大模型不同语种/语系数据的数据配比调节

在训练多语言的大型语言模型时,调整不同语种或语系数据的比例是一个重要的问题。理想情况下,模型应该能够平等地理解并生成所有支持的语言。然而,由于某些语言的数据可能比其他语言更容易获得(例如英语比哈萨克语),因此需要采取特定的策略来确保模型不会偏向于那些数据更…

docker镜像原理

什么是镜像 容器解决应用开发、测试和部署的问题&#xff0c;而镜像解决应用部署环境问题。镜像是一个只读的容器模板&#xff0c; 打包了应用程序和应用程序所依赖的文件系统以及启动容器的配置文件&#xff0c;是启动容器的基础。镜像所打 包的文件内容就是容器的系统运行环…

C++初阶--String类的使用

string类 在C语言中&#xff0c;我们总是用char* 的类型来创建一个变量&#xff0c;存储一个字符串&#xff1b;当我们想对它进行修改或者读写时&#xff0c;需要自我创建空间和使用string.h的库函数来进行操作它&#xff1b; 而在C中&#xff0c;C专门提供了一个头文件 stri…

HNU练习七 字符串编程题7. 机器人游戏

【问题描述】 有人建造了一些机器人&#xff0c;并且将他们放置在包含n个单元的一维网格上&#xff0c;一个长度为n的字符串s代表了他们的编排方式&#xff0c;字符串中的字符既可以是.&#xff0c;也可以是0~9之间的一个数字字符&#xff0c;字符.表示开始时在相应的单元上无机…