whisper.cpp 学习笔记

whisper.cpp 学习笔记

    正在检查是否收录...

whisper.cpp

whisper.cpp 学习笔记 whisper 介绍 源码下载 源码编译 支持的模型 优化/加速 生成库文件 使用 whispe.cpp 的 demo 参考文献

whisper.cpp 学习笔记

whisper 介绍

whisper 是基于 OpenAI 的自动语音识别(ASR)模型。他可以识别包括英语、普通话等在内多国语言。

whisper 分为 whisper (python 版本)和 whisper.cpp(C/C++ 版本)。

python 版本的 whisper 可以直接通过 pip install whisper 安装;whisper.cpp 可以通过源码进行安装。

以下主要介绍 whisper.cpp,因为其识别速度要快于 python 版本的 whisper。

源码下载

源码下载

网址:https://github.com/ggerganov/whisper.cpp

git clone https://github.com/ggerganov/whisper.cpp.git 
下载模型
bash ./models/download-ggml-model.sh base.en 

源码编译

方法一

直接在 whisper.cpp 目录下执行 make 命令就可以编译

# build the main example make # transcribe an audio file ./main -f samples/jfk.wav 

默认会生成 main benchquantize 这三个命令:

main :whisper 的命令 quantize : 对 whisper 的模型进行量化处理 bench :性能测试

注:

使用此方法生成的可执行文件会包含 whisper 的代码,即没有生成 whisper 的库文件

whisper 只能识别音频采样频率为 16000 Hz 的声音数据,数据格式为 float类型——如果是 wav 文件则内部会自动转成 float 格式

方法二

make build cd build cmake xxx #xxx 为 cmake 传入的参数,例如 prefix 等等,单独的 cmake 不能生成 Makefile make 

使用这种方式会在 build 目录下生成 liwhisper.so liwhisper.so.1liwhisper.so。1.5.5 库文件 —— 对应的头文件在 whisper.cpp 目录下 whisper.h 可以直接将这几个文件防盗 /usr/lib/usr/include 下即可使用。

支持的模型

whisper 目前支持:tiny、base、small、medium 以及 large 模型,其中带 .en 的表示之支持英文。

通过 make xxx 可以直接下载模型,例如:

make small 

各种模型的内存使用情况:

Model Disk Mem tiny 75 MiB ~273 MB base 142 MiB ~388 MB small 466 MiB ~852 MB medium 1.5 GiB ~2.1 GB large 2.9 GiB ~3.9 GB

优化/加速

使用硬件加速

whipser 支持多种加速(详见 whisper.cpp 的 Readme)

OpenVINO NVIDIA GPU CLBlast OpenBLAS MKL …

这里只介绍 MKL。

首先通过 Intel® oneAPI Math Kernel Library 下载 intel 的 oneapi 数学库;

该数学库是二进制安装的,在安装完后需要执行一个脚本用于产生命令和连接库位置的环境

source /opt/intel/oneapi/setvars.sh mkdir build cd build cmake -DWHISPER_MKL=ON .. WHISPER_MKL=1 make -j 

通过上步可以生成依赖 intel oneapi 的 whisper 动态库。这里为了能够开机使用 intel oneapi,可以将 source /opt/intel/oneapi/setvars.sh 命令放到 ~/.bashrc 配置文件中——要想所有用户都可以使用,可以在 /ect/profile.d 目录下建一个 intel oneapi 的脚本,这样在用户登陆时可以自动配置环境变量。

注:

如果使用 root 权限安装 intel oneapi 则该软件安装在 /opt 目录下,否则安装在用户的 home 目录下。

量化模型

编译生成的可执行文件中有 quantize 这个命令,该命令用来量化模型可以减少模型的体积和加快运行的速度。

usage: ./quantize model-f32.bin model-quant.bin type type = "q2_k" or 10 type = "q3_k" or 11 type = "q4_0" or 2 type = "q4_1" or 3 type = "q4_k" or 12 type = "q5_0" or 8 type = "q5_1" or 9 type = "q5_k" or 13 type = "q6_k" or 14 type = "q8_0" or 7 

