Skip to content

Auto-detect audio format in OpenAISpeechToTextClient - #7575

Merged
jozkee merged 2 commits into
mainfrom
issue-7543
Jun 18, 2026
Merged

jozkee merged 2 commits into
mainfrom
issue-7543

Conversation

@jozkee

@jozkee jozkee commented Jun 16, 2026 •

Copy link
Copy Markdown
Member

When the audio stream is not a FileStream, the client now peeks at the leading bytes to detect the format (wav, webm, m4a, mp3) and sets the multipart filename accordingly. This fixes HTTP 400 errors when sending non-MP3 audio (e.g. WAV) in a MemoryStream, since the OpenAI API uses the file extension to determine the audio format.

  • Add DetectAudioExtension using Span.SequenceEqual for readability
  • Add integration tests for all OpenAI-supported formats (mp3, wav, m4a, webm)
  • Add unit tests covering each magic-byte detection branch
  • Add ExpectedAudioFilename assertion to VerbatimMultiPartHttpHandler

Fixes #7543

Microsoft Reviewers: Open in CodeFlow

โ€ฆ#7543)

When the audio stream is not a FileStream, the client now peeks at the
leading bytes to detect the format (wav, webm, m4a, mp3) and sets the
multipart filename accordingly. This fixes HTTP 400 errors when sending
non-MP3 audio (e.g. WAV) in a MemoryStream, since the OpenAI API uses
the file extension to determine the audio format.

- Add DetectAudioExtension using Span.SequenceEqual for readability
- Add integration tests for all OpenAI-supported formats (mp3, wav, m4a, webm)
- Add unit tests covering each magic-byte detection branch
- Add ExpectedAudioFilename assertion to VerbatimMultiPartHttpHandler

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jozkee
jozkee requested a review from rogerbarreto June 16, 2026 21:46
@jozkee jozkee self-assigned this Jun 16, 2026
@jozkee
jozkee requested a review from a team as a code owner June 16, 2026 21:46
Copilot AI review requested due to automatic review settings June 16, 2026 21:46
@jozkee jozkee added the area-ai Microsoft.Extensions.AI libraries label Jun 16, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates OpenAISpeechToTextClient to auto-detect audio format (wav/webm/m4a/mp3) from leading โ€œmagic bytesโ€ when the provided audio stream is not a FileStream, and uses the detected extension in the multipart filename so OpenAI can correctly infer the format (fixing 400s for non-MP3 MemoryStream inputs).

Changes:

  • Add stream-header โ€œmagic byteโ€ detection and filename resolution logic in OpenAISpeechToTextClient.
  • Add unit tests validating filename selection for each supported format and branch.
  • Add integration coverage for multiple embedded audio formats and enhance multipart handler assertions to validate the uploaded filename.

Reviewed changes

Copilot reviewed 5 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAISpeechToTextClient.cs Adds filename resolution with magic-byte detection for non-FileStream inputs.
test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAISpeechToTextClientTests.cs Adds theory-based unit tests asserting detected multipart filenames for different headers.
test/Libraries/Microsoft.Extensions.AI.Integration.Tests/VerbatimMultiPartHttpHandler.cs Adds optional filename assertion for multipart โ€œfileโ€ fields.
test/Libraries/Microsoft.Extensions.AI.Integration.Tests/SpeechToTextClientIntegrationTests.cs Adds integration test that exercises auto-detection across multiple audio formats.
test/Libraries/Microsoft.Extensions.AI.Integration.Tests/Microsoft.Extensions.AI.Integration.Tests.csproj Embeds additional audio resource files used by the new integration test.
Comments suppressed due to low confidence (1)

