| 1 | using Deepgram; |
| 2 | using Deepgram.Logger; |
| 3 | using Deepgram.Models.Authenticate.v1; |
| 4 | using Deepgram.Models.Agent.v2.WebSocket; |
| 5 | using System.Collections.Generic; |
| 6 | using System.Net.Http; |
| 7 | |
| 8 | namespace SampleApp |
| 9 | { |
| 10 | class Program |
| 11 | { |
| 12 | static async Task Main(string[] args) |
| 13 | { |
| 14 | try |
| 15 | { |
| 16 | Deepgram.Library.Initialize(LogLevel.Debug); |
| 17 | |
| 18 | var apiKey = Environment.GetEnvironmentVariable("DEEPGRAM_API_KEY"); |
| 19 | DeepgramWsClientOptions options = new DeepgramWsClientOptions(null, null, true); |
| 20 | var agentClient = ClientFactory.CreateAgentWebSocketClient(apiKey, options); |
| 21 | |
| 22 | var lastAudioTime = DateTime.Now; |
| 23 | var audioFileCount = 0; |
| 24 | |
| 25 | var settingsConfiguration = new SettingsSchema(); |
| 26 | settingsConfiguration.Agent.Think.Provider.Type = "open_ai"; |
| 27 | settingsConfiguration.Agent.Think.Provider.Model = "gpt-4o-mini"; |
| 28 | settingsConfiguration.Audio.Output.SampleRate = 24000; |
| 29 | settingsConfiguration.Audio.Output.Container = "wav"; |
| 30 | settingsConfiguration.Audio.Input.SampleRate = 24000; |
| 31 | settingsConfiguration.Agent.Greeting = "Hello, how can I help you today?"; |
| 32 | settingsConfiguration.Agent.Listen.Provider.Type = "deepgram"; |
| 33 | settingsConfiguration.Agent.Listen.Provider.Model = "nova-3"; |
| 34 | settingsConfiguration.Agent.Speak.Provider.Type = "deepgram"; |
| 35 | settingsConfiguration.Agent.Speak.Provider.Model = "aura-2-thalia-en"; |
| 36 | |
| 37 | bool connected = await agentClient.Connect(settingsConfiguration); |
| 38 | if (!connected) |
| 39 | { |
| 40 | Console.WriteLine("Failed to connect to Deepgram WebSocket server."); |
| 41 | return; |
| 42 | } |
| 43 | |
| 44 | await agentClient.Subscribe(new EventHandler<AudioResponse>((sender, e) => |
| 45 | { |
| 46 | if (DateTime.Now.Subtract(lastAudioTime).TotalSeconds > 7) |
| 47 | { |
| 48 | audioFileCount++; |
| 49 | using (BinaryWriter writer = new BinaryWriter(File.Open($"output_{audioFileCount}.wav", FileMode.Create))) |
| 50 | { |
| 51 | writer.Write(CreateWavHeader(24000, 16, 1)); |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | if (e.Stream != null) |
| 56 | { |
| 57 | using (BinaryWriter writer = new BinaryWriter(File.Open($"output_{audioFileCount}.wav", FileMode.Append))) |
| 58 | { |
| 59 | writer.Write(e.Stream.ToArray()); |
| 60 | } |
| 61 | } |
| 62 | lastAudioTime = DateTime.Now; |
| 63 | })); |
| 64 | |
| 65 | string url = "https://dpgr.am/spacewalk.wav"; |
| 66 | using (var httpClient = new HttpClient()) |
| 67 | { |
| 68 | var response = await httpClient.GetAsync(url); |
| 69 | var stream = await response.Content.ReadAsStreamAsync(); |
| 70 | var buffer = new byte[8192]; |
| 71 | int bytesRead; |
| 72 | |
| 73 | while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0) |
| 74 | { |
| 75 | var chunk = new byte[bytesRead]; |
| 76 | Array.Copy(buffer, chunk, bytesRead); |
| 77 | await agentClient.SendBinaryImmediately(chunk); |
| 78 | } |
| 79 | } |
| 80 | |
| 81 | Console.WriteLine("Press any key to exit..."); |
| 82 | Console.ReadKey(); |
| 83 | |
| 84 | await agentClient.Stop(); |
| 85 | Deepgram.Library.Terminate(); |
| 86 | } |
| 87 | catch (Exception ex) |
| 88 | { |
| 89 | Console.WriteLine($"Exception: {ex.Message}"); |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | static byte[] CreateWavHeader(int sampleRate, short bitsPerSample, short channels) |
| 94 | { |
| 95 | int byteRate = sampleRate * channels * (bitsPerSample / 8); |
| 96 | short blockAlign = (short)(channels * (bitsPerSample / 8)); |
| 97 | byte[] header = new byte[44]; |
| 98 | |
| 99 | header[0] = 0x52; // R |
| 100 | header[1] = 0x49; // I |
| 101 | header[2] = 0x46; // F |
| 102 | header[3] = 0x46; // F |
| 103 | header[8] = 0x57; // W |
| 104 | header[9] = 0x41; // A |
| 105 | header[10] = 0x56; // V |
| 106 | header[11] = 0x45; // E |
| 107 | header[12] = 0x66; // f |
| 108 | header[13] = 0x6D; // m |
| 109 | header[14] = 0x74; // t |
| 110 | header[15] = 0x20; // Space |
| 111 | header[16] = 0x10; // Subchunk1Size |
| 112 | header[20] = 0x01; // AudioFormat |
| 113 | header[22] = (byte)channels; |
| 114 | header[24] = (byte)(sampleRate & 0xFF); |
| 115 | header[25] = (byte)((sampleRate >> 8) & 0xFF); |
| 116 | header[26] = (byte)((sampleRate >> 16) & 0xFF); |
| 117 | header[27] = (byte)((sampleRate >> 24) & 0xFF); |
| 118 | header[28] = (byte)(byteRate & 0xFF); |
| 119 | header[29] = (byte)((byteRate >> 8) & 0xFF); |
| 120 | header[30] = (byte)((byteRate >> 16) & 0xFF); |
| 121 | header[31] = (byte)((byteRate >> 24) & 0xFF); |
| 122 | header[32] = (byte)blockAlign; |
| 123 | header[34] = (byte)bitsPerSample; |
| 124 | header[36] = 0x64; // d |
| 125 | header[37] = 0x61; // t |
| 126 | header[38] = 0x74; // t |
| 127 | header[39] = 0x61; // a |
| 128 | |
| 129 | return header; |
| 130 | } |
| 131 | } |
| 132 | } |