Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reintroduce TTS WS #316

Merged
merged 1 commit into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions Deepgram.Dev.sln
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "speech-to-text", "speech-to
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "rest", "rest", "{C1A7ADF7-ACAC-4B10-8266-C7224156C012}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "websocket", "websocket", "{889B3075-777E-476D-BB18-B1CD647F1893}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "file", "file", "{F2DCE1E6-FC12-4CA5-A738-5A3F359B8A96}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "hello-world", "hello-world", "{F31817AD-AC9F-4021-A9E0-7C26C31D5744}"
Expand All @@ -159,6 +161,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "models", "models", "{1CC0C0
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Models", "examples\manage\models\Models.csproj", "{918E56D3-FABF-4F50-AC01-8DDFF58FB0CE}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "simple", "simple", "{2F92D959-D3C7-4EFF-8549-C6162E517644}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Speak", "examples\text-to-speech\websocket\simple\Speak.csproj", "{ECB0B55E-54C1-4723-8641-9249E7507FB0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -293,6 +299,10 @@ Global
{918E56D3-FABF-4F50-AC01-8DDFF58FB0CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{918E56D3-FABF-4F50-AC01-8DDFF58FB0CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{918E56D3-FABF-4F50-AC01-8DDFF58FB0CE}.Release|Any CPU.Build.0 = Release|Any CPU
{ECB0B55E-54C1-4723-8641-9249E7507FB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ECB0B55E-54C1-4723-8641-9249E7507FB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ECB0B55E-54C1-4723-8641-9249E7507FB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ECB0B55E-54C1-4723-8641-9249E7507FB0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -362,13 +372,16 @@ Global
{B98F6A00-292E-431F-8B11-0CFCA5FD1E37} = {02746530-6811-4F1B-8851-544C89CA66DA}
{5EEA8D9D-0C0D-4EE3-93B1-F0133C629478} = {C673DFD1-528A-4BAE-94E6-02EF058AC363}
{C1A7ADF7-ACAC-4B10-8266-C7224156C012} = {E2E3000D-FBBA-450E-A4E0-3542B38ADAFD}
{889B3075-777E-476D-BB18-B1CD647F1893} = {E2E3000D-FBBA-450E-A4E0-3542B38ADAFD}
{F2DCE1E6-FC12-4CA5-A738-5A3F359B8A96} = {C1A7ADF7-ACAC-4B10-8266-C7224156C012}
{F31817AD-AC9F-4021-A9E0-7C26C31D5744} = {F2DCE1E6-FC12-4CA5-A738-5A3F359B8A96}
{E1B8DE3D-2B86-4A60-BDC1-A7F425986DC1} = {F2DCE1E6-FC12-4CA5-A738-5A3F359B8A96}
{1850D8CC-ADFD-4187-80D4-C5DBDA55B6E3} = {F31817AD-AC9F-4021-A9E0-7C26C31D5744}
{12115887-AFBF-4EEF-953D-936B9D810E97} = {E1B8DE3D-2B86-4A60-BDC1-A7F425986DC1}
{1CC0C0DE-55D9-4B83-9070-1668A4472A27} = {FA5723B3-74E9-4221-80EF-4833C1C3DD9F}
{918E56D3-FABF-4F50-AC01-8DDFF58FB0CE} = {1CC0C0DE-55D9-4B83-9070-1668A4472A27}
{2F92D959-D3C7-4EFF-8549-C6162E517644} = {889B3075-777E-476D-BB18-B1CD647F1893}
{ECB0B55E-54C1-4723-8641-9249E7507FB0} = {2F92D959-D3C7-4EFF-8549-C6162E517644}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8D4ABC6D-7126-4EE2-9303-43A954616B2A}
Expand Down
3 changes: 1 addition & 2 deletions Deepgram.Tests/UnitTests/ClientTests/SpeakClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ public async Task StreamCallBack_Should_Throw_ArgumentException_With_No_CallBack
var expectedResponse = new AutoFaker<AsyncResponse>().Generate();
var speakSchema = new AutoFaker<SpeakSchema>().Generate();
var source = new TextSource("Hello World!");
speakSchema.CallBack = null;

// Fake Client
var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse);
Expand All @@ -160,8 +161,6 @@ public async Task StreamCallBack_Should_Throw_ArgumentException_With_No_CallBack
// Mock Methods
speakClient.When(x => x.PostAsync<Stream, SpeakSchema, AsyncResponse>(Arg.Any<string>(), Arg.Any<SpeakSchema>(), Arg.Any<Stream>())).DoNotCallBase();
speakClient.PostAsync<Stream, SpeakSchema, AsyncResponse>(url, Arg.Any<SpeakSchema>(), Arg.Any<Stream>()).Returns(expectedResponse);

speakSchema.CallBack = null;

// Act and Assert
await speakClient.Invoking(y => y.StreamCallBack(source, null, speakSchema))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public void Should_Return_HttpClient_With_Default_BaseAddress_And_Custom_Headers
{
// Input and Output
var _apiKey = new Faker().Random.Guid().ToString();
var _clientOptions = new DeepgramHttpClientOptions(_apiKey, null, null, FakeHeaders());
var _clientOptions = new DeepgramHttpClientOptions(_apiKey, null, null, null, FakeHeaders());

// Fake Clients
var httpClient = MockHttpClient.CreateHttpClientWithResult(new MessageResponse(), HttpStatusCode.OK);
Expand All @@ -95,7 +95,7 @@ public void Should_Return_HttpClient_With_Custom_BaseAddress_And_Custom_Headers(
var expectedBaseAddress = $"https://{_customUrl}/v1";
var customBaseAddress = $"https://{_customUrl}";
var _apiKey = new Faker().Random.Guid().ToString();
var _clientOptions = new DeepgramHttpClientOptions(_apiKey, customBaseAddress, null, FakeHeaders());
var _clientOptions = new DeepgramHttpClientOptions(_apiKey, customBaseAddress, null, null, FakeHeaders());

// Fake Clients
var httpClient = MockHttpClient.CreateHttpClientWithResult(new MessageResponse(), HttpStatusCode.OK);
Expand All @@ -122,7 +122,7 @@ public void Should_Return_HttpClient_With_Predefined_Values()
var expectedBaseAddress = $"https://{_customUrl}/v1";
var customBaseAddress = $"https://{_customUrl}";
var _apiKey = new Faker().Random.Guid().ToString();
var _clientOptions = new DeepgramHttpClientOptions(_apiKey, customBaseAddress, null, FakeHeaders());
var _clientOptions = new DeepgramHttpClientOptions(_apiKey, customBaseAddress, null, null, FakeHeaders());

// Fake Clients
var httpClient = MockHttpClient.CreateHttpClientWithResult(new MessageResponse(), HttpStatusCode.OK, expectedBaseAddress);
Expand Down
20 changes: 10 additions & 10 deletions Deepgram/ClientFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,14 @@ public static ISpeakRESTClient CreateSpeakRESTClient(string apiKey = "", Deepgra
return new SpeakRESTClient(apiKey, options, httpId);
}

///// <summary>
///// Create a new AnalyzeClient
///// </summary>
///// <param name="apiKey"></param>
///// <param name="options"></param>
///// <returns></returns>
//public static ISpeakWebSocketClient CreateSpeakWebSocketClient(string apiKey = "", DeepgramWsClientOptions? options = null)
//{
// return new SpeakWebSocketClient(apiKey, options);
//}
/// <summary>
/// Create a new AnalyzeClient
/// </summary>
/// <param name="apiKey"></param>
/// <param name="options"></param>
/// <returns></returns>
public static ISpeakWebSocketClient CreateSpeakWebSocketClient(string apiKey = "", DeepgramWsClientOptions? options = null)
{
return new SpeakWebSocketClient(apiKey, options);
}
}
149 changes: 149 additions & 0 deletions Deepgram/Clients/Interfaces/v1/ISpeakWebSocketClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved.
// Use of this source code is governed by a MIT license that can be found in the LICENSE file.
// SPDX-License-Identifier: MIT

using Deepgram.Models.Speak.v1.WebSocket;

namespace Deepgram.Clients.Interfaces.v1;

/// <summary>
/// Implements version 1 of the Live Client.
/// </summary>
public interface ISpeakWebSocketClient
{
#region Connect and Disconnect
public Task Connect(SpeakSchema options, CancellationTokenSource? cancelToken = null, Dictionary<string, string>? addons = null,
Dictionary<string, string>? headers = null);

public Task Stop(CancellationTokenSource? cancelToken = null);
#endregion

#region Subscribe Event
/// <summary>
/// Subscribe to an Open event from the Deepgram API
/// </summary>
/// <param name="eventHandler"></param>
/// <returns>True if successful</returns>
public bool Subscribe(EventHandler<OpenResponse> eventHandler);

/// <summary>
/// Subscribe to a Metadata event from the Deepgram API
/// </summary>
/// <param name="eventHandler"></param>
/// <returns>True if successful</returns>
public bool Subscribe(EventHandler<MetadataResponse> eventHandler);

/// <summary>
/// Subscribe to a Flushed event from the Deepgram API
/// </summary>
/// <returns>True if successful</returns>
public bool Subscribe(EventHandler<FlushedResponse> eventHandler);

/// <summary>
/// Subscribe to a Cleared event from the Deepgram API
/// </summary>
/// <returns>True if successful</returns>
public bool Subscribe(EventHandler<ClearedResponse> eventHandler);

/// <summary>
/// Subscribe to a Audio buffer/event from the Deepgram API
/// </summary>
/// <returns>True if successful</returns>
public bool Subscribe(EventHandler<AudioResponse> eventHandler);

/// <summary>
/// Subscribe to a Close event from the Deepgram API
/// </summary>
/// <returns>True if successful</returns>
public bool Subscribe(EventHandler<CloseResponse> eventHandler);

/// <summary>
/// Subscribe to an Unhandled event from the Deepgram API
/// </summary>
/// <returns>True if successful</returns>
public bool Subscribe(EventHandler<UnhandledResponse> eventHandler);

/// <summary>
/// Subscribe to an Warning event from the Deepgram API
/// </summary>
/// <returns>True if successful</returns>
public bool Subscribe(EventHandler<WarningResponse> eventHandler);


/// <summary>
/// Subscribe to an Error event from the Deepgram API
/// </summary>
/// <returns>True if successful</returns>
public bool Subscribe(EventHandler<ErrorResponse> eventHandler);
#endregion

#region Send Functions
/// <summary>
/// Sends text data over the WebSocket connection.
/// </summary>
/// <param name="data"></param>
public void SpeakWithText(string data);

///// <summary>
///// This method Flushes the text buffer on Deepgram to be converted to audio
///// </summary>
public void Flush();

///// <summary>
///// This method Resets the text buffer on Deepgram to be converted to audio
///// </summary>
public void Clear();

///// <summary>
///// This method tells Deepgram to initiate the close server-side.
///// </summary>
public void Close();

///// <summary>
///// This method sends a binary message over the WebSocket connection.
///// </summary>
///// <param name="data"></param>
//public void SpeakWithStream(byte[] data);

/// <summary>
/// Sends a binary message over the WebSocket connection.
/// </summary>
/// <param name="data">The data to be sent over the WebSocket.</param>
public void Send(byte[] data);

///// <summary>
///// This method sends a binary message over the WebSocket connection.
///// </summary>
///// <param name="data"></param>
//public void SendBinary(byte[] data);

/// <summary>
/// This method sends a text message over the WebSocket connection.
/// </summary>
public void SendMessage(byte[] data);

///// <summary>
///// This method sends a binary message over the WebSocket connection immediately without queueing.
///// </summary>
//public void SendBinaryImmediately(byte[] data);

/// <summary>
/// This method sends a text message over the WebSocket connection immediately without queueing.
/// </summary>
public void SendMessageImmediately(byte[] data);
davidvonthenen marked this conversation as resolved.
Show resolved Hide resolved
#endregion

#region Helpers
/// <summary>
/// Retrieves the connection state of the WebSocket
/// </summary>
/// <returns>Returns the connection state of the WebSocket</returns>
public WebSocketState State();

/// <summary>
/// Indicates whether the WebSocket is connected
/// </summary>
/// <returns>Returns true if the WebSocket is connected</returns>
public bool IsConnected();
#endregion
}
2 changes: 1 addition & 1 deletion Deepgram/Clients/Listen/v1/WebSocket/Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@
Log.Verbose("ProcessDataReceived", $"Type: {val}");


if (_deepgramClientOptions.InspectMessage())
if (_deepgramClientOptions.InspectListenMessage())
{
Log.Debug("ProcessDataReceived", "Call InspectMessage...");
InspectMessage(val, data);
Expand Down Expand Up @@ -967,7 +967,7 @@

if (_deepgramClientOptions.AutoFlushReplyDelta > 0)
{
if ((bool)resultResponse.IsFinal)

Check warning on line 970 in Deepgram/Clients/Listen/v1/WebSocket/Client.cs

View workflow job for this annotation

GitHub Actions / build

Nullable value type may be null.

Check warning on line 970 in Deepgram/Clients/Listen/v1/WebSocket/Client.cs

View workflow job for this annotation

GitHub Actions / test (6.0.x)

Nullable value type may be null.

Check warning on line 970 in Deepgram/Clients/Listen/v1/WebSocket/Client.cs

View workflow job for this annotation

GitHub Actions / test (7.0.x)

Nullable value type may be null.

Check warning on line 970 in Deepgram/Clients/Listen/v1/WebSocket/Client.cs

View workflow job for this annotation

GitHub Actions / test (8.0.x)

Nullable value type may be null.
{
var now = DateTime.Now;
Log.Debug("InspectMessage", $"AutoFlush IsFinal received. Time: {now}");
Expand Down
Loading
Loading