src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAISpeechToTextClient.cs:121

  • In GetStreamingTextAsync, ResolveFilename(audioSpeechStream) is executed unconditionally even for translation requests, but the translation branch immediately delegates to GetTextAsync(...) (which resolves the filename again). With the new magic-byte peek, this results in redundant header reads/rewinds for translation streaming.
        _ = Throw.IfNull(audioSpeechStream);

        string filename = ResolveFilename(audioSpeechStream);

        if (IsTranslationRequest(options))
        {
            foreach (var update in (await GetTextAsync(audioSpeechStream, options, cancellationToken).ConfigureAwait(false)).ToSpeechToTextResponseUpdates())

@dotnet-comment-bot

Copy link
Copy Markdown
Collaborator

โ€ผ๏ธ Found issues โ€ผ๏ธ

Project Coverage Type Expected Actual
Microsoft.Extensions.Diagnostics.Testing Line 99 98.65 ๐Ÿ”ป
Microsoft.Extensions.Telemetry Line 93 91.95 ๐Ÿ”ป
Microsoft.Extensions.AI Line 89 88.53 ๐Ÿ”ป
Microsoft.Extensions.AI Branch 89 88.57 ๐Ÿ”ป
Microsoft.Extensions.AI.OpenAI Line 75 62.86 ๐Ÿ”ป
Microsoft.Extensions.AI.OpenAI Branch 75 50.31 ๐Ÿ”ป
Microsoft.Extensions.DataIngestion.MarkItDown Line 75 4.46 ๐Ÿ”ป
Microsoft.Extensions.DataIngestion.MarkItDown Branch 75 0 ๐Ÿ”ป
Microsoft.Extensions.Diagnostics.ResourceMonitoring Line 99 96.03 ๐Ÿ”ป
Microsoft.Extensions.Diagnostics.ResourceMonitoring Branch 99 94.39 ๐Ÿ”ป
Microsoft.Extensions.Diagnostics.ResourceMonitoring.Kubernetes Line 99 97.73 ๐Ÿ”ป
Microsoft.Extensions.ServiceDiscovery.Dns Line 75 69.93 ๐Ÿ”ป
Microsoft.Extensions.ServiceDiscovery.Abstractions Line 75 42.11 ๐Ÿ”ป
Microsoft.Extensions.ServiceDiscovery.Abstractions Branch 75 42.86 ๐Ÿ”ป
Microsoft.Extensions.ServiceDiscovery Line 75 67.81 ๐Ÿ”ป
Microsoft.Extensions.ServiceDiscovery Branch 75 71.43 ๐Ÿ”ป
Microsoft.Extensions.ServiceDiscovery.Yarp Line 75 73.85 ๐Ÿ”ป
Microsoft.Extensions.ServiceDiscovery.Yarp Branch 75 70 ๐Ÿ”ป
Microsoft.Extensions.VectorData.Abstractions Line 75 37.39 ๐Ÿ”ป
Microsoft.Extensions.VectorData.Abstractions Branch 75 22.73 ๐Ÿ”ป

๐ŸŽ‰ Good job! The coverage increased ๐ŸŽ‰
Update MinCodeCoverage in the project files.

Project Expected Actual
Microsoft.Gen.BuildMetadata 97 100
Microsoft.Gen.MetadataExtractor 57 73
Microsoft.Gen.MetricsReports 67 69
Microsoft.Extensions.AI.Abstractions 82 85
Microsoft.Extensions.AI.Evaluation.NLP 0 78
Microsoft.Extensions.Caching.Hybrid 82 89
Microsoft.Extensions.DataIngestion 75 89
Microsoft.Extensions.DataIngestion.Markdig 75 90
Microsoft.Extensions.Http.Resilience 97 100

Full code coverage report: https://dev.azure.com/dnceng-public/public/_build/results?buildId=1467244&view=codecoverage-tab

@dotnet-comment-bot

Copy link
Copy Markdown
Collaborator

โ€ผ๏ธ Found issues โ€ผ๏ธ

Project Coverage Type Expected Actual
Microsoft.Extensions.Diagnostics.Testing Line 99 98.65 ๐Ÿ”ป
Microsoft.Extensions.Telemetry Line 93 91.95 ๐Ÿ”ป
Microsoft.Extensions.AI Line 89 88.61 ๐Ÿ”ป
Microsoft.Extensions.AI Branch 89 88.57 ๐Ÿ”ป
Microsoft.Extensions.AI.OpenAI Line 75 62.89 ๐Ÿ”ป
Microsoft.Extensions.AI.OpenAI Branch 75 50.41 ๐Ÿ”ป
Microsoft.Extensions.DataIngestion.MarkItDown Line 75 4.46 ๐Ÿ”ป
Microsoft.Extensions.DataIngestion.MarkItDown Branch 75 0 ๐Ÿ”ป
Microsoft.Extensions.Diagnostics.ResourceMonitoring Line 99 96.03 ๐Ÿ”ป
Microsoft.Extensions.Diagnostics.ResourceMonitoring Branch 99 94.39 ๐Ÿ”ป
Microsoft.Extensions.Diagnostics.ResourceMonitoring.Kubernetes Line 99 97.73 ๐Ÿ”ป
Microsoft.Extensions.ServiceDiscovery.Dns Line 75 71.61 ๐Ÿ”ป
Microsoft.Extensions.ServiceDiscovery.Abstractions Line 75 42.11 ๐Ÿ”ป
Microsoft.Extensions.ServiceDiscovery.Abstractions Branch 75 42.86 ๐Ÿ”ป
Microsoft.Extensions.ServiceDiscovery Line 75 67.21 ๐Ÿ”ป
Microsoft.Extensions.ServiceDiscovery Branch 75 71.43 ๐Ÿ”ป
Microsoft.Extensions.ServiceDiscovery.Yarp Line 75 73.85 ๐Ÿ”ป
Microsoft.Extensions.ServiceDiscovery.Yarp Branch 75 70 ๐Ÿ”ป
Microsoft.Extensions.VectorData.Abstractions Line 75 37.39 ๐Ÿ”ป
Microsoft.Extensions.VectorData.Abstractions Branch 75 22.73 ๐Ÿ”ป

๐ŸŽ‰ Good job! The coverage increased ๐ŸŽ‰
Update MinCodeCoverage in the project files.

Project Expected Actual
Microsoft.Gen.BuildMetadata 97 100
Microsoft.Gen.MetadataExtractor 57 73
Microsoft.Gen.MetricsReports 67 69
Microsoft.Extensions.AI.Abstractions 82 85
Microsoft.Extensions.AI.Evaluation.NLP 0 78
Microsoft.Extensions.Caching.Hybrid 82 89
Microsoft.Extensions.DataIngestion 75 89
Microsoft.Extensions.DataIngestion.Markdig 75 90
Microsoft.Extensions.Http.Resilience 97 100

Full code coverage report: https://dev.azure.com/dnceng-public/public/_build/results?buildId=1471017&view=codecoverage-tab

@jozkee
jozkee merged commit 2e53716 into main Jun 18, 2026
6 checks passed
@jozkee
jozkee deleted the issue-7543 branch June 18, 2026 16:36
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 19, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-ai Microsoft.Extensions.AI libraries

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ISpeechToTextClient does not allow to specify the audio FileName

5 participants