实战指南:封装Whisper为FastAPI接口并实现高并发处理-附整合包
实战指南:封装Whisper为FastAPI接口并实现高并发处理
下面给出一个详细的示例,说明如何使用 FastAPI 封装 OpenAI 的 Whisper 模型,提供一个对外的 REST API 接口,并支持一定的并发请求。
下面是主要步骤和示例代码。
1. 环境准备
- Python 环境: 建议使用 Python 3.8+。
- 依赖库:
- FastAPI:轻量级、高性能的 Python web 框架。
- Uvicorn:用于运行 FastAPI 的 ASGI 服务器。
- Whisper:开源的语音识别模型,依赖于 PyTorch,因此需提前安装 torch(根据具体设备配置选择版本)。
可以使用 pip 安装依赖:
pip install fastapi uvicorn
# pip install git+https://github.com/openai/whisper.git 这个网络问题比较大
pip install openai-whisper
pip install torch # 根据硬件环境选择合适的版本# torch
# pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu126
2. 项目结构
项目目录结构可以如下:
whisper_fastapi/
├── models
├── app.py
└── requirements.txt
其中 requirements.txt 可写入:
fastapi
uvicorn
torch
# git+https://github.com/openai/whisper.git
openai-whisper
3. 编写 FastAPI 应用
在 app.py 中完成以下主要内容:
-
模型加载
为了避免每次请求都重复加载模型,建议在应用启动时加载一次模型,可以定义为全局变量。 -
接口定义
使用 POST 接口接收音频文件(例如 MP3、WAV 等)通过文件上传方式。注意这里使用UploadFile与File。 -
并发执行
由于 Whisper 的转录过程比较耗时且是 CPU 或 GPU 密集型的计算,我们可以将其放入线程池中执行。FastAPI 中通过asyncio.get_running_loop().run_in_executor(...)调用同步的转录方法,让异步接口可以处理并发。
下面给出示例代码:
import sys
import shutil
import tempfile
import asyncio
import warnings
import torch # 用于检测 CUDA 是否可用
from fastapi import FastAPI, UploadFile, File, HTTPException, Query
from fastapi.responses import JSONResponse
import whisper # 导入 OpenAI 的 Whisper 模型
from concurrent.futures import ThreadPoolExecutor# 检查 ffmpeg 是否可用
if shutil.which("ffmpeg") is None:sys.exit("错误:未找到 ffmpeg。请下载并安装 ffmpeg,并确保其所在目录已添加到系统 PATH 环境变量中。")app = FastAPI(title="Whisper FastAPI 接口")# 指定本地模型文件存储目录,事先要将下载好的模型文件放入该目录
local_model_dir = "./models"# 用一个全局字典缓存加载过的模型,避免重复加载
loaded_models = {}# 自动检测设备:如果 CUDA 可用则使用 GPU,否则使用 CPU
device = "cuda" if torch.cuda.is_available() else "cpu"
if device == "cpu":warnings.filterwarnings("ignore", message="FP16 is not supported on CPU; using FP32 instead")
print(f"使用的设备:{device}")def load_model_if_needed(model_name: str):"""检查全局字典中是否已存在指定 model_name 对应的模型,如果不存在,则从本地目录加载模型并保存到缓存中,并使用 device 参数确保模型加载到正确的设备上。"""if model_name not in loaded_models:try:model = whisper.load_model(model_name, download_root=local_model_dir, device=device)loaded_models[model_name] = modelexcept Exception as e:raise RuntimeError(f"加载 Whisper 模型 {model_name} 失败,请检查本地模型文件是否存在或模型路径配置是否正确") from ereturn loaded_models[model_name]# 创建线程池,用于并发处理(模型加载和转录过程可能较为耗时)
executor = ThreadPoolExecutor(max_workers=4)def transcribe_audio(model, file_path: str) -> dict:"""对给定音频文件进行转录,返回转录结果。根据设备自动启用或禁用 fp16 模式:- GPU:fp16=True- CPU:fp16=False"""try:result = model.transcribe(file_path, fp16=(device == "cuda"))return resultexcept Exception as e:return {"error": str(e)}@app.post("/transcribe")
async def transcribe(file: UploadFile = File(...),model_name: str = Query("base", description="使用的模型名称(如:tiny, base, small, medium, large)")
):"""接收上传的音频文件及可选参数 model_name,通过指定的模型进行转录并返回结果。"""if file.content_type not in ["audio/wav","audio/x-wav","audio/wave","audio/x-pn-wav","audio/mpeg","audio/mp3"]:raise HTTPException(status_code=400, detail="文件类型不支持,请上传 WAV 或 MP3 格式的音频文件")# 保存上传文件到临时文件try:suffix = "." + file.filename.split(".")[-1]except Exception:suffix = ".wav"try:with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp:contents = await file.read()tmp.write(contents)tmp_path = tmp.nameexcept Exception as e:raise HTTPException(status_code=500, detail="保存临时文件失败")# 使用线程池加载指定的模型(如果尚未加载)loop = asyncio.get_running_loop()try:model = await loop.run_in_executor(executor, load_model_if_needed, model_name)except Exception as e:raise HTTPException(status_code=500, detail=str(e))# 异步调用转录任务,放入线程池执行以避免阻塞事件循环transcription_result = await loop.run_in_executor(executor, transcribe_audio, model, tmp_path)if "error" in transcription_result:raise HTTPException(status_code=500, detail=transcription_result["error"])return JSONResponse(content=transcription_result)if __name__ == "__main__":import uvicornuvicorn.run("app:app", host="0.0.0.0", port=8000, reload=True)
4. 运行与部署
-
本地测试
在项目目录下运行:uvicorn app:app --host 0.0.0.0 --port 8000 --reload访问 http://localhost:8000/docs 可查看 FastAPI 自动生成的 API 文档,测试接口。
-
并发支持说明
- 这里我们通过
ThreadPoolExecutor将转录任务分发到子线程上,利用多线程来处理阻塞的 CPU 密集型任务,支持一定的并发。 - 在正式生产环境中,建议考虑使用 GPU 加速模型推理,并根据服务器硬件资源配置合理的线程数或进程数。另外,也可使用 Uvicorn 的多进程启动,例如:
uvicorn app:app --host 0.0.0.0 --port 8000 --workers 4
- 这里我们通过
-
容错与日志
根据需要可以增加异常处理、日志记录和监控,这里给出一个简单示例,您可以根据需求扩展。
5. 总结
- 环境搭建与依赖安装:确保 Python、FastAPI、Uvicorn、Whisper 及其相关依赖正确安装。
- 全局加载模型:避免重复加载模型,提高接口响应效率。
- 接口实现:使用 FastAPI 实现
/transcribe接口,通过上传文件参数进行音频转录。
http://localhost:8000/transcribe?model_name=base - 并发处理:将耗时的模型转录调用放置在线程池中执行,并结合 uvicorn 部署参数进一步扩展并发。
这样,一个简单的封装了 Whisper 模型的 FastAPI 接口就搭建完成了,可以支持并发调用,对外提供语音转文本的服务。
相关文章:
实战指南:封装Whisper为FastAPI接口并实现高并发处理-附整合包
实战指南:封装Whisper为FastAPI接口并实现高并发处理 下面给出一个详细的示例,说明如何使用 FastAPI 封装 OpenAI 的 Whisper 模型,提供一个对外的 REST API 接口,并支持一定的并发请求。 下面是主要步骤和示例代码。 1. 环境准备…...
C#Winform程序将子窗体嵌入容器方法
private void OpenForm(Form childFrom) { //首先判断容器中是否有其他的窗体 foreach (Control item in this.panelRight.Controls) { if (item is Form) { ((Form)item).Close(); } } //嵌入新的窗体 childFrom.TopLevel false;//将子窗体设置成非顶级控件 childFrom.Parent…...
Web三漏洞学习(其一:文件上传漏洞)
靶场:云曦历年考核题 一、文件上传 在此之前先准备一个一句话木马 将其命名为muma.txt 23年秋期末考 来给师兄上个马 打开环境以后直接上传muma.txt,出现js弹窗,说明有前端验证 提示只能上传.png .jpg 和 .gif文件,那就把muma.txt的后缀…...
37-串联所有单词的子串
给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。 s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。 例如,如果 words ["ab","cd","ef"], 那么 "abcdef…...
ShardingSphere复合分片之hash槽算法
前言 上一篇《ShardingSphere复合分片》中有详细介绍多key多value的复合分片算法应该如何设计,在大部分情况下该算法是没有问题的,但是一旦涉及到数据迁移时,该算法的缺点就暴露无疑了。 为满足日益增长的用户或者订单的需求,在分…...
Web三漏洞学习(其二:sql注入)
靶场:NSSCTF 、云曦历年考核题 二、sql注入 NSSCTF 【SWPUCTF 2021 新生赛】easy_sql 这题虽然之前做过,但为了学习sql,整理一下就再写一次 打开以后是杰哥的界面 注意到html网页标题的名称是 “参数是wllm” 那就传参数值试一试 首先判…...
KrillinAI:视频跨语言传播的一站式AI解决方案
引言 在全球内容创作领域,跨语言传播一直是内容创作者面临的巨大挑战。传统的视频本地化流程繁琐,涉及多个环节和工具,不仅耗时耗力,还常常面临质量不稳定的问题。随着大语言模型(LLM)技术的迅猛发展,一款名为Krillin…...
gravity`(控制 View 内部内容的对齐方式)
文章目录 **1. 常用取值****示例** **2. layout_gravity(控制 View 在父容器中的对齐方式)****常用取值****示例** **3. gravity vs layout_gravity 对比****4. 注意事项****5. 总结** 作用对象:当前 View 的内部内容(如 TextView…...
gitdiagram源码架构分析
https://github.com/ahmedkhaleel2004/gitdiagram 整体架构分析 前端请求入口: 后端对应接口: 后端调试 后端调试:会提示api_key失败的问题: 有两种方法解决: 1、注释掉下面的行代码; 方法二࿱…...
蓝光三维扫描:汽车冲压模具与钣金件全尺寸检测的精准解决方案
随着汽车市场竞争日趋激烈,新车型开发周期缩短,安全性能要求提高,车身结构愈加复杂。白车身由多达上百个具有复杂空间型面的钣金件,通过一系列工装装配、焊接而成。 钣金件尺寸精度是白车身装配精度的基础。采用新拓三维XTOM蓝光…...
《分布式软总线:网络抖动下的数据传输“定海神针”》
在当下,智能设备之间的互联互通已成为生活与工作的刚需。分布式软总线作为实现这一愿景的关键技术,正日益凸显其重要性。然而,网络环境的复杂性,尤其是网络抖动频繁的情况,给分布式软总线的数据传输带来了严峻挑战。如…...
WPS JS宏编程教程(从基础到进阶)-- 第八部分:字符串技术与WPS结合应用
目录 第8章 字符串技术与WPS结合应用8-1 字符串的3种引用方式场景:动态生成报表标题三种引用方式对比代码解析表模板字符串核心优势8-2 字符串处理之切片与搜索场景:提取身份证中的出生年份三大截取方法对比方法选择指南索引搜索实战8-3 字符串处理之修改与填充场景:规范商品…...
C++实用函数:bind
本篇来介绍了C++中bind功能。 1 std::bind 在 C++ 里,std::bind 是一个函数模板,其作用是创建一个可调用对象,该对象可绑定到一组参数上。std::bind 的函数原型如下: template< class F, class... Args > /*unspecified*/ bind( F&& f, Args&&...…...
深度学习占用大量内存空间解决办法
应该是缓存的问题,关机重启内存多了10G,暂时没找到别的方法 重启前 关机重启后...
完全无网络环境的 openEuler 系统离线安装 ClamAV 的详细步骤
准备工作(在外网机器操作) 1. 下载 ClamAV RPM 包及依赖 mkdir -p ~/clamav-offline/packages cd ~/clamav-offline/packages# 使用 yumdownloader 下载所有依赖包(需提前安装 yum-utils) sudo dnf install yum-utils -y sudo y…...
Matlab绘制函数方程图形
Matlab绘制函数方程图形: 多项式计算: polyval 函数 Values of Polynomials: polyval ( ) 绘制方程式图形: 代码如下: >> a[9,-5,3,7]; x-2:0.01:5; fpolyval(a,x); plot(x,f,LineWidth,2); xlabel(x); ylabel(f(x))…...
Unity UI 从零到精通 (第30天): Canvas、布局与C#交互实战
Langchain系列文章目录 01-玩转LangChain:从模型调用到Prompt模板与输出解析的完整指南 02-玩转 LangChain Memory 模块:四种记忆类型详解及应用场景全覆盖 03-全面掌握 LangChain:从核心链条构建到动态任务分配的实战指南 04-玩转 LangChai…...
在AMGX中使用MPI加载自定义分布式矩阵和向量
在AMGX中使用MPI加载自定义分布式矩阵和向量 AMGX是一个用于大规模并行代数多重网格求解的GPU加速库,支持MPI多线程环境。以下是加载用户自定义分布式矩阵和向量的方法: 1. 矩阵和向量分布的基本概念 在MPI环境中,AMGX使用行分布方式&…...
电视盒子 刷armbian
参考 中兴电视盒子中兴B860AV3.2-M刷Armbian新手级教程-CSDN博客 1.刷安卓9 带root版本 a. 下载安卓线刷包 链接:https://pan.baidu.com/s/1hz87_ld2lJea0gYjeoHQ8A?pwdd7as 提取码:d7as b.拆机短接 3.安装usbburning工具 使用方法 ,…...
AI应用开发之扣子第一课-夸夸机器人
首先,进入官网:点击跳转至扣子。 1.创建智能体 登录进网站后,点击左上角+图标,创建智能体,输入智能体名称、功能介绍 2.输入智能体提示词 在“人设与回复逻辑”输入以下内容: # 角色 你是一…...
【计算机网络实践】(十二)大学校园网综合项目设计
本系列包含: (一)以太网帧分析与网际互联协议报文结构分析 (二)地址解析协议分析与传输控制协议特性分析 (三)交换机的基本操作、配置、 虚拟局域网配置和应用 (四)交…...
uniapp小程序位置授权弹框与隐私协议耦合(合而为一)(只在真机上有用,模拟器会分开弹 )
注意: 只在真机上有用,模拟器会分开弹 效果图: 模拟器效果图(授权框跟隐私政策会分开弹,先弹隐私政策,同意再弹授权弹框): manifest-template.json配置( "__usePr…...
【星闪模组开发板WS8204SLEBLEModule】星闪数据收发测试
目录 开发板简介 串口设置 主从模式设置 AT命令数据发送 透传模式数据发送 结语 本文首发于《电子产品世界》论坛:【星闪模组开发板WS8204SLE&BLEModule】星闪数据收发测试-电子产品世界论坛https://forum.eepw.com.cn/thread/392011/1 感谢eepw论坛和成…...
天梯赛L1-22-25
L1-022 奇偶分家 题目描述 给定 N 个正整数,统计其中奇数和偶数各有多少个。 输入格式 第一行:一个正整数 N(≤1000)。第二行:N 个非负整数,以空格分隔。 输出格式 在一行中输出奇数的个数和偶数的个…...
基础知识:Dify 错误排查
Case1:Dify 卡在管理员界面 查看容器状态 docker compose ps 可以看到有个容器异常:docker_db_1 的状态是 Restarting(表示一直在重启) 解决方案 参考:https://github.com/langgenius/dify/issues/5731...
spring cloud微服务断路器详解及主流断路器框架对比
微服务断路器详解 1. 核心概念 定义:断路器模式通过快速失败机制防止故障扩散,当服务调用出现异常或超时时,自动切换到降级逻辑,避免级联故障。核心功能: 熔断:在故障阈值(如错误率)…...
BufferedReader 终极解析与记忆指南
BufferedReader 终极解析与记忆指南 一、核心本质 BufferedReader 是 Java 提供的缓冲字符输入流,继承自 Reader,通过内存缓冲和行读取功能极大提升文本读取效率。 核心特性速查表 特性说明继承链Reader → BufferedReader缓冲机制默认 8KB 字符缓冲…...
linux-设置每次ssh登录服务器的时候提醒多久需要修改密码
在 Linux 系统中,你可以通过设置 motd(Message of the Day)或 sshd 配置来在用户通过 SSH 登录时提醒他们密码即将过期。以下是具体步骤: 方法 1: 使用 motd 文件 motd 文件在用户登录时显示,你可以通过脚本动态生成内容,提醒用户密码过期时间。 编辑 /etc/motd 文件:…...
(小白0基础) 微调deepseek-8b模型参数详解以及全流程——训练篇
本篇参考bilibili如何在本地微调DeepSeek-R1-8b模型_哔哩哔哩_bilibili 上篇:(小白0基础) 租用AutoDL服务器进行deepseek-8b模型微调全流程(Xshell,XFTP) —— 准备篇 初始变量 max_seq_length 2048 dtype None load_in_4bit True单批次最大处理模型大小dy…...
调用LLM的api
目录 chatgptdemo可选模型 chatgpt demo import openai openai.api_key xxxxxxxxx # 自己的api key openai.api_base https://api.feidaapi.com/v1 # 中转非直连 # response openai.ChatCompletion.create( # model"gpt-4o", # messages[ # {"rol…...
