diff --git a/global.json b/global.json index 7eb9bc5b..67db0e87 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.100", + //"version": "8.0.100", "rollForward": "feature" } } \ No newline at end of file diff --git a/src/Custom/Audio/AudioClient.cs b/src/Custom/Audio/AudioClient.cs index 9a224768..61fecb98 100644 --- a/src/Custom/Audio/AudioClient.cs +++ b/src/Custom/Audio/AudioClient.cs @@ -1,7 +1,10 @@ using System; +using System.Buffers; using System.ClientModel; using System.ClientModel.Primitives; +using System.Collections.Generic; using System.IO; +using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; @@ -108,9 +111,47 @@ public virtual async Task> GenerateSpeechAsync(string t using BinaryContent content = options; ClientResult result = await GenerateSpeechAsync(content, cancellationToken.ToRequestOptions()).ConfigureAwait(false); + await result.GetRawResponse().BufferContentAsync(cancellationToken).ConfigureAwait(false); return ClientResult.FromValue(result.GetRawResponse().Content, result.GetRawResponse()); } + /// Generates a life-like, spoken audio recording of the input text. + /// + /// The default format of the generated audio is unless otherwise specified + /// via . + /// + /// The text to generate audio for. + /// The voice to use in the generated audio. + /// The options to configure the audio generation. + /// A token that can be used to cancel this method call. + /// is null. + /// Streaming chunks of the generated audio in the specified output format. + public virtual async IAsyncEnumerable GenerateSpeechStreamingAsync(string text, GeneratedSpeechVoice voice, SpeechGenerationOptions options = null, [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + Argument.AssertNotNull(text, nameof(text)); + + options ??= new(); + CreateSpeechGenerationOptions(text, voice, ref options); + + using BinaryContent content = options; + ClientResult result = await GenerateSpeechAsync(content, cancellationToken.ToRequestOptions()).ConfigureAwait(false); + var stream = result.GetRawResponse().ContentStream; + + var buffer = ArrayPool.Shared.Rent(1024 * 16); + try + { + int bytesRead; + while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0) + { + yield return BinaryData.FromBytes(buffer.AsMemory(0, bytesRead)); + } + } + finally + { + ArrayPool.Shared.Return(buffer); + } + } + /// Generates a life-like, spoken audio recording of the input text. /// /// The default format of the generated audio is unless otherwise specified @@ -130,7 +171,8 @@ public virtual ClientResult GenerateSpeech(string text, GeneratedSpe CreateSpeechGenerationOptions(text, voice, ref options); using BinaryContent content = options; - ClientResult result = GenerateSpeech(content, cancellationToken.ToRequestOptions()); ; + ClientResult result = GenerateSpeech(content, cancellationToken.ToRequestOptions()); + result.GetRawResponse().BufferContent(cancellationToken); return ClientResult.FromValue(result.GetRawResponse().Content, result.GetRawResponse()); } diff --git a/src/Custom/Audio/SpeechGenerationOptions.cs b/src/Custom/Audio/SpeechGenerationOptions.cs index 40985190..ec9ebf27 100644 --- a/src/Custom/Audio/SpeechGenerationOptions.cs +++ b/src/Custom/Audio/SpeechGenerationOptions.cs @@ -37,4 +37,11 @@ public SpeechGenerationOptions() [CodeGenMember("Speed")] public float? SpeedRatio { get; set; } + + // CUSTOM: + /// + /// Control the voice of your generated audio with additional instructions. Does not work with tts-1 or tts-1-hd. + /// + [CodeGenMember("Instructions")] + public string Instructions { get; set; } } \ No newline at end of file diff --git a/src/Generated/AudioClient.RestClient.cs b/src/Generated/AudioClient.RestClient.cs index 719788ac..c018c3fb 100644 --- a/src/Generated/AudioClient.RestClient.cs +++ b/src/Generated/AudioClient.RestClient.cs @@ -18,6 +18,7 @@ internal virtual PipelineMessage CreateCreateSpeechRequest(BinaryContent content { PipelineMessage message = Pipeline.CreateMessage(); message.ResponseClassifier = PipelineMessageClassifier200; + message.BufferResponse = false; PipelineRequest request = message.Request; request.Method = "POST"; ClientUriBuilder uri = new ClientUriBuilder(); diff --git a/src/Generated/Models/SpeechGenerationOptions.Serialization.cs b/src/Generated/Models/SpeechGenerationOptions.Serialization.cs index 2b21d919..c8100088 100644 --- a/src/Generated/Models/SpeechGenerationOptions.Serialization.cs +++ b/src/Generated/Models/SpeechGenerationOptions.Serialization.cs @@ -52,6 +52,11 @@ protected virtual void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWrit writer.WritePropertyName("speed"u8); writer.WriteNumberValue(SpeedRatio.Value); } + if (Optional.IsDefined(Instructions) && _additionalBinaryDataProperties?.ContainsKey("instructions") != true) + { + writer.WritePropertyName("instructions"u8); + writer.WriteStringValue(Instructions); + } if (_additionalBinaryDataProperties != null) { foreach (var item in _additionalBinaryDataProperties) @@ -97,6 +102,7 @@ internal static SpeechGenerationOptions DeserializeSpeechGenerationOptions(JsonE string input = default; GeneratedSpeechVoice voice = default; float? speedRatio = default; + string instructions = default; IDictionary additionalBinaryDataProperties = new ChangeTrackingDictionary(); foreach (var prop in element.EnumerateObject()) { @@ -133,6 +139,11 @@ internal static SpeechGenerationOptions DeserializeSpeechGenerationOptions(JsonE speedRatio = prop.Value.GetSingle(); continue; } + if (prop.NameEquals("instructions"u8)) + { + instructions = prop.Value.GetString(); + continue; + } additionalBinaryDataProperties.Add(prop.Name, BinaryData.FromString(prop.Value.GetRawText())); } return new SpeechGenerationOptions( @@ -141,6 +152,7 @@ internal static SpeechGenerationOptions DeserializeSpeechGenerationOptions(JsonE input, voice, speedRatio, + instructions, additionalBinaryDataProperties); } diff --git a/src/Generated/Models/SpeechGenerationOptions.cs b/src/Generated/Models/SpeechGenerationOptions.cs index e48d5cf0..e140c489 100644 --- a/src/Generated/Models/SpeechGenerationOptions.cs +++ b/src/Generated/Models/SpeechGenerationOptions.cs @@ -11,13 +11,14 @@ public partial class SpeechGenerationOptions { private protected IDictionary _additionalBinaryDataProperties; - internal SpeechGenerationOptions(GeneratedSpeechFormat? responseFormat, InternalCreateSpeechRequestModel model, string input, GeneratedSpeechVoice voice, float? speedRatio, IDictionary additionalBinaryDataProperties) + internal SpeechGenerationOptions(GeneratedSpeechFormat? responseFormat, InternalCreateSpeechRequestModel model, string input, GeneratedSpeechVoice voice, float? speedRatio, string instructions, IDictionary additionalBinaryDataProperties) { ResponseFormat = responseFormat; Model = model; Input = input; Voice = voice; SpeedRatio = speedRatio; + Instructions = instructions; _additionalBinaryDataProperties = additionalBinaryDataProperties; } diff --git a/src/OpenAI.csproj b/src/OpenAI.csproj index ce4029cd..e6667f13 100644 --- a/src/OpenAI.csproj +++ b/src/OpenAI.csproj @@ -11,7 +11,7 @@ 2.2.0 beta.4 - net8.0;net6.0;netstandard2.0 + net9.0;net8.0;net6.0;netstandard2.0 latest