【.NET】使用Whisper.net实现录音转文本

前言:上一篇文章写了关于如何录音,这篇咱们做个升级,让录音内容转为文本。废话不多说,直接上手,以下正文:

1、新建一个控制台项目,引用CommandLineParser和Whisper.net

3d4bdbda3df24f917fb2cbdf04c005eb.png

2、新建Options实体类,用于提供使用模型的一些参数

public class Options
    {
        /// <summary>
        /// 指令类型
        /// </summary>
        [Option('t', "command", Required = false, HelpText = "运行指令 (lang-detect, transcribe 或 translate)", Default = "transcribe")]
        public string Command { get; set; } = "transcribe";


        /// <summary>
        /// 音频文件,默认要存放bin目录下
        /// </summary>
        [Option('f', "file", Required = false, HelpText = "需要处理的音频文件", Default = "test.mp3")]
        public string FileName { get; set; }


        /// <summary>
        /// 语言,默认自动选择
        /// </summary>
        [Option('l', "lang", Required = false, HelpText = "语言", Default = "auto")]
        public string Language { get; set; } = "chinese";


        /// <summary>
        /// 模型文件,默认也存在在bin同级目录下
        /// </summary>
        [Option('m', "modelFile", Required = false, HelpText = "使用的模型的文件名", Default = "ggml-base.bin")]
        public string ModelName { get; set; } = "ggml-base.bin";


        /// <summary>
        /// 模型类型
        /// </summary>
        [Option('g', "ggml", Required = false, HelpText = "根据模型类型,验证是否存在模型文件,不存在则下载", Default = GgmlType.Base)]
        public GgmlType ModelType { get; set; }= GgmlType.Base;
    }

3、ggml模型类别枚举参考:

public enum GgmlType
{
        Tiny,
        TinyEn,
        Base,
        BaseEn,
        Small,
        SmallEn,
        Medium,
        MediumEn,
        LargeV1,
        Large
    }

它们会对应在线的模型,会根据需要自动下载。在线模型文件参考:

b6241b999817fe69b78044714d4b5474.png

模型地址:

https://huggingface.co/sandrohanea/whisper.net/tree/main/classic

4、验证模型文件不存在,则下载

if (!File.Exists(opt.ModelName))
            {
                Console.WriteLine($"准备下载模型:{opt.ModelName}");
                using (var modelStream = await WhisperGgmlDownloader.GetGgmlModelAsync(opt.ModelType))
                {
                    using (var fileWriter = File.OpenWrite(opt.ModelName))
                    {
                        await modelStream.CopyToAsync(fileWriter);
                    }
                }
            }

上面代码下载没进度提示,稍微改造下:

