
FunASR 离线文件转写 C# WebSocket 客户端实战指南配置、编译与热词/时间戳解析【免费下载链接】FunASROpen-source speech recognition toolkit for training, inference, streaming ASR, VAD, punctuation, speaker diarization pipelines, and OpenAI-compatible/MCP serving.项目地址: https://gitcode.com/GitHub_Trending/fun/FunASR本文围绕 FunASR 仓库中提供的 C# 离线 WebSocket 客户端FunASRWSClient_Offline展开讲解如何基于 FunASR-WebSocket 服务端实现本地音频文件wav/pcm/mp3/mp4的离线转写。读完本文你将掌握该客户端的目录结构与配置方式、VS2022 下的编译运行流程、WebSocket 通信协议细节首帧 JSON、音频分块发送、结束标志以及热词、时间戳结果的解析与使用前提。一、客户端定位与适用场景FunASR 官方提供了基于 WebSocket 的 C# 客户端实现代码位于 runtime/csharp/ws-client 目录包含两个独立工程FunASRWSClient_Offline离线文件转写客户端本篇文章的主角用于将本地音频文件发送给服务端完成一次性转写FunASRWSClient_Online在线/实时语音识别客户端含麦克风采集、online与2pass两种流式模式可作为对照参考。离线客户端面向的典型场景是文件批量/逐条转写用户在控制台输入音频文件路径程序将文件按 WebSocket 协议切块上传至 FunASR 服务端服务端返回识别文本若部署的是时间戳模型还会附带逐字时间戳客户端在控制台输出带时间戳的逐句结果。原文档说明该客户端已在 Windows 11 下完成测试编译环境为 Visual Studio 2022。二、工程结构与前置条件2.1 关键文件离线客户端工程由四个文件组成功能划分清晰文件作用Program.cs程序入口包含Program与WSClient_Offline两个类负责配置加载、热词加载、连接自检与交互式文件输入循环WebScoketClient.csCWebSocketClient类封装 Websocket.Client 库实现连接、发送音频、接收并解析识别结果FunASRWSClient_Offline.csproj工程文件声明目标框架与 NuGet 依赖README.md原版使用说明同时仓库在 runtime/csharp/ws-client/confg 目录下提供了配套的配置文件模板config.ini、hotword.txt以及示例音频tmp.wav。2.2 目标框架与依赖查看 FunASRWSClient_Offline.csproj 可知Project SdkMicrosoft.NET.Sdk PropertyGroup OutputTypeExe/OutputType TargetFrameworknet6.0/TargetFramework ImplicitUsingsenable/ImplicitUsings Nullableenable/Nullable /PropertyGroup ItemGroup PackageReference IncludeWebsocket.Client Version4.6.1 / /ItemGroup /Project要点如下目标框架net6.0即 .NET 6长期支持版本唯一第三方依赖Websocket.Client4.6.1这是客户端与服务端通信的核心库从源码 import 看它还间接依赖System.Reactive.Linq用于订阅MessageReceived等可观察流这些依赖会随 NuGet 包自动还原配置方式按原文档说明在 VS 中打开工程后需先添加Websocket.Client的 NuGet 程序包若直接打开仓库自带 sln则包引用已声明在 csproj 中还原即可随后即可直接编译测试。三、配置文件与热词准备3.1 config.ini服务端地址配置原文档要求将配置文件放在与程序相同目录下的 config 文件夹中实际运行目录结构约定为在程序生成物exe同级的config目录下放置config.ini在其中配置服务端 IP 和端口号。仓库自带的模板位于 runtime/csharp/ws-client/confg/config.inihost127.0.0.1 port10095hostFunASR-WebSocket 服务端的 IP 地址默认为127.0.0.1即本机port服务端监听端口默认为10095与 runtime/docs/websocket_protocol_zh.md 中约定的默认端口一致。从 Program.cs 的loadconfig()实现可以看出解析规则逐行读取config.ini忽略空行以及以;或#开头的注释行按keyvalue形式解析host与port分别写入静态字段代码中静态字段的兜底默认值分别是0.0.0.0与10095但实际连接地址取决于配置文件内容。3.2 hotword.txt热词配置客户端从 2023 年左右的版本起支持热词hotwords。热词文件同样放在程序执行路径下名为hotword.txt仓库模板见 runtime/csharp/ws-client/confg/hotword.txt阿里巴巴 达摩院 FunASR每行一个热词。loadhotword()见 Program.cs会逐行读取并拼装成以空格分隔的字符串例如阿里巴巴 达摩院 FunASR该字符串随后被写入 WebSocket 首帧消息的hotwords字段。需要特别注意原文档的提醒热词与时间戳来自不同的模型。也就是说要使用热词能力服务端需要部署支持热词的模型FST 热词服务热词权重仅在 FST 热词服务下生效见 websocket_protocol_zh.md 中的参数注释要使用时间戳能力则需要部署时间戳timestamp模型。两者需要根据实际模型能力分别开启不能假设单个模型同时具备两种能力。四、编译运行与交互流程4.1 操作步骤使用 Visual Studio 2022 打开解决方案 FunASRClient_CShape.sln还原/添加Websocket.Client4.6.1 NuGet 包将 config.ini 与 hotword.txt 复制到程序输出目录下的config文件夹hotword.txt 放在执行路径下启动 FunASR-WebSocket 服务端离线部署方式参考 runtime/docs/SDK_tutorial_zh.md确保服务端 IP 与端口与config.ini一致编译运行程序按控制台提示输入本地音频文件的路径回车后即可得到识别结果。4.2 启动自检逻辑FunASR_Main()见 Program.cs在进入文件输入循环前会执行两步自检加载配置与热词loadconfig()与loadhotword()通信连接自检ClientConnTest()调用CWebSocketClient.ClientConnTest()尝试建立 WebSocket 连接只有连接成功后才会进入while(true)循环等待用户输入文件路径若连接失败则直接Environment.Exit(0)退出程序。交互主循环非常简洁控制台提示请输入转录文件路径用户输入非空路径后调用ClientSendFileFunc(filepath)完成一次文件转写随后继续等待下一条输入天然支持连续多文件转写。五、WebSocket 通信协议与发送实现离线客户端遵循 runtime/docs/websocket_protocol_zh.md 中离线文件转写一节的约定配置参数与 meta 信息用 JSON音频数据用 bytes。5.1 首帧 JSON 消息发送音频前客户端先发送一段 JSON 首帧见 WebScoketClient.cs。对 wav 文件{mode: offline, wav_name: xxx.wav, is_speaking: true, hotwords: 阿里巴巴 达摩院 FunASR}对其他格式mp3/mp4/pcm还会追加wav_format字段{mode: offline, wav_name: xxx.mp3, is_speaking: true, hotwords: 阿里巴巴 达摩院 FunASR, wav_format: mp3}各字段含义与协议文档一致modeoffline表示离线文件转写模式wav_name音频文件名仅取Path.GetFileName不含路径is_speakingtrue表示音频数据即将开始hotwords热词字符串多个热词以空格分隔wav_format音频格式pcm/mp3/mp4等wav 场景下客户端省略该字段服务端按 wav 头自行解析。5.2 音频数据分块发送ClientSendFileFunc首先校验文件扩展名仅接受wav、pcm、mp3、mp4四种格式其余直接返回。随后按格式选择不同的发送路径wav 文件调用showWAVForm先读取整个文件字节再Skip(44)跳过 44 字节的 WAV 文件头只发送裸音频数据其他格式mp3/mp4/pcm调用showWAVForm_All发送完整文件字节含头部由服务端按wav_format解析。两种路径都采用分块发送策略每块 1024000 字节约 1 MB块间Thread.Sleep(5)毫秒限速避免瞬时大流量冲击服务端。5.3 结束标志音频数据全部发送完毕后客户端发送 JSON 结束标志{is_speaking: false}服务端据此判定音频流结束执行 VAD 切分与最终识别并回传结果。这也是 websocket_protocol_zh.md 明确要求的收尾步骤。六、识别结果解析文本、时间戳与逐句对齐服务端返回的识别结果同样是 JSON形如{mode: offline, wav_name: xxx.wav, text: 识别文本, is_final: true, timestamp: [[100,200],[200,500]], stamp_sents: []}客户端的recmessage()见 WebScoketClient.cs负责解析逻辑如下用JsonDocument解析出mode、text、wav_name三个必填字段检测是否含时间戳通过message.IndexOf(timestamp)判断返回消息是否携带时间戳字段无时间戳场景直接打印文件名称:{name} 文件转录内容: {text}有时间戳场景做逐句对齐输出先将识别文本中的,与?替换为。再按。切分为句子列表sens用正则\[(\d),(\d)\]从时间戳字符串中提取所有[start,end]毫秒对构造ListListint data按句子长度推进时间戳下标为每个句子输出形如[start-end]:句子内容的结果例如[100-500]:你好。。需要说明的是时间戳字段的粒度取决于服务端所部署的模型若 AM声学模型为时间戳模型返回timestamp逐字级格式[[100,200],[200,500]]单位毫秒以及stamp_sents句子级时间戳。客户端当前实现消费的是逐字时间戳字段并将其与按标点切分出的句子做粗粒度对齐。6.1 通信健壮性设计CWebSocketClient中还有若干值得注意的工程细节断线重连设置client.ReconnectTimeout null表示不自动限时重连同时订阅ReconnectionHappened与DisconnectionHappened事件并打印日志便于排查网络问题消息订阅通过MessageReceived.Where(msg msg.Text ! null).Subscribe(...)只处理文本消息识别结果是 JSON 文本二进制消息被过滤JSON 异常保护解析过程包裹在try/catch (JsonException)中解析失败打印JSON 解析错误而不崩溃。七、与在线客户端的对比及注意事项仓库中的 FunASRWSClient_Online 是同一协议族的实时版客户端二者共享config.ini的解析方式但存在关键差异理解这些差异有助于正确选用客户端维度离线客户端本文在线客户端音频来源本地文件wav/pcm/mp3/mp4麦克风实时采集NAudio 本地文件首帧模式modeofflinemodeonline/mode2pass带chunk_size:[5,10,5]与chunk_interval音频发送1 MB 分块、块间 5ms 间隔按chunk_size计算的 CHUNK 切块实时发送结果输出一次性文本/时间戳流式2pass-online中间结果 2pass-offline修正结果使用离线客户端时还需注意模型与服务端匹配热词需要 FST 热词服务支持权重仅在该服务下生效时间戳需要时间戳模型二者是不同模型能力应按需部署服务端必须先启动客户端启动时会做连接自检连不上直接退出wav 头处理wav 文件发送时跳过 44 字节头因此要求 wav 为标准 PCM 编码格式44 字节标准 RIFF 头非标准 wav 建议先转码或改用带wav_format的方式运行环境官方在 Windows 11 VS2022 下完成测试net6.0目标框架需安装对应 .NET SDK 运行时。八、小结FunASRWSClient_Offline是一个结构清晰、可直接编译运行的 C# 参考客户端完整演示了 FunASR WebSocket 离线转写协议的三个关键步骤JSON 首帧握手 → 二进制音频分块上传 →is_speaking:false结束收尾并额外实现了热词注入与时间戳逐句对齐输出。结合 runtime/docs/websocket_protocol_zh.md 协议文档开发者可以快速将它改造为批量转写工具、桌面应用或集成到 .NET 业务系统中无需从零摸索协议细节。【免费下载链接】FunASROpen-source speech recognition toolkit for training, inference, streaming ASR, VAD, punctuation, speaker diarization pipelines, and OpenAI-compatible/MCP serving.项目地址: https://gitcode.com/GitHub_Trending/fun/FunASR创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考