funasr/runtime/wss-client/FunASRClient_CShape.sln
New file @@ -0,0 +1,31 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.6.33829.357 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FunASRWSClient_Offline", "FunASRWSClient_Offline\FunASRWSClient_Offline.csproj", "{E0986CC4-D443-44E2-96E8-F6E4B691CA57}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FunASRWSClient_Online", "FunASRWSClient_Online\FunASRWSClient_Online.csproj", "{11E80B4F-A838-4DFB-A0C8-9BAE6726BAC0}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {E0986CC4-D443-44E2-96E8-F6E4B691CA57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E0986CC4-D443-44E2-96E8-F6E4B691CA57}.Debug|Any CPU.Build.0 = Debug|Any CPU {E0986CC4-D443-44E2-96E8-F6E4B691CA57}.Release|Any CPU.ActiveCfg = Release|Any CPU {E0986CC4-D443-44E2-96E8-F6E4B691CA57}.Release|Any CPU.Build.0 = Release|Any CPU {11E80B4F-A838-4DFB-A0C8-9BAE6726BAC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {11E80B4F-A838-4DFB-A0C8-9BAE6726BAC0}.Debug|Any CPU.Build.0 = Debug|Any CPU {11E80B4F-A838-4DFB-A0C8-9BAE6726BAC0}.Release|Any CPU.ActiveCfg = Release|Any CPU {11E80B4F-A838-4DFB-A0C8-9BAE6726BAC0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E8483245-31D3-4C42-AAF9-B3195EAB97C2} EndGlobalSection EndGlobal funasr/runtime/wss-client/FunASRClient_CShape.suoBinary files differ
funasr/runtime/wss-client/FunASRWSClient_Offline/FunASRWSClient_Offline.csproj
New file @@ -0,0 +1,14 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net6.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <ItemGroup> <PackageReference Include="Websocket.Client" Version="4.6.1" /> </ItemGroup> </Project> funasr/runtime/wss-client/FunASRWSClient_Offline/Program.cs
New file @@ -0,0 +1,85 @@ using System.Collections.Specialized; using WebSocketSpace; namespace FunASRWSClient_Offline { /// <summary> /// /主程序入口 /// </summary> public class Program { private static void Main() { WSClient_Offline m_funasrclient = new WSClient_Offline(); m_funasrclient.FunASR_Main(); } } public class WSClient_Offline { public static string host = "0.0.0.0"; public static string port = "10095"; private static CWebSocketClient m_websocketclient = new CWebSocketClient(); [STAThread] public async void FunASR_Main() { loadconfig(); //初始化通信连接 string errorStatus = string.Empty; string commstatus = ClientConnTest(); if (commstatus != "通信连接成功") errorStatus = commstatus; //程序初始监测异常--报错、退出 if (errorStatus != string.Empty) { //报错方式待加 Environment.Exit(0); } //循环输入推理文件 while (true) { Console.WriteLine("请输入转录文件路径:"); string filepath = Console.ReadLine(); if (filepath != string.Empty && filepath != null) { await m_websocketclient.ClientSendFileFunc(filepath); } } } private void loadconfig() { string filePath = "config.ini"; NameValueCollection settings = new NameValueCollection(); using (StreamReader reader = new StreamReader(filePath)) { string line; while ((line = reader.ReadLine()) != null) { // 忽略空行和注释 if (string.IsNullOrEmpty(line) || line.StartsWith(";") || line.StartsWith("#")) continue; // 解析键值对 int equalsIndex = line.IndexOf('='); if (equalsIndex > 0) { string key = line.Substring(0, equalsIndex).Trim(); string value = line.Substring(equalsIndex + 1).Trim(); if (key == "host") host = value; else if (key == "port") port = value; } } } } private static string ClientConnTest() { //WebSocket连接状态监测 Task<string> websocketstatus = m_websocketclient.ClientConnTest(); if (websocketstatus != null && websocketstatus.Result.IndexOf("成功") == -1) return websocketstatus.Result; return "通信连接成功"; } } } funasr/runtime/wss-client/FunASRWSClient_Offline/README.md
New file @@ -0,0 +1,9 @@ # cshape-client-offline 这是一个基于FunASR-Websocket服务器的CShape客户端,用于转录本地音频文件。 将配置文件放在与程序相同目录下的config文件夹中,并在config.ini中配置服务器ip地址和端口号。 配置好服务端ip和端口号,在vs中打开需添加Websocket.Client的Nuget程序包后,可直接进行测试,按照控制台提示操作即可。 注:本客户端暂支持wav文件,在win11下完成测试,编译环境VS2022。 funasr/runtime/wss-client/FunASRWSClient_Offline/WebScoketClient.cs
New file @@ -0,0 +1,120 @@ using Websocket.Client; using System.Text.Json; using System.Reactive.Linq; using FunASRWSClient_Offline; namespace WebSocketSpace { internal class CWebSocketClient { private static readonly Uri serverUri = new Uri($"ws://{WSClient_Offline.host}:{WSClient_Offline.port}"); // 你要连接的WebSocket服务器地址 private static WebsocketClient client = new WebsocketClient(serverUri); public async Task<string> ClientConnTest() { string commstatus = "WebSocket通信连接失败"; try { client.Name = "funasr"; client.ReconnectTimeout = null; client.ReconnectionHappened.Subscribe(info => Console.WriteLine($"Reconnection happened, type: {info.Type}, url: {client.Url}")); client.DisconnectionHappened.Subscribe(info => Console.WriteLine($"Disconnection happened, type: {info.Type}")); client .MessageReceived .Where(msg => msg.Text != null) .Subscribe(msg => { recmessage(msg.Text); }); await client.Start(); if (client.IsRunning) commstatus = "WebSocket通信连接成功"; } catch (Exception ex) { Console.WriteLine(ex.ToString()); client.Dispose(); } return commstatus; } public async Task<Task> ClientSendFileFunc(string file_name)//文件转录 { try { if (client.IsRunning) { var exitEvent = new ManualResetEvent(false); string path = Path.GetFileName(file_name); string firstbuff = string.Format("{{\"mode\": \"offline\", \"wav_name\": \"{0}\", \"is_speaking\": true}}", Path.GetFileName(file_name)); client.Send(firstbuff); showWAVForm(client, file_name); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } return Task.CompletedTask; } public void recmessage(string message) { if (message != null) { try { JsonDocument jsonDoc = JsonDocument.Parse(message); JsonElement root = jsonDoc.RootElement; string mode = root.GetProperty("mode").GetString(); string text = root.GetProperty("text").GetString(); string name = root.GetProperty("wav_name").GetString(); if(name == "asr_stream") Console.WriteLine($"实时识别内容: {text}"); else Console.WriteLine($"文件名称:{name} 文件转录内容: {text}"); } catch (JsonException ex) { Console.WriteLine("JSON 解析错误: " + ex.Message); } } } private void showWAVForm(WebsocketClient client, string file_name) { byte[] getbyte = FileToByte(file_name).Skip(44).ToArray(); for (int i = 0; i < getbyte.Length; i += 1024000) { byte[] send = getbyte.Skip(i).Take(1024000).ToArray(); client.Send(send); Thread.Sleep(5); } Thread.Sleep(10); client.Send("{\"is_speaking\": false}"); } public byte[] FileToByte(string fileUrl) { try { using (FileStream fs = new FileStream(fileUrl, FileMode.Open, FileAccess.Read)) { byte[] byteArray = new byte[fs.Length]; fs.Read(byteArray, 0, byteArray.Length); return byteArray; } } catch { return null; } } } } funasr/runtime/wss-client/FunASRWSClient_Online/FunASRWSClient_Online.csproj
New file @@ -0,0 +1,15 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net6.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <ItemGroup> <PackageReference Include="NAudio" Version="2.1.0" /> <PackageReference Include="Websocket.Client" Version="4.6.1" /> </ItemGroup> </Project> funasr/runtime/wss-client/FunASRWSClient_Online/Program.cs
New file @@ -0,0 +1,255 @@ using AliFsmnVadSharp; using NAudio.Wave; using System.Collections.Concurrent; using WebSocketSpace; using NAudio.CoreAudioApi; using System.IO; using System.Collections.Specialized; namespace FunASRWSClient_Online { /// <summary> /// /主程序入口 /// </summary> public class Program { private static void Main() { WSClient_Online m_funasrclient = new WSClient_Online(); m_funasrclient.FunASR_Main(); } } /// <summary> /// /主线程入口,初始化后读取数据 /// </summary> public class WSClient_Online { /// <summary> /// FunASR客户端软件运行状态 /// </summary> /// public static string host = "0.0.0.0"; public static string port = "10095"; public static string onlineasrmode = string.Empty; private static WaveCollect m_wavecollect = new WaveCollect(); private static CWebSocketClient m_websocketclient = new CWebSocketClient(); public static readonly ConcurrentQueue<byte[]> ActiveAudioSet = new ConcurrentQueue<byte[]>(); public static readonly ConcurrentQueue<string> AudioFileQueue = new ConcurrentQueue<string>(); [STAThread] public void FunASR_Main() { loadconfig(); //麦克风状态监测 string errorStatus = string.Empty; if (GetCurrentMicVolume() == -2) errorStatus = "注意:麦克风被设置为静音!"; else if (GetCurrentMicVolume() == -1) errorStatus = "注意:麦克风未连接!"; else if (GetCurrentMicVolume() == 0) errorStatus = "注意:麦克风声音设置为0!"; //初始化通信连接 string commstatus = ClientConnTest(); if (commstatus != "通信连接成功") errorStatus = commstatus; //程序初始监测异常--报错、退出 if (errorStatus != string.Empty) { Environment.Exit(0);//报错方式待加 } //启动客户端向服务端发送音频数据线程 Thread SendAudioThread = new Thread(SendAudioToSeverAsync); SendAudioThread.Start(); //启动音频文件转录线程 Thread AudioFileThread = new Thread(SendAudioFileToSeverAsync); AudioFileThread.Start(); while (true) { Console.WriteLine("请选择语音识别方式:1.离线文件转写;2.实时语音识别"); string str = Console.ReadLine(); if (str != string.Empty) { if (str == "1")//离线文件转写 { onlineasrmode = "offline"; Console.WriteLine("请输入转录文件路径"); str = Console.ReadLine(); if (!string.IsNullOrEmpty(str)) AudioFileQueue.Enqueue(str); } else if (str == "2")//实时语音识别 { Console.WriteLine("请输入实时语音识别模式:1.online;2.2pass"); str = Console.ReadLine(); OnlineASR(str); } } } } private void loadconfig() { string filePath = "config.ini"; NameValueCollection settings = new NameValueCollection(); using (StreamReader reader = new StreamReader(filePath)) { string line; while ((line = reader.ReadLine()) != null) { // 忽略空行和注释 if (string.IsNullOrEmpty(line) || line.StartsWith(";") || line.StartsWith("#")) continue; // 解析键值对 int equalsIndex = line.IndexOf('='); if (equalsIndex > 0) { string key = line.Substring(0, equalsIndex).Trim(); string value = line.Substring(equalsIndex + 1).Trim(); if (key == "host") host = value; else if (key == "port") port = value; } } } } private void OnlineASR(string str) { if (!string.IsNullOrEmpty(str)) { if (str == "1")//实时语音识别 onlineasrmode = "online"; else if (str == "2")//实时语音识别-动态修正 onlineasrmode = "2pass"; } //开始录制声音、发送识别 if (onlineasrmode != string.Empty) { m_wavecollect.StartRec(); m_websocketclient.ClientFirstConnOnline(onlineasrmode); try { while (true) { if (!WaveCollect.voicebuff.IsEmpty) { byte[] buff; int buffcnt = WaveCollect.voicebuff.Count; WaveCollect.voicebuff.TryDequeue(out buff); if (buff != null) ActiveAudioSet.Enqueue(buff); } else { if (Console.KeyAvailable) { var key = Console.ReadKey(true); // 检测到按下Ctrl+C if ((key.Modifiers & ConsoleModifiers.Control) != 0 && key.Key == ConsoleKey.C) { // 执行相应的操作 Console.WriteLine("Ctrl+C Pressed!"); // 退出循环或执行其他操作 break; } } else { Thread.Sleep(10); } } } } catch { Console.WriteLine("实时识别出现异常!"); } finally { m_wavecollect.StopRec(); m_websocketclient.ClientLastConnOnline(); } } } private string ClientConnTest() { //WebSocket连接状态监测 Task<string> websocketstatus = m_websocketclient.ClientConnTest(); if (websocketstatus != null && websocketstatus.Result.IndexOf("成功") == -1) return websocketstatus.Result; return "通信连接成功"; } private void SendAudioFileToSeverAsync() { while (true) { Thread.Sleep(1000); if (AudioFileQueue.Count > 0) { string filepath = string.Empty; AudioFileQueue.TryDequeue(out filepath); if (filepath != string.Empty && filepath != null) { m_websocketclient.ClientSendFileFunc(filepath); } } else { Thread.Sleep(100); } } } private void SendAudioToSeverAsync() { while (true) { if (ActiveAudioSet.Count > 0) { byte[] audio; ActiveAudioSet.TryDequeue(out audio); if (audio == null) continue; byte[] mArray = new byte[audio.Length]; Array.Copy(audio, 0, mArray, 0, audio.Length); if (mArray != null) m_websocketclient.ClientSendAudioFunc(mArray); } else { Thread.Sleep(10); } } } private void SaveAsWav(byte[] pcmData, string fileName, int sampleRate, int bitsPerSample, int channels) { using (var writer = new WaveFileWriter(fileName, new WaveFormat(sampleRate, bitsPerSample, channels))) { writer.Write(pcmData, 0, pcmData.Length); } } private int GetCurrentMicVolume() //获取麦克风设置 { int volume = -1; var enumerator = new MMDeviceEnumerator(); //获取音频输入设备 IEnumerable<MMDevice> captureDevices = enumerator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.Active).ToArray(); if (captureDevices.Count() > 0) { MMDevice mMDevice = captureDevices.ToList()[0]; if (mMDevice.AudioEndpointVolume.Mute) return -2; volume = (int)(mMDevice.AudioEndpointVolume.MasterVolumeLevelScalar * 100); } return volume; } } } funasr/runtime/wss-client/FunASRWSClient_Online/README.md
New file @@ -0,0 +1,9 @@ # cshape-client-online 这是一个基于FunASR-Websocket服务器的CShape客户端,用于实时语音识别和转录本地音频文件。 将配置文件放在与程序相同目录下的config文件夹中,并在config.ini中配置服务器ip地址和端口号。 配置好服务端ip和端口号,在vs中打开需添加NAudio和Websocket.Client的Nuget程序包后,可直接进行测试,按照控制台提示操作即可。 注:实时语音识别使用online或2pass,转录文件默认使用offline,在win11下完成测试,编译环境VS2022。 funasr/runtime/wss-client/FunASRWSClient_Online/WaveCollect.cs
New file @@ -0,0 +1,106 @@ using System.Collections.Concurrent; using NAudio.Wave; using NAudio.CoreAudioApi; namespace AliFsmnVadSharp { class WaveCollect { private string fileName = string.Empty; private WaveInEvent? waveSource = null; private WaveFileWriter? waveFile = null; public static int wave_buffer_milliseconds = 600; public static int wave_buffer_collectbits = 16; public static int wave_buffer_collectchannels = 1; public static int wave_buffer_collectfrequency = 16000; public static readonly ConcurrentQueue<byte[]> voicebuff = new ConcurrentQueue<byte[]>(); public void StartRec() { // 获取麦克风设备 var captureDevices = new MMDeviceEnumerator().EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.Active); foreach (var device in captureDevices) { Console.WriteLine("Device Name: " + device.FriendlyName); using (var capture = new WasapiLoopbackCapture(device)) { // 获取支持的采样率列表 Console.WriteLine("Device Channels:" + capture.WaveFormat.Channels); Console.WriteLine("Device SampleRate:" + capture.WaveFormat.SampleRate); Console.WriteLine("Device BitsPerSample:" + capture.WaveFormat.BitsPerSample); } } //清空缓存数据 int buffnum = voicebuff.Count; for (int i = 0; i < buffnum; i++) voicebuff.TryDequeue(out byte[] buff); waveSource = new WaveInEvent(); waveSource.BufferMilliseconds = wave_buffer_milliseconds; waveSource.WaveFormat = new WaveFormat(wave_buffer_collectfrequency, wave_buffer_collectbits, wave_buffer_collectchannels); // 16bit,16KHz,Mono的录音格式 waveSource.DataAvailable += new EventHandler<WaveInEventArgs>(waveSource_DataAvailable); SetFileName(AppDomain.CurrentDomain.BaseDirectory + "tmp.wav"); waveFile = new WaveFileWriter(fileName, waveSource.WaveFormat); waveSource.StartRecording(); } public void StopRec() { if (waveSource != null) { waveSource.StopRecording(); if (waveSource != null) { waveSource.Dispose(); waveSource = null; } if (waveFile != null) { waveFile.Dispose(); waveFile = null; } } } public void SetFileName(string fileName) { this.fileName = fileName; } private void waveSource_DataAvailable(object sender, WaveInEventArgs e) { if (waveFile != null) { if (e.Buffer != null && e.BytesRecorded > 0) { voicebuff.Enqueue(e.Buffer); //waveFile.Write(e.Buffer, 0, e.BytesRecorded); waveFile.Flush(); } } } public static byte[] Wavedata_Dequeue() { byte[] datas; voicebuff.TryDequeue(out datas); return datas; } private void waveSource_RecordingStopped(object sender, StoppedEventArgs e) { if (waveSource != null) { waveSource.Dispose(); waveSource = null; } if (waveFile != null) { waveFile.Dispose(); waveFile = null; } } } } funasr/runtime/wss-client/FunASRWSClient_Online/WebScoketClient.cs
New file @@ -0,0 +1,219 @@ using System.Net.WebSockets; using Websocket.Client; using System.Text.Json; using NAudio.Wave; using AliFsmnVadSharp; using System.Reactive.Linq; using FunASRWSClient_Online; namespace WebSocketSpace { internal class CWebSocketClient { private static int chunk_interval = 10; private static int[] chunk_size = new int[] { 5, 10, 5 }; private static readonly Uri serverUri = new Uri($"ws://{WSClient_Online.host}:{WSClient_Online.port}"); // 你要连接的WebSocket服务器地址 private static WebsocketClient client = new WebsocketClient(serverUri); public async Task<string> ClientConnTest() { string commstatus = "WebSocket通信连接失败"; try { client.Name = "funasr"; client.ReconnectTimeout = null; client.ReconnectionHappened.Subscribe(info => Console.WriteLine($"Reconnection happened, type: {info.Type}, url: {client.Url}")); client.DisconnectionHappened.Subscribe(info => Console.WriteLine($"Disconnection happened, type: {info.Type}")); client .MessageReceived .Where(msg => msg.Text != null) .Subscribe(msg => { rec_message(msg.Text, client); }); await client.Start(); if (client.IsRunning) commstatus = "WebSocket通信连接成功"; } catch (Exception ex) { Console.WriteLine(ex.ToString()); client.Dispose(); } return commstatus; } public bool ClientFirstConnOnline(string asrmode) { if (client.IsRunning) { string firstbuff = string.Format("{{\"mode\": \"{0}\", \"chunk_size\": [{1},{2},{3}], \"chunk_interval\": {4}, \"wav_name\": \"microphone\", \"is_speaking\": true}}" , asrmode, chunk_size[0], chunk_size[1], chunk_size[2], chunk_interval); Task.Run(() => client.Send(firstbuff)); } else { client.Reconnect(); return false; } return true; } public bool ClientSendAudioFunc(byte[] buff) //实时识别 { if (client.IsRunning) { ////发送音频数据 int CHUNK = WaveCollect.wave_buffer_collectfrequency / 1000 * 60 * chunk_size[1] / chunk_interval; for (int i = 0; i < buff.Length; i += CHUNK) { byte[] send = buff.Skip(i).Take(CHUNK).ToArray(); Task.Run(() => client.Send(send)); Thread.Sleep(1); } } else { client.Reconnect(); return false; } return true; } public void ClientLastConnOnline() { Task.Run(() => client.Send("{\"is_speaking\": false}")); } public int ClientSendFileFunc(string file_name)//文件转录 0:发送成功 ret -1:文件类型不支持 -2:通信断开 { string fileExtension = Path.GetExtension(file_name); fileExtension = fileExtension.Replace(".", ""); if (!(fileExtension == "mp3" || fileExtension == "mp4" || fileExtension == "wav" || fileExtension == "pcm")) return -1; if (client.IsRunning) { if (fileExtension == "wav" || fileExtension == "pcm") { string firstbuff = string.Format("{{\"mode\": \"office\", \"chunk_size\": [{0},{1},{2}], \"chunk_interval\": {3}, \"wav_name\": \"{4}\", \"is_speaking\": true, \"wav_format\":\"pcm\"}}" , chunk_size[0], chunk_size[1], chunk_size[2], chunk_interval, Path.GetFileName(file_name)); Task.Run(() => client.Send(firstbuff)); if (fileExtension == "wav") showWAVForm(file_name); else if (fileExtension == "pcm") showWAVForm_All(file_name); } else if (fileExtension == "mp3" || fileExtension == "mp4") { string firstbuff = string.Format("{{\"mode\": \"offline\", \"chunk_size\": \"{0},{1},{2}\", \"chunk_interval\": {3}, \"wav_name\": \"{4}\", \"is_speaking\": true, \"wav_format\":\"{5}\"}}" , chunk_size[0], chunk_size[1], chunk_size[2], chunk_interval, Path.GetFileName(file_name), fileExtension); Task.Run(() => client.Send(firstbuff)); showWAVForm_All(file_name); } } else { client.Reconnect(); return -2; } return 0; } private string recbuff = string.Empty;//接收累计缓存内容 private string onlinebuff = string.Empty;//接收累计在线缓存内容 public void rec_message(string message, WebsocketClient client) { if (message != null) { try { string name = string.Empty; JsonDocument jsonDoc = JsonDocument.Parse(message); JsonElement root = jsonDoc.RootElement; string mode = root.GetProperty("mode").GetString(); string text = root.GetProperty("text").GetString(); bool isfinal = root.GetProperty("is_final").GetBoolean(); if (message.IndexOf("wav_name ") != -1) name = root.GetProperty("wav_name").GetString(); //if (name == "microphone") // Console.WriteLine($"实时识别内容: {text}"); //else // Console.WriteLine($"文件名称:{name} 文件转录内容: {text}"); if (mode == "2pass-online" && WSClient_Online.onlineasrmode != "offline") { onlinebuff += text; Console.WriteLine(recbuff + onlinebuff); } else if (mode == "2pass-offline") { recbuff += text; onlinebuff = string.Empty; Console.WriteLine(recbuff); } if (isfinal && WSClient_Online.onlineasrmode != "offline")//未结束当前识别 { recbuff = string.Empty; } } catch (JsonException ex) { Console.WriteLine("JSON 解析错误: " + ex.Message); } } } private void showWAVForm(string file_name) { byte[] getbyte = FileToByte(file_name).Skip(44).ToArray(); for (int i = 0; i < getbyte.Length; i += 102400) { byte[] send = getbyte.Skip(i).Take(102400).ToArray(); Task.Run(() => client.Send(send)); Thread.Sleep(5); } Thread.Sleep(100); Task.Run(() => client.Send("{\"is_speaking\": false}")); } private void showWAVForm_All(string file_name) { byte[] getbyte = FileToByte(file_name).ToArray(); for (int i = 0; i < getbyte.Length; i += 1024000) { byte[] send = getbyte.Skip(i).Take(1024000).ToArray(); Task.Run(() => client.Send(send)); Thread.Sleep(5); } Thread.Sleep(10); Task.Run(() => client.Send("{\"is_speaking\": false}")); } public byte[] FileToByte(string fileUrl) { try { using (FileStream fs = new FileStream(fileUrl, FileMode.Open, FileAccess.Read)) { byte[] byteArray = new byte[fs.Length]; fs.Read(byteArray, 0, byteArray.Length); return byteArray; } } catch { return null; } } } } funasr/runtime/wss-client/confg/config.ini
New file @@ -0,0 +1,2 @@ host=127.0.0.1 port=10095 funasr/runtime/wss-client/confg/tmp.wavBinary files differ