例如量化前 ggml-medium.bin 的大小为 1.5 G,采用 q4_k 量化后大小为 424 M。

执行速度:

量化前

time whisper --language chinese --model models/ggml-medium.bin output.wav 
system_info: n_threads = 4 / 8 | AVX = 1 | AVX2 = 1 | AVX512 = 0 | FMA = 1 | NEON = 0 | ARM_FMA = 0 | METAL = 0 | F16C = 1 | FP16_VA = 0 | WASM_SIMD = 0 | BLAS = 1 | SSE3 = 1 | SSSE3 = 1 | VSX = 0 | CUDA = 0 | COREML = 0 | OPENVINO = 0 main: processing 'output.wav' (42624 samples, 2.7 sec), 4 threads, 1 processors, 5 beams + best of 5, lang = chinese, task = transcribe, timestamps = 1 ... [00:00:00.000 --> 00:00:02.000] 你好 你好 你好 whisper_print_timings: load time = 606.10 ms whisper_print_timings: fallbacks = 0 p / 0 h whisper_print_timings: mel time = 6.12 ms whisper_print_timings: sample time = 12.43 ms / 24 runs ( 0.52 ms per run) whisper_print_timings: encode time = 9836.69 ms / 1 runs ( 9836.69 ms per run) whisper_print_timings: decode time = 69.17 ms / 2 runs ( 34.59 ms per run) whisper_print_timings: batchd time = 364.41 ms / 20 runs ( 18.22 ms per run) whisper_print_timings: prompt time = 0.00 ms / 1 runs ( 0.00 ms per run) whisper_print_timings: total time = 10899.75 ms real 0m11.000s user 0m44.862s sys 0m2.151s 

量化后

time whisper --language chinese --model models/ggml-medium_q4_k.bin output.wav 
system_info: n_threads = 4 / 8 | AVX = 1 | AVX2 = 1 | AVX512 = 0 | FMA = 1 | NEON = 0 | ARM_FMA = 0 | METAL = 0 | F16C = 1 | FP16_VA = 0 | WASM_SIMD = 0 | BLAS = 1 | SSE3 = 1 | SSSE3 = 1 | VSX = 0 | CUDA = 0 | COREML = 0 | OPENVINO = 0 main: processing 'output.wav' (42624 samples, 2.7 sec), 4 threads, 1 processors, 5 beams + best of 5, lang = chinese, task = transcribe, timestamps = 1 ... [00:00:00.000 --> 00:00:02.000] 你好 你好 你好 whisper_print_timings: load time = 303.66 ms whisper_print_timings: fallbacks = 0 p / 0 h whisper_print_timings: mel time = 6.37 ms whisper_print_timings: sample time = 13.74 ms / 27 runs ( 0.51 ms per run) whisper_print_timings: encode time = 8979.33 ms / 1 runs ( 8979.33 ms per run) whisper_print_timings: decode time = 34.54 ms / 2 runs ( 17.27 ms per run) whisper_print_timings: batchd time = 289.84 ms / 23 runs ( 12.60 ms per run) whisper_print_timings: prompt time = 0.00 ms / 1 runs ( 0.00 ms per run) whisper_print_timings: total time = 9632.14 ms real 0m9.702s user 0m42.165s sys 0m1.342s 

从量化前后的执行速度来看,执行时间提升了1秒左右。

生成库文件

在前面我们介绍了使用 cmake & make 命令可以生成动态库。

使用 whispe.cpp 的 demo

example 目录下有各种使用的 demo ,通过在 whisper.cpp 目录下执行 make xxx (xxx 为 example 中演示 demo 的名字),即可生成该 demo 的可执行文件。

通过分析各种 demo 文件可以发现,主要使用了 whisper 中的如下几个函数:

