diff --git a/Deepgram/Abstractions/AbstractRestClient.cs b/Deepgram/Abstractions/AbstractRestClient.cs index d2375e0f..6eec2b63 100644 --- a/Deepgram/Abstractions/AbstractRestClient.cs +++ b/Deepgram/Abstractions/AbstractRestClient.cs @@ -3,7 +3,6 @@ // SPDX-License-Identifier: MIT using Deepgram.Encapsulations; -using Deepgram.Models.Analyze.v1; using Deepgram.Models.Authenticate.v1; namespace Deepgram.Abstractions; diff --git a/Deepgram/Models/Live/v1/NoopSchema.cs b/Deepgram/Abstractions/NoopSchema.cs similarity index 87% rename from Deepgram/Models/Live/v1/NoopSchema.cs rename to Deepgram/Abstractions/NoopSchema.cs index 7839c378..6d72526a 100644 --- a/Deepgram/Models/Live/v1/NoopSchema.cs +++ b/Deepgram/Abstractions/NoopSchema.cs @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT -namespace Deepgram.Models.Live.v1; +namespace Deepgram.Abstractions; public class NoopSchema { diff --git a/Deepgram/Clients/Live/v1/Client.cs b/Deepgram/Clients/Live/v1/Client.cs index 2a9f0eec..3f9e159e 100644 --- a/Deepgram/Clients/Live/v1/Client.cs +++ b/Deepgram/Clients/Live/v1/Client.cs @@ -2,6 +2,8 @@ // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT +using System; +using System.Diagnostics.Tracing; using Deepgram.Models.Authenticate.v1; using Deepgram.Models.Live.v1; @@ -10,14 +12,14 @@ namespace Deepgram.Clients.Live.v1; /// /// Implements version 1 of the Live Client. /// -public class Client : IDisposable +public class Client : Attribute, IDisposable { #region Fields internal ILogger logger => LogProvider.GetLogger(this.GetType().Name); internal readonly DeepgramWsClientOptions _deepgramClientOptions; + internal ClientWebSocket? _clientWebSocket; internal CancellationTokenSource _cancellationTokenSource; - internal bool _isDisposed; #endregion /// Required DeepgramApiKey @@ -30,9 +32,16 @@ public Client(string? apiKey = null, DeepgramWsClientOptions? options = null) #region Subscribe Events /// - /// Fires when transcription metadata is received from the Deepgram API - /// - public event EventHandler? EventResponseReceived; + /// Fires when an event is received from the Deepgram API + /// + public event EventHandler? _openReceived; + public event EventHandler? _metadataReceived; + public event EventHandler? _resultsReceived; + public event EventHandler? _utteranceEndReceived; + public event EventHandler? _speechStartedReceived; + public event EventHandler? _closeReceived; + public event EventHandler? _unhandledReceived; + public event EventHandler? _errorReceived; #endregion //TODO when a response is received check if it is a transcript(LiveTranscriptionEvent) or metadata (LiveMetadataEvent) response @@ -44,10 +53,21 @@ public Client(string? apiKey = null, DeepgramWsClientOptions? options = null) /// The task object representing the asynchronous operation. public async Task Connect(LiveSchema options, CancellationTokenSource? cancellationToken = null, Dictionary? addons = null, Dictionary? headers = null) { + // check if the client is disposed + if (_clientWebSocket != null) + { + // client has already connected + // TODO: logging + var ex = new Exception("Client has already been initialized"); + ProcessException("Connect", ex); + throw ex; + } + // create client _clientWebSocket = new ClientWebSocket(); // set headers + _clientWebSocket.Options.SetRequestHeader("Authorization", $"token {_deepgramClientOptions.ApiKey}"); if (_deepgramClientOptions.Headers is not null) { foreach (var header in _deepgramClientOptions.Headers) @@ -94,6 +114,37 @@ void StartReceiverBackgroundThread() => _ = Task.Factory.StartNew( TaskCreationOptions.LongRunning); } + //// TODO: convienence method for subscribing to events + //public void On(T e, EventHandler eventHandler) { + // switch (e) + // { + // case OpenResponse open: + // OpenReceived += (sender, e) => eventHandler; + // break; + // case MetadataResponse metadata: + // MetadataReceived += (sender, e) => eventHandler; + // break; + // case ResultResponse result: + // ResultsReceived += (sender, e) => eventHandler; + // break; + // case UtteranceEndResponse utteranceEnd: + // UtteranceEndReceived += (sender, e) => eventHandler; + // break; + // case SpeechStartedResponse speechStarted: + // SpeechStartedReceived += (sender, e) => eventHandler; + // break; + // case CloseResponse close: + // CloseReceived += (sender, e) => eventHandler; + // break; + // case UnhandledResponse unhandled: + // UnhandledReceived += (sender, e) => eventHandler; + // break; + // case ErrorResponse error: + // ErrorReceived += (sender, e) => eventHandler; + // break; + // } + //} + /// /// Sends a binary message over the WebSocket connection. /// @@ -115,7 +166,7 @@ internal void EnqueueSendMessage(WebSocketMessage message) internal async Task ProcessSendQueue() { - if (_isDisposed) + if (_clientWebSocket == null) { var ex = new Exception( "Attempting to start a sender queue when the WebSocket has been disposed is not allowed."); @@ -146,26 +197,36 @@ internal async Task ProcessReceiveQueue() { try { - var buffer = new ArraySegment(new byte[1024 * 16]); // Default receive buffer size + if (_cancellationTokenSource.Token.IsCancellationRequested) + { + // TODO: logging + break; + } + + var buffer = new ArraySegment(new byte[Constants.BufferSize]); WebSocketReceiveResult result; using (var ms = new MemoryStream()) { do { + // get the result of the receive operation result = await _clientWebSocket.ReceiveAsync(buffer, _cancellationTokenSource.Token); - if (result.MessageType == WebSocketMessageType.Close) - { - Log.RequestedSocketClose(logger, result.CloseStatusDescription!); - break; - } ms.Write( buffer.Array ?? throw new InvalidOperationException("buffer cannot be null"), buffer.Offset, - result.Count); + result.Count + ); } while (!result.EndOfMessage); + if (result.MessageType == WebSocketMessageType.Close) + { + Log.RequestedSocketClose(logger, result.CloseStatusDescription!); + break; + } + + // TODO: replace with fine grained event handling ProcessDataReceived(result, ms); } @@ -195,26 +256,96 @@ internal void ProcessDataReceived(WebSocketReceiveResult result, MemoryStream ms { try { - var eventResponse = new EventResponse(); + var data = JsonDocument.Parse(response); var val = Enum.Parse(typeof(LiveType), data.RootElement.GetProperty("type").GetString()!); switch (val) - { + { + case LiveType.Open: + //var openResponse = new ResponseEvent(data.Deserialize()); + var openResponse = data.Deserialize(); + if (_openReceived == null || openResponse == null) + { + return; + } + _openReceived.Invoke(null, data.Deserialize()); + //InvokeResponseReceived(_openReceived, openResponse); + break; case LiveType.Results: - eventResponse.Transcription = data.Deserialize()!; + //var eventResponse = new ResponseEvent(data.Deserialize()); + var eventResponse = data.Deserialize(); + if (_resultsReceived == null || eventResponse == null) + { + return; + } + _resultsReceived.Invoke(null, data.Deserialize()); + //InvokeResponseReceived(_resultsReceived, eventResponse); break; case LiveType.Metadata: - eventResponse.MetaData = data.Deserialize()!; + //var metadataResponse = new ResponseEvent(data.Deserialize()); + var metadataResponse = data.Deserialize(); + if (_metadataReceived == null || metadataResponse == null) + { + return; + } + _metadataReceived.Invoke(null, data.Deserialize()); + //InvokeResponseReceived(_metadataReceived, metadataResponse); break; case LiveType.UtteranceEnd: - eventResponse.UtteranceEnd = data.Deserialize()!; + //var utteranceEndResponse = new ResponseEvent(data.Deserialize()); + var utteranceEndResponse = data.Deserialize(); + if (_utteranceEndReceived == null || utteranceEndResponse == null) + { + return; + } + _utteranceEndReceived.Invoke(null, data.Deserialize()); + //InvokeResponseReceived(_utteranceEndReceived, utteranceEndResponse); break; case LiveType.SpeechStarted: - eventResponse.SpeechStarted = data.Deserialize()!; + //var speechStartedResponse = new ResponseEvent(data.Deserialize()); + var speechStartedResponse = data.Deserialize(); + if (_speechStartedReceived == null || speechStartedResponse == null) + { + return; + } + _speechStartedReceived.Invoke(null, data.Deserialize()); + //InvokeResponseReceived(_speechStartedReceived, speechStartedResponse); + break; + case LiveType.Close: + //var closeResponse = new ResponseEvent(data.Deserialize()); + var closeResponse = data.Deserialize(); + if (_closeReceived == null || closeResponse == null) + { + return; + } + _closeReceived.Invoke(null, data.Deserialize()); + //InvokeResponseReceived(_closeReceived, closeResponse); + break; + case LiveType.Error: + //var errorResponse = new ResponseEvent(data.Deserialize()); + var errorResponse = data.Deserialize(); + if (_errorReceived == null || errorResponse == null) + { + return; + } + _errorReceived.Invoke(null, data.Deserialize()); + //InvokeResponseReceived(_errorReceived, errorResponse); + break; + default: + if (_unhandledReceived == null) + { + return; + } + //var unhandledResponse = new ResponseEvent(data.Deserialize()); + var unhandledResponse = new UnhandledResponse(); + unhandledResponse.Type = LiveType.Unhandled; + unhandledResponse.Raw = response; + + _unhandledReceived.Invoke(null, unhandledResponse); + //InvokeResponseReceived(_unhandledReceived, unhandledResponse); break; } - EventResponseReceived?.Invoke(null, new ResponseEventArgs(eventResponse)); } catch (Exception ex) { @@ -228,14 +359,27 @@ internal void ProcessDataReceived(WebSocketReceiveResult result, MemoryStream ms /// Closes the Web Socket connection to the Deepgram API /// /// The task object representing the asynchronous operation. - public async Task Stop(CancellationToken? cancellationToken = null) + public async Task Stop(CancellationTokenSource? cancellationToken = null) { - // send the close message and flush transcription messages - if (_clientWebSocket!.State != WebSocketState.Open) + var cancelToken = _cancellationTokenSource.Token; + if (cancellationToken != null) + { + cancelToken = cancellationToken.Token; + } + + // client is already disposed + if (_clientWebSocket == null) + { + // TODO: logging return; + } - await _clientWebSocket.SendAsync(new ArraySegment([]), WebSocketMessageType.Binary, true, _cancellationTokenSource.Token) + // send the close message and flush transcription message + if (_clientWebSocket!.State == WebSocketState.Open) + { + await _clientWebSocket.SendAsync(new ArraySegment([]), WebSocketMessageType.Binary, true, cancelToken) .ConfigureAwait(false); + } // attempt to stop the connection try @@ -245,20 +389,21 @@ await _clientWebSocket.SendAsync(new ArraySegment([]), WebSocketMessageTyp Log.ClosingSocket(logger); } - if (!_isDisposed) + if (_clientWebSocket!.State != WebSocketState.Closed) { - if (_clientWebSocket!.State != WebSocketState.Closed) - { - await _clientWebSocket.CloseOutputAsync( - WebSocketCloseStatus.NormalClosure, - string.Empty, - _cancellationTokenSource.Token) - .ConfigureAwait(false); - } + await _clientWebSocket.CloseOutputAsync( + WebSocketCloseStatus.NormalClosure, + string.Empty, + cancelToken) + .ConfigureAwait(false); + } - // Always request cancellation to the local token source, if some function has been called without a token - _cancellationTokenSource.Cancel(); + // Always request cancellation to the local token source, if some function has been called without a token + if (cancellationToken != null) + { + cancellationToken.Cancel(); } + _cancellationTokenSource.Cancel(); } catch (Exception ex) { @@ -273,9 +418,21 @@ await _clientWebSocket.CloseOutputAsync( /// Returns the connection state of the WebSocket public WebSocketState State() => _clientWebSocket.State; + /// + /// Indicates whether the WebSocket is connected + /// + /// Returns true if the WebSocket is connected + public bool IsConnected() => _clientWebSocket.State == WebSocketState.Open; + + /// + /// TODO + /// internal readonly Channel _sendChannel = System.Threading.Channels.Channel .CreateUnbounded(new UnboundedChannelOptions { SingleReader = true, SingleWriter = true, }); + /// + /// TODO + /// internal static Uri GetUri(DeepgramWsClientOptions options, LiveSchema parameter, Dictionary? addons = null) { var propertyInfoList = parameter.GetType() @@ -287,34 +444,57 @@ internal static Uri GetUri(DeepgramWsClientOptions options, LiveSchema parameter return new Uri($"{options.BaseAddress}/{UriSegments.LISTEN}?{queryString}"); } + /// + /// TODO + /// private void ProcessException(string action, Exception ex) { - if (_isDisposed) + if (_clientWebSocket == null) Log.SocketDisposed(logger, action, ex); else Log.Exception(logger, action, ex); - EventResponseReceived?.Invoke(null, new ResponseEventArgs(new EventResponse() { Error = ex })); + //EventResponseReceived?.Invoke(null, new ResponseEventArgs(new EventResponse() { Error = ex })); } #endregion #region Dispose + /// + /// TODO + /// public void Dispose() { - if (_isDisposed) + if (_clientWebSocket == null) { return; } - + if (_cancellationTokenSource != null) { - _cancellationTokenSource.Cancel(); + if (!_cancellationTokenSource.Token.IsCancellationRequested) + { + _cancellationTokenSource.Cancel(); + } _cancellationTokenSource.Dispose(); } - _sendChannel?.Writer.Complete(); - _clientWebSocket?.Dispose(); - _isDisposed = true; + if (_sendChannel != null) + { + _sendChannel.Writer.Complete(); + } + + _clientWebSocket.Dispose(); GC.SuppressFinalize(this); } + + //internal void InvokeResponseReceived(EventHandler eventHandler, ResponseEvent e) + //{ + // if (eventHandler != null) + // { + // Parallel.ForEach( + // eventHandler.GetInvocationList().Cast(), + // (handler) => + // handler(null, e)); + // } + //} #endregion } diff --git a/Deepgram/Clients/Live/v1/Constants.cs b/Deepgram/Clients/Live/v1/Constants.cs new file mode 100644 index 00000000..8de49ed7 --- /dev/null +++ b/Deepgram/Clients/Live/v1/Constants.cs @@ -0,0 +1,15 @@ +// 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 + +namespace Deepgram.Clients.Live.v1; + +/// +/// Headers of interest in the return values from the Deepgram Speak API. +/// +public static class Constants +{ + // WS buffer size + public const int BufferSize = 1024 * 16; +} + diff --git a/Deepgram/Clients/Live/v1/ResponseEventArgs.cs b/Deepgram/Clients/Live/v1/ResponseEvent.cs similarity index 61% rename from Deepgram/Clients/Live/v1/ResponseEventArgs.cs rename to Deepgram/Clients/Live/v1/ResponseEvent.cs index 364dd737..bab1c38e 100644 --- a/Deepgram/Clients/Live/v1/ResponseEventArgs.cs +++ b/Deepgram/Clients/Live/v1/ResponseEvent.cs @@ -2,12 +2,10 @@ // 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.Live.v1; - namespace Deepgram.Clients.Live.v1; -public class ResponseEventArgs(EventResponse response) : EventArgs +public class ResponseEvent(T? response) : EventArgs { - public EventResponse Response { get; set; } = response; + public T? Response { get; set; } = response; } diff --git a/Deepgram/Models/Analyze/v1/NoopSchema.cs b/Deepgram/Models/Analyze/v1/NoopSchema.cs deleted file mode 100644 index a4a561fb..00000000 --- a/Deepgram/Models/Analyze/v1/NoopSchema.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2021-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 - -namespace Deepgram.Models.Analyze.v1; - -public class NoopSchema -{ -} - diff --git a/Deepgram/Models/Live/v1/CloseResponse.cs b/Deepgram/Models/Live/v1/CloseResponse.cs new file mode 100644 index 00000000..50fe8367 --- /dev/null +++ b/Deepgram/Models/Live/v1/CloseResponse.cs @@ -0,0 +1,15 @@ +// 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 + +namespace Deepgram.Models.Live.v1; + +public record CloseResponse +{ + /// + /// TODO + /// + [JsonPropertyName("type")] + [JsonConverter(typeof(JsonStringEnumConverter))] + public LiveType? Type { get; set; } = LiveType.Close; +} diff --git a/Deepgram/Models/Live/v1/ErrorResponse.cs b/Deepgram/Models/Live/v1/ErrorResponse.cs new file mode 100644 index 00000000..ee830d59 --- /dev/null +++ b/Deepgram/Models/Live/v1/ErrorResponse.cs @@ -0,0 +1,33 @@ +// 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 + +namespace Deepgram.Models.Live.v1; + +public record ErrorResponse +{ + /// + /// Error Description + /// + [JsonPropertyName("description")] + public string? Description { get; set; } = ""; + + /// + /// Error Message + /// + [JsonPropertyName("message")] + public string? Message { get; set; } = ""; + + /// + /// Error Variant + /// + [JsonPropertyName("variant")] + public string? Variant { get; set; } = ""; + + /// + /// TODO + /// + [JsonPropertyName("type")] + [JsonConverter(typeof(JsonStringEnumConverter))] + public LiveType? Type { get; set; } = LiveType.Error; +} diff --git a/Deepgram/Models/Live/v1/EventResponse.cs b/Deepgram/Models/Live/v1/EventResponse.cs deleted file mode 100644 index 3a3d56c5..00000000 --- a/Deepgram/Models/Live/v1/EventResponse.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2021-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 - -namespace Deepgram.Models.Live.v1; - -public class EventResponse -{ - /// - /// MetaData response from the live transcription service - /// - public MetadataResponse? MetaData { get; set; } - - /// - /// Transcription response from the live transcription service - /// - public TranscriptionResponse? Transcription { get; set; } - - /// - /// UtterancEnd response from the live transcription service - /// - public UtteranceEndResponse? UtteranceEnd { get; set; } - - /// - /// UtterancEnd response from the live transcription service - /// - public SpeechStartedResponse? SpeechStarted { get; set; } - - /// - /// Error response from the live transcription service - /// - public Exception? Error { get; set; } -} diff --git a/Deepgram/Models/Live/v1/LiveType.cs b/Deepgram/Models/Live/v1/LiveType.cs index f02f1792..e64d2eb9 100644 --- a/Deepgram/Models/Live/v1/LiveType.cs +++ b/Deepgram/Models/Live/v1/LiveType.cs @@ -6,8 +6,12 @@ namespace Deepgram.Models.Live.v1; public enum LiveType { + Open, Metadata, Results, UtteranceEnd, SpeechStarted, + Close, + Unhandled, + Error, } diff --git a/Deepgram/Models/Live/v1/OpenResponse.cs b/Deepgram/Models/Live/v1/OpenResponse.cs new file mode 100644 index 00000000..ca171ed4 --- /dev/null +++ b/Deepgram/Models/Live/v1/OpenResponse.cs @@ -0,0 +1,15 @@ +// 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 + +namespace Deepgram.Models.Live.v1; + +public record OpenResponse +{ + /// + /// TODO + /// + [JsonPropertyName("type")] + [JsonConverter(typeof(JsonStringEnumConverter))] + public LiveType? Type { get; set; } = LiveType.Open; +} diff --git a/Deepgram/Models/Live/v1/TranscriptionResponse.cs b/Deepgram/Models/Live/v1/ResultResponse.cs similarity index 97% rename from Deepgram/Models/Live/v1/TranscriptionResponse.cs rename to Deepgram/Models/Live/v1/ResultResponse.cs index 6e46adf9..6a8757d7 100644 --- a/Deepgram/Models/Live/v1/TranscriptionResponse.cs +++ b/Deepgram/Models/Live/v1/ResultResponse.cs @@ -3,7 +3,7 @@ // SPDX-License-Identifier: MIT namespace Deepgram.Models.Live.v1; -public record TranscriptionResponse +public record ResultResponse { /// /// TODO diff --git a/Deepgram/Models/Live/v1/UnhandledResponse.cs b/Deepgram/Models/Live/v1/UnhandledResponse.cs new file mode 100644 index 00000000..543cf466 --- /dev/null +++ b/Deepgram/Models/Live/v1/UnhandledResponse.cs @@ -0,0 +1,21 @@ +// 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 + +namespace Deepgram.Models.Live.v1; + +public record UnhandledResponse +{ + /// + /// Raw JSON + /// + [JsonPropertyName("raw")] + public string? Raw { get; set; } = ""; + + /// + /// TODO + /// + [JsonPropertyName("type")] + [JsonConverter(typeof(JsonStringEnumConverter))] + public LiveType? Type { get; set; } = LiveType.Unhandled; +} diff --git a/Deepgram/Models/Manage/v1/NoopSchema.cs b/Deepgram/Models/Manage/v1/NoopSchema.cs deleted file mode 100644 index c9867f4d..00000000 --- a/Deepgram/Models/Manage/v1/NoopSchema.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2021-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 - -namespace Deepgram.Models.Manage.v1; - -public class NoopSchema -{ -} - diff --git a/Deepgram/Models/OnPrem/v1/NoopSchema.cs b/Deepgram/Models/OnPrem/v1/NoopSchema.cs deleted file mode 100644 index 0b683a60..00000000 --- a/Deepgram/Models/OnPrem/v1/NoopSchema.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2021-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 - -namespace Deepgram.Models.OnPrem.v1; - -public class NoopSchema -{ -} - diff --git a/Deepgram/Models/PreRecorded/v1/NoopSchema.cs b/Deepgram/Models/PreRecorded/v1/NoopSchema.cs deleted file mode 100644 index 8c458fc3..00000000 --- a/Deepgram/Models/PreRecorded/v1/NoopSchema.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2021-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 - -namespace Deepgram.Models.PreRecorded.v1; - -public class NoopSchema -{ -} - diff --git a/Deepgram/Models/Speak/v1/NoopSchema.cs b/Deepgram/Models/Speak/v1/NoopSchema.cs deleted file mode 100644 index 6ea7e255..00000000 --- a/Deepgram/Models/Speak/v1/NoopSchema.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2021-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 - -namespace Deepgram.Models.Speak.v1; - -public class NoopSchema -{ -} - diff --git a/examples/streaming/file/Program.cs b/examples/streaming/file/Program.cs index 8bdccd25..cee9b468 100644 --- a/examples/streaming/file/Program.cs +++ b/examples/streaming/file/Program.cs @@ -17,36 +17,47 @@ static async Task Main(string[] args) var liveClient = new LiveClient(); // Subscribe to the EventResponseReceived event - liveClient.EventResponseReceived += (sender, e) => + liveClient._resultsReceived += (sender, e) => { - if (e.Response.Transcription != null) + if (e.Channel.Alternatives[0].Transcript == "") { - if (e.Response.Transcription.Channel.Alternatives[0].Transcript == "") - { - Console.WriteLine("Empty transcription received."); - return; - } - - // Console.WriteLine("Transcription received: " + JsonSerializer.Serialize(e.Response.Transcription)); - Console.WriteLine($"Speaker: {e.Response.Transcription.Channel.Alternatives[0].Transcript}"); - } - else if (e.Response.SpeechStarted != null) - { - Console.WriteLine("SpeechStarted received: " + JsonSerializer.Serialize(e.Response.SpeechStarted)); - } - else if (e.Response.UtteranceEnd != null) - { - Console.WriteLine("UtteranceEnd received: " + JsonSerializer.Serialize(e.Response.UtteranceEnd)); - } - else if (e.Response.MetaData != null) - { - Console.WriteLine("Metadata received: " + JsonSerializer.Serialize(e.Response.MetaData)); - } - else if (e.Response.Error != null) - { - Console.WriteLine("Error: " + JsonSerializer.Serialize(e.Response.Error.Message)); + Console.WriteLine("Empty transcription received."); + return; } + + // Console.WriteLine("Transcription received: " + JsonSerializer.Serialize(e.Response.Transcription)); + Console.WriteLine($"Speaker: {e.Channel.Alternatives[0].Transcript}"); }; + //liveClient.EventResponseReceived += (sender, e) => + //{ + // if (e.Response.Transcription != null) + // { + // if (e.Response.Transcription.Channel.Alternatives[0].Transcript == "") + // { + // Console.WriteLine("Empty transcription received."); + // return; + // } + + // // Console.WriteLine("Transcription received: " + JsonSerializer.Serialize(e.Response.Transcription)); + // Console.WriteLine($"Speaker: {e.Response.Transcription.Channel.Alternatives[0].Transcript}"); + // } + // else if (e.Response.SpeechStarted != null) + // { + // Console.WriteLine("SpeechStarted received: " + JsonSerializer.Serialize(e.Response.SpeechStarted)); + // } + // else if (e.Response.UtteranceEnd != null) + // { + // Console.WriteLine("UtteranceEnd received: " + JsonSerializer.Serialize(e.Response.UtteranceEnd)); + // } + // else if (e.Response.MetaData != null) + // { + // Console.WriteLine("Metadata received: " + JsonSerializer.Serialize(e.Response.MetaData)); + // } + // else if (e.Response.Error != null) + // { + // Console.WriteLine("Error: " + JsonSerializer.Serialize(e.Response.Error.Message)); + // } + //}; // Start the connection var liveSchema = new LiveSchema() diff --git a/examples/streaming/microphone/Program.cs b/examples/streaming/microphone/Program.cs index d23e9a51..d951997f 100644 --- a/examples/streaming/microphone/Program.cs +++ b/examples/streaming/microphone/Program.cs @@ -14,35 +14,16 @@ static async Task Main(string[] args) var liveClient = new LiveClient(); // Subscribe to the EventResponseReceived event - liveClient.EventResponseReceived += (sender, e) => + liveClient._resultsReceived += (sender, e) => { - if (e.Response.Transcription != null) + if (e.Channel.Alternatives[0].Transcript == "") { - if (e.Response.Transcription.Channel.Alternatives[0].Transcript == "") - { - Console.WriteLine("Empty transcription received."); - return; - } - - // Console.WriteLine("Transcription received: " + JsonSerializer.Serialize(e.Response.Transcription)); - Console.WriteLine($"Speaker: {e.Response.Transcription.Channel.Alternatives[0].Transcript}"); - } - else if (e.Response.SpeechStarted != null) - { - Console.WriteLine("SpeechStarted received: " + JsonSerializer.Serialize(e.Response.SpeechStarted)); - } - else if (e.Response.UtteranceEnd != null) - { - Console.WriteLine("UtteranceEnd received: " + JsonSerializer.Serialize(e.Response.UtteranceEnd)); - } - else if (e.Response.MetaData != null) - { - Console.WriteLine("Metadata received: " + JsonSerializer.Serialize(e.Response.MetaData)); - } - else if (e.Response.Error != null) - { - Console.WriteLine("Error: " + JsonSerializer.Serialize(e.Response.Error.Message)); + Console.WriteLine("Empty transcription received."); + return; } + + // Console.WriteLine("Transcription received: " + JsonSerializer.Serialize(e.Response.Transcription)); + Console.WriteLine($"Speaker: {e.Channel.Alternatives[0].Transcript}"); }; // Start the connection @@ -61,7 +42,9 @@ static async Task Main(string[] args) var microphone = new Microphone(liveClient.Send); microphone.Start(); - Thread.Sleep(3600000); + // Wait for the user to press a key + Console.WriteLine("Press any key to stop the microphone streaming..."); + Console.ReadKey(); // Stop the connection await liveClient.Stop();