Skip to content

Commit 849cbde

Browse files
committed
add audio tests
1 parent 30ea2d0 commit 849cbde

File tree

73 files changed

+4605
-242
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+4605
-242
lines changed

tests/Audio/GenerateSpeechTests.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
namespace OpenAI.Tests.Audio;
1111

12-
[Parallelizable(ParallelScope.All)]
1312
[Category("Audio")]
1413
public partial class GenerateSpeechTests : OpenAIRecordedTestBase
1514
{
@@ -20,12 +19,15 @@ public GenerateSpeechTests(bool isAsync) : base(isAsync)
2019
[Test]
2120
public async Task BasicTextToSpeechWorks()
2221
{
23-
AudioClient client = GetProxiedOpenAIClient<AudioClient>(TestScenario.Audio_TTS);
22+
using (Recording.DisableRequestBodyRecording()) // Temp while multipart support in the test proxy is being implemented
23+
{
24+
AudioClient client = GetProxiedOpenAIClient<AudioClient>(TestScenario.Audio_TTS);
2425

25-
BinaryData audio = await client.GenerateSpeechAsync("Hello, world! This is a test.", GeneratedSpeechVoice.Shimmer);
26+
BinaryData audio = await client.GenerateSpeechAsync("Hello, world! This is a test.", GeneratedSpeechVoice.Shimmer);
2627

27-
Assert.That(audio, Is.Not.Null);
28-
await ValidateGeneratedAudio(audio, "hello");
28+
Assert.That(audio, Is.Not.Null);
29+
await ValidateGeneratedAudio(audio, "hello");
30+
}
2931
}
3032

3133
[Test]

tests/Audio/TranscriptionTests.cs

Lines changed: 203 additions & 183 deletions
Large diffs are not rendered by default.

tests/Audio/TranslationTests.cs

Lines changed: 59 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@
99

1010
namespace OpenAI.Tests.Audio;
1111

12-
[Parallelizable(ParallelScope.All)]
1312
[Category("Audio")]
1413
public partial class TranslationTests : OpenAIRecordedTestBase
1514
{
16-
public TranslationTests(bool isAsync) : base(isAsync)
15+
public TranslationTests(bool isAsync) : base(isAsync, RecordedTestMode.Record)
1716
{
1817
}
1918

@@ -28,24 +27,27 @@ public enum AudioSourceKind
2827
[TestCase(AudioSourceKind.UsingFilePath)]
2928
public async Task TranslationWorks(AudioSourceKind audioSourceKind)
3029
{
31-
AudioClient client = GetProxiedOpenAIClient<AudioClient>(TestScenario.Audio_Whisper);
30+
using (Recording.DisableRequestBodyRecording()) // Temp while multipart support in the test proxy is being implemented
31+
{
32+
AudioClient client = GetProxiedOpenAIClient<AudioClient>(TestScenario.Audio_Whisper);
3233

33-
string filename = "audio_french.wav";
34-
string path = Path.Combine("Assets", filename);
35-
AudioTranslation translation = null;
34+
string filename = "audio_french.wav";
35+
string path = Path.Combine("Assets", filename);
36+
AudioTranslation translation = null;
3637

37-
if (audioSourceKind == AudioSourceKind.UsingStream)
38-
{
39-
using FileStream audio = File.OpenRead(path);
38+
if (audioSourceKind == AudioSourceKind.UsingStream)
39+
{
40+
using FileStream audio = File.OpenRead(path);
4041

41-
translation = await client.TranslateAudioAsync(audio, filename);
42-
}
43-
else if (audioSourceKind == AudioSourceKind.UsingFilePath)
44-
{
45-
translation = await client.TranslateAudioAsync(path);
42+
translation = await client.TranslateAudioAsync(audio, filename);
43+
}
44+
else if (audioSourceKind == AudioSourceKind.UsingFilePath)
45+
{
46+
translation = await client.TranslateAudioAsync(path);
47+
}
48+
Assert.That(translation?.Text, Is.Not.Null);
49+
Assert.That(translation.Text.ToLowerInvariant(), Contains.Substring("whisper"));
4650
}
47-
Assert.That(translation?.Text, Is.Not.Null);
48-
Assert.That(translation.Text.ToLowerInvariant(), Contains.Substring("whisper"));
4951
}
5052

5153
[Test]
@@ -57,55 +59,58 @@ public async Task TranslationWorks(AudioSourceKind audioSourceKind)
5759
[TestCase(null)]
5860
public async Task TranslationFormatsWork(string responseFormat)
5961
{
60-
AudioClient client = GetProxiedOpenAIClient<AudioClient>(TestScenario.Audio_Whisper);
61-
string path = Path.Combine("Assets", "audio_french.wav");
62-
63-
AudioTranslationOptions options = new()
62+
using (Recording.DisableRequestBodyRecording()) // Temp while multipart support in the test proxy is being implemented
6463
{
65-
ResponseFormat = responseFormat switch
66-
{
67-
"text" => AudioTranslationFormat.Text,
68-
"json" => AudioTranslationFormat.Simple,
69-
"verbose_json" => AudioTranslationFormat.Verbose,
70-
"srt" => AudioTranslationFormat.Srt,
71-
"vtt" => AudioTranslationFormat.Vtt,
72-
_ => (AudioTranslationFormat?)null
73-
}
74-
};
64+
AudioClient client = GetProxiedOpenAIClient<AudioClient>(TestScenario.Audio_Whisper);
65+
string path = Path.Combine("Assets", "audio_french.wav");
7566

76-
AudioTranslation translation = await client.TranslateAudioAsync(path, options);
67+
AudioTranslationOptions options = new()
68+
{
69+
ResponseFormat = responseFormat switch
70+
{
71+
"text" => AudioTranslationFormat.Text,
72+
"json" => AudioTranslationFormat.Simple,
73+
"verbose_json" => AudioTranslationFormat.Verbose,
74+
"srt" => AudioTranslationFormat.Srt,
75+
"vtt" => AudioTranslationFormat.Vtt,
76+
_ => (AudioTranslationFormat?)null
77+
}
78+
};
7779

78-
Assert.That(translation?.Text?.ToLowerInvariant(), Does.Contain("recognition"));
80+
AudioTranslation translation = await client.TranslateAudioAsync(path, options);
7981

80-
if (options.ResponseFormat == AudioTranslationFormat.Verbose)
81-
{
82-
Assert.That(translation.Language, Is.EqualTo("english"));
83-
Assert.That(translation.Duration, Is.GreaterThan(TimeSpan.Zero));
84-
Assert.That(translation.Segments, Is.Not.Empty);
82+
Assert.That(translation?.Text?.ToLowerInvariant(), Does.Contain("recognition"));
8583

86-
for (int i = 0; i < translation.Segments.Count; i++)
84+
if (options.ResponseFormat == AudioTranslationFormat.Verbose)
8785
{
88-
TranscribedSegment segment = translation.Segments[i];
86+
Assert.That(translation.Language, Is.EqualTo("english"));
87+
Assert.That(translation.Duration, Is.GreaterThan(TimeSpan.Zero));
88+
Assert.That(translation.Segments, Is.Not.Empty);
8989

90-
if (i > 0)
90+
for (int i = 0; i < translation.Segments.Count; i++)
9191
{
92-
Assert.That(segment.StartTime, Is.GreaterThanOrEqualTo(translation.Segments[i - 1].EndTime));
93-
}
92+
TranscribedSegment segment = translation.Segments[i];
93+
94+
if (i > 0)
95+
{
96+
Assert.That(segment.StartTime, Is.GreaterThanOrEqualTo(translation.Segments[i - 1].EndTime));
97+
}
9498

95-
Assert.That(segment.Id, Is.EqualTo(i));
96-
Assert.That(segment.EndTime, Is.GreaterThanOrEqualTo(segment.StartTime));
97-
Assert.That(segment.TokenIds.Span.Length, Is.GreaterThan(0));
99+
Assert.That(segment.Id, Is.EqualTo(i));
100+
Assert.That(segment.EndTime, Is.GreaterThanOrEqualTo(segment.StartTime));
101+
Assert.That(segment.TokenIds.Span.Length, Is.GreaterThan(0));
98102

99-
Assert.That(segment.AverageLogProbability, Is.LessThan(-0.001f).Or.GreaterThan(0.001f));
100-
Assert.That(segment.CompressionRatio, Is.LessThan(-0.001f).Or.GreaterThan(0.001f));
101-
Assert.That(segment.NoSpeechProbability, Is.LessThan(-0.001f).Or.GreaterThan(0.001f));
103+
Assert.That(segment.AverageLogProbability, Is.LessThan(-0.001f).Or.GreaterThan(0.001f));
104+
Assert.That(segment.CompressionRatio, Is.LessThan(-0.001f).Or.GreaterThan(0.001f));
105+
Assert.That(segment.NoSpeechProbability, Is.LessThan(-0.001f).Or.GreaterThan(0.001f));
106+
}
107+
}
108+
else
109+
{
110+
Assert.That(translation.Duration, Is.Null);
111+
Assert.That(translation.Language, Is.Null);
112+
Assert.That(translation.Segments, Is.Not.Null.And.Empty);
102113
}
103-
}
104-
else
105-
{
106-
Assert.That(translation.Duration, Is.Null);
107-
Assert.That(translation.Language, Is.Null);
108-
Assert.That(translation.Segments, Is.Not.Null.And.Empty);
109114
}
110115
}
111116
}

tests/SessionRecords/GenerateSpeechTests/BasicTextToSpeechWorks.json

Lines changed: 91 additions & 0 deletions
Large diffs are not rendered by default.

tests/SessionRecords/GenerateSpeechTests/BasicTextToSpeechWorksAsync.json

Lines changed: 87 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"Entries": [
3+
{
4+
"RequestUri": "https://api.openai.com/v1/audio/speech",
5+
"RequestMethod": "POST",
6+
"RequestHeaders": {
7+
"Accept": "application/octet-stream",
8+
"Authorization": "Sanitized",
9+
"Content-Length": "81",
10+
"Content-Type": "application/json",
11+
"User-Agent": "OpenAI/2.4.0 (.NET 9.0.9; Microsoft Windows 10.0.26100)"
12+
},
13+
"RequestBody": {
14+
"model": "tts-1",
15+
"input": "Hello, world!",
16+
"voice": "alloy",
17+
"response_format": "aac"
18+
},
19+
"StatusCode": 200,
20+
"ResponseHeaders": {
21+
"Access-Control-Expose-Headers": "X-Request-ID",
22+
"Alt-Svc": "h3=\":443\"",
23+
"cf-cache-status": "DYNAMIC",
24+
"CF-RAY": "9801df296c08ebaf-SEA",
25+
"Connection": "keep-alive",
26+
"Content-Type": "audio/aac",
27+
"Date": "Tue, 16 Sep 2025 16:52:00 GMT",
28+
"openai-organization": "Sanitized",
29+
"openai-processing-ms": "460",
30+
"openai-project": "Sanitized",
31+
"openai-version": "2020-10-01",
32+
"Server": "cloudflare",
33+
"Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload",
34+
"Transfer-Encoding": "chunked",
35+
"Via": "envoy-router-787f7fc76c-nv5p2",
36+
"X-Content-Type-Options": "nosniff",
37+
"x-envoy-upstream-service-time": "556",
38+
"x-openai-proxy-wasm": "v0.1",
39+
"x-ratelimit-limit-requests": "10000",
40+
"x-ratelimit-remaining-requests": "9999",
41+
"x-ratelimit-reset-requests": "6ms",
42+
"X-Request-ID": "Sanitized"
43+
},
44+
"ResponseBody": "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"
45+
}
46+
],
47+
"Variables": {}
48+
}

0 commit comments

Comments
 (0)