var bytesRead = 0;
                            var buffer = new byte[8192]; // 8KB 的缓冲区
                            var lastUpdateTime = DateTime.Now; // 记录上次更新的时间


                            int bytesJustRead;
                            while ((bytesJustRead = await modelStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
                            {
                                await fileWriter.WriteAsync(buffer, 0, bytesJustRead);
                                bytesRead += bytesJustRead;


                                // 检查是否已经过去了1秒
                                if ((DateTime.Now - lastUpdateTime).TotalSeconds >= 1)
                                {
                                    // 将已下载的字节数转换为MB
                                    double downloadedMB = bytesRead / 1024.0 / 1024.0;


                                    // 将光标移回到上一行的开始
                                    Console.SetCursorPosition(0, Console.CursorTop - 1);


                                    // 使用 \r 来覆盖当前行并显示已下载的MB
                                    Console.WriteLine($"已下载: {downloadedMB:0.00} MB ({downloadedMB / 1024.0} GB)\r");


                                    // 更新上次更新的时间
                                    lastUpdateTime = DateTime.Now;
                                }
                            }

5、新建音频转文本的处理函数,具体内容看代码和有关注释:

static async Task Audio2Text(Options opt)
        {
            // 从给定的模型名称路径创建一个 WhisperFactory 实例
            using var factory = WhisperFactory.FromPath(opt.ModelName);


            var builder = factory.CreateBuilder()
                .WithLanguage(opt.Language);


            // 如果值为 "translate",则在构建器中启用翻译功能
            if (opt.Command == "translate")
            {
                builder.WithTranslate();
            }


            using var processor = builder.Build();


            // 打开一个文件流来读取由 opt.FileName 指定的音频文件
            using var fileStream = File.OpenRead(opt.FileName);


            // 使用处理器异步处理音频文件。对于处理器返回的每个段(segment),它将段的开始时间、结束时间和文本打印到控制台。
            await foreach (var segment in processor.ProcessAsync(fileStream, CancellationToken.None))
            {
                Console.WriteLine($"{segment.Start} ==> {segment.End} : {segment.Text}");
            }
        }

6、创建一个检测语言的方法:

void LanguageIdentification(Options opt)
        {
            // 使用 File.ReadAllBytes 方法将模型文件读取到内存中。
            var bufferedModel = File.ReadAllBytes(opt.ModelName);


            // 多个任务可以使用同一个工厂来创建处理器
            using var factory = WhisperFactory.FromBuffer(bufferedModel);


            // 使用工厂创建一个新的构建器,并设置其语言
            var builder = factory.CreateBuilder()
               .WithLanguage(opt.Language);


            using var processor = builder.Build();


            // 打开一个文件流来读取由 opt.FileName 指定的音频文件
            using var fileStream = File.OpenRead(opt.FileName);


            // 使用 WaveParser 类来解析音频文件
            var wave = new WaveParser(fileStream);


            // 使用 WaveParser 的 GetAvgSamples 方法获取音频文件的平均样本
            var samples = wave.GetAvgSamples();


            // 使用处理器的 DetectLanguage 方法检测音频样本中的语言
            var language = processor.DetectLanguage(samples, speedUp: true);
            Console.WriteLine("Language is " + language);
        }

processor.DetectLanguage(samples, speedUp: true) 的speedUp说明:

当speedUp为true时,使用whisper_pcm_to_mel_phase_vocoder_with_state方法进行处理。这个方法可能使用了phase vocoder技术,这是一种在不改变音高的情况下改变音频速度的技术。

当speedUp为false时,使用whisper_pcm_to_mel_with_state方法进行处理。这个方法可能是一个更传统或基本的方法来从PCM数据转换到Mel频谱。

7b1a3917f7dc59d75058ea3640bf80ed.png

7、根据指令,执行内容

switch (opt.Command)
            {
                case "lang-detect":
                    LanguageIdentification(opt);
                    break;
                case "transcribe":
                case "translate":
                    await Audio2Text(opt);
                    break;
                default:
                    Console.WriteLine("未知指令类型");
                    break;
            }

8、制作一个录音文件备用。录音教程,可以参考之前文章:

https://mp.weixin.qq.com/s/vAZUyuT5F_S5Oee-BkV_dw

备注:录制音频需要使用16KHZ,可在链接文章內的录音部分代码中,新增以下参数:

waveIn.WaveFormat = new WaveFormat(16000,16,1);

如果需要录制系统音频,可以使用:

using var waveIn = new WasapiLoopbackCapture();

我录制了个系统音频,网络上随便找了一个频道进行播放其中一小段,然后录制成音频:

https://www.ximalaya.com/sound/565311273

6e3070b16182054b179f5427c2471f90.png

把录音文件放到根目录下:

545885c751dc71ef2e61b7b0f0fc9200.png

先用本地播放器播放下,看下长度和是否能正常播放先:

85a5b20f16d43c9aecfbff7fc4384ef3.png

可以播放,说明文件是正常的,开始运行音频转文本程序:

aca32eba15dc3c163d500f3001102045.png

可以看到音频内容被输出了。

如果以上内容对你有帮助,欢迎一键三连,点赞、关注、转发,谢谢大佬们~关注可以通过扫码以下二维码快捷关注,不定时更新技术文章。

0fceea53fce1c061f976e452e142e2d7.jpeg

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Colab Whisper模型是一种先进的语音文字模型,它基于语音识别技术,利用深度学习算法将语音信号换为文本。 Colab Whisper模型的实现步骤如下: 1. 准备数据:首先,需要准备用于训练模型的语音数据集。这些语音数据应该包含不同人的不同语音片段,涵盖不同的语言和口音。 2. 数据预处理:接下来,需要对语音数据进行预处理。这包括对语音信号进行采样和分割,去除噪音和不必要的部分,并将其换为模型可处理的格式,例如MFCC特征。 3. 构建模型:使用深度学习框架,如TensorFlow或PyTorch,构建Colab Whisper模型。该模型通常由多个卷积神经网络和循环神经网络层组成,用于提取语音信号的特征并进行序列建模。 4. 训练模型:使用准备好的语音数据集,通过反向传播算法和训练集的迭代,对模型进行训练。在每个迭代步骤中,模型会根据预测输出与实际标签之间的差异调整自身的权重和参数,以提高预测准确性。 5. 模型评估和优化:在每个训练周期结束后,使用验证集和测试集对模型进行评估。评估指标可以包括词错误率(WER)和字符错误率(CER)。通过这些指标,可以确定模型的性能,并对其进行改进。 6. 部署和应用:一旦模型训练完成并通过评估,就可以将其部署到实际应用中。通过输入语音信号,模型将对其进行换,并输出相应的文本结果。 总之,Colab Whisper模型通过深度学习算法实现了从语音到文本换。通过准备数据、进行数据预处理、构建模型、训练模型、评估和优化以及部署应用等步骤,可以实现一个高效准确的语音文字系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值