whisper_lang_id() 语言支持检测——这里要使用小写,如 chinese 而不能用 Chinese whisper_context_default_params() 设置默认的上下文参数 whisper_init_from_file_with_params() 初始化上下文 whisper_is_multilingual() 检查上下文是否支持多国语言 whisper_full() 语音识别过程的函数 whisper_full_n_segments() 获取一共产生了多少段文字 whisper_full_get_segments_text() 获取识别到的一段文字 whisper_full_n_token() 一段识别中有多少个 tokern whisper_full_get_token_id() 获取对应 id 的 token

以下是参考 example/main/main.cpp 改写的简单 cpp 文件。

#include "common.h" #include "whisper.h" #include "grammar-parser.h" #include <cmath> #include <fstream> #include <cstdio> #include <regex> #include <string> #include <thread> #include <vector> #include <cstring> bool wav_read(std::string fname, std::vector<float>& pcmf32) { std::vector<std::vector<float>> pcmf32s; if (!::read_wav(fname, pcmf32, pcmf32s, false)) { fprintf(stderr, "error: failed to read WAV file '%s'\n", fname.c_str()); return false; } return true; } int whisper_init(struct whisper_context * *ctx, whisper_full_params& wparams) { if (whisper_lang_id("chinese") == -1) { fprintf(stderr, "error: unknown language '%s'\n", "Chinese"); exit(0); } struct whisper_context_params cparams = whisper_context_default_params(); cparams.use_gpu = false; *ctx = whisper_init_from_file_with_params("models/ggml-small.bin", cparams); if (*ctx == nullptr) { fprintf(stderr, "error: failed to initialize whisper context\n"); return 3; } wparams = whisper_full_default_params(WHISPER_SAMPLING_GREEDY); wparams.language = "chinese"; return 0; } int whisper_exit(struct whisper_context ** ctx) { whisper_free(*ctx); return 0; } int whisper_identify(struct whisper_context **ctx, whisper_full_params& wparams, std::vector<float> pcmf32, std::string& result) { if(whisper_full(*ctx, wparams, pcmf32.data(), pcmf32.size()) != 0){ return -1; } const int n_segments = whisper_full_n_segments(*ctx); for (int i = 0; i < n_segments; ++i) { const char * text = whisper_full_get_segment_text(*ctx, i); result += text; } return 0; } int main(int argc, char ** argv) { std::vector<float> pcmf32; struct whisper_context *ctx = nullptr; whisper_full_params wparams; std::string text; if(!wav_read("output.wav", pcmf32)){ fprintf(stderr, "wave read failed !\n"); return -1; } if(whisper_init(&ctx, wparams)){ fprintf(stderr, "whisper init error !\n"); return -1; } if(whisper_identify(&ctx, wparams, pcmf32, text)){ fprintf(stderr, "identify error !\n"); return 0; } whisper_exit(&ctx); fprintf(stdout, "text is : %s\n", text.c_str()); return 0; } 

该文件简化为 wav 文件读、whisper 初始化、whisper 识别以及 whisper 退出这几个函数,结构简单更容易理解。将其替换 example/main/main.cpp 重新编译即可以执行。

注:
在 whisper 的 api 函数中涉及到的语言全部用小写,不能使用大写,否则会提示不支持。

参考文献

whisper.cpp

whisperapiintelctomediumtputhreadscodegitpythontoken上下文ide可执行文件语音识别参考文献stembashgangithub
  • 本文作者:李琛
  • 本文链接: https://wapzz.net/post-17739.html
  • 版权声明:本博客所有文章除特别声明外,均默认采用 CC BY-NC-SA 4.0 许可协议。
本站部分内容来源于网络转载,仅供学习交流使用。如涉及版权问题,请及时联系我们,我们将第一时间处理。
文章很赞!支持一下吧 还没有人为TA充电
为TA充电
还没有人为TA充电
0
  • 支付宝打赏
    支付宝扫一扫
  • 微信打赏
    微信扫一扫
感谢支持
文章很赞!支持一下吧
关于作者
2.3W+
5
0
1
WAP站长官方

[AI里程碑]StableDiffusion3今日开源 | 首个开源超越Midjourney

上一篇

Meta Llama 3 残差结构

下一篇
  • 复制图片
按住ctrl可打开默认菜单