From 478139ef79692ca21409090f79779aa8fb3ecf3e Mon Sep 17 00:00:00 2001 From: Sandro Hanea Date: Thu, 10 Apr 2025 18:20:35 +0200 Subject: [PATCH 1/7] Fixed netstandard2 nullable waning on language for CI + other small (style) warnings --- .../SpeechToTextClient/SpeechToTextOptionsExtensions.cs | 2 +- Whisper.net/Wave/WaveParser.cs | 3 ++- Whisper.net/WhisperFactoryOptions.cs | 2 +- .../SpeechToText/SpeechToTextOptionsExtensionsTests.cs | 4 ++-- .../WhisperSpeechToTextClientConstructorTests.cs | 6 +++--- .../SpeechToText/WhisperSpeechToTextClientTest.cs | 6 +++--- 6 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Whisper.net/SpeechToTextClient/SpeechToTextOptionsExtensions.cs b/Whisper.net/SpeechToTextClient/SpeechToTextOptionsExtensions.cs index 29e3ab808..8cf53de29 100644 --- a/Whisper.net/SpeechToTextClient/SpeechToTextOptionsExtensions.cs +++ b/Whisper.net/SpeechToTextClient/SpeechToTextOptionsExtensions.cs @@ -652,7 +652,7 @@ internal static WhisperProcessor BuildWhisperProcessor(this SpeechToTextOptions? if (GetAdditionalProperty(LanguageKey, options!, out var language) && !string.IsNullOrEmpty(language)) { - processorBuilder.WithLanguage(language); + processorBuilder.WithLanguage(language!); } if (GetAdditionalProperty(LanguageDetectionKey, options!, out var languageDetection) && languageDetection) diff --git a/Whisper.net/Wave/WaveParser.cs b/Whisper.net/Wave/WaveParser.cs index a3c52137f..1ce9ee9ac 100644 --- a/Whisper.net/Wave/WaveParser.cs +++ b/Whisper.net/Wave/WaveParser.cs @@ -252,7 +252,8 @@ private async IAsyncEnumerable InternalReadSamples(bool useAsync, [Enume yield return currentSamples; sampleIndex++; } - }; + } + if (sampleIndex < SamplesCount) { throw new CorruptedWaveException("Invalid wave file, the size is too small and couldn't read all the samples."); diff --git a/Whisper.net/WhisperFactoryOptions.cs b/Whisper.net/WhisperFactoryOptions.cs index dbd7e7216..b58015436 100644 --- a/Whisper.net/WhisperFactoryOptions.cs +++ b/Whisper.net/WhisperFactoryOptions.cs @@ -4,7 +4,7 @@ namespace Whisper.net; public struct WhisperFactoryOptions { - public static WhisperFactoryOptions Default => new WhisperFactoryOptions(); + public static WhisperFactoryOptions Default => new(); public WhisperFactoryOptions() { diff --git a/tests/Whisper.net.Tests/SpeechToText/SpeechToTextOptionsExtensionsTests.cs b/tests/Whisper.net.Tests/SpeechToText/SpeechToTextOptionsExtensionsTests.cs index 05bd05d8f..89a11afb6 100644 --- a/tests/Whisper.net.Tests/SpeechToText/SpeechToTextOptionsExtensionsTests.cs +++ b/tests/Whisper.net.Tests/SpeechToText/SpeechToTextOptionsExtensionsTests.cs @@ -5,7 +5,7 @@ #pragma warning disable MEAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. -namespace Whisper.net.Tests; +namespace Whisper.net.Tests.SpeechToText; public class SpeechToTextOptionsExtensionsTests { @@ -746,7 +746,7 @@ public void WithTokenTimestampsThreshold_SetsAdditionalProperty() // Helper class for testing private class TestStringPool : IStringPool { - public string? GetStringUtf8(IntPtr nativeUtf8) + public string? GetStringUtf8(IntPtr nativeUtf8) { return null; } diff --git a/tests/Whisper.net.Tests/SpeechToText/WhisperSpeechToTextClientConstructorTests.cs b/tests/Whisper.net.Tests/SpeechToText/WhisperSpeechToTextClientConstructorTests.cs index 1d3939265..7686d727d 100644 --- a/tests/Whisper.net.Tests/SpeechToText/WhisperSpeechToTextClientConstructorTests.cs +++ b/tests/Whisper.net.Tests/SpeechToText/WhisperSpeechToTextClientConstructorTests.cs @@ -6,7 +6,7 @@ #pragma warning disable MEAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. -namespace Whisper.net.Tests; +namespace Whisper.net.Tests.SpeechToText; public class WhisperSpeechToTextClientConstructorTests : IClassFixture { @@ -32,7 +32,7 @@ public void Constructor_WithModelFileName_ShouldNotCreateFactoryImmediately() public void Constructor_WithFactoryBuilder_ShouldNotCreateFactoryImmediately() { // Arrange - bool factoryBuilderCalled = false; + var factoryBuilderCalled = false; WhisperFactory FactoryBuilder() { factoryBuilderCalled = true; @@ -116,7 +116,7 @@ WhisperFactory FactoryBuilder() public async Task MultipleRequests_ShouldReuseFactory() { // Arrange - int factoryBuilderCallCount = 0; + var factoryBuilderCallCount = 0; WhisperFactory FactoryBuilder() { factoryBuilderCallCount++; diff --git a/tests/Whisper.net.Tests/SpeechToText/WhisperSpeechToTextClientTest.cs b/tests/Whisper.net.Tests/SpeechToText/WhisperSpeechToTextClientTest.cs index 3ea9bcb81..2f8aab69a 100644 --- a/tests/Whisper.net.Tests/SpeechToText/WhisperSpeechToTextClientTest.cs +++ b/tests/Whisper.net.Tests/SpeechToText/WhisperSpeechToTextClientTest.cs @@ -6,7 +6,7 @@ #pragma warning disable MEAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. -namespace Whisper.net.Tests; +namespace Whisper.net.Tests.SpeechToText; public partial class WhisperSpeechToTextClientTest(TinyModelFixture model) : IClassFixture { [Fact] @@ -183,13 +183,13 @@ public async Task GetTextAsync_CalledMultipleTimes_Serially_WillCompleteEverytim using var fileReader3 = await TestDataProvider.OpenFileStreamAsync("kennedy.wav"); var result3 = await client.GetTextAsync(fileReader3, options); var segments3 = Assert.IsAssignableFrom>(result3.RawRepresentation); - + Assert.True(segments1.SequenceEqual(segments2, new SegmentDataComparer())); Assert.True(segments2.SequenceEqual(segments3, new SegmentDataComparer())); } - private class UpdateDataComparer : IEqualityComparer + private class UpdateDataComparer : IEqualityComparer { public bool Equals(SpeechToTextResponseUpdate? xUpdate, SpeechToTextResponseUpdate? yUpdate) { From 62e0100b8e836e8f08213263f14eb81681fe3402 Mon Sep 17 00:00:00 2001 From: Sandro Hanea Date: Thu, 10 Apr 2025 18:36:43 +0200 Subject: [PATCH 2/7] Removed `github.head_ref` as it was breaking CI from forks --- .github/workflows/android-native-build.yml | 1 - .github/workflows/linux-cuda-native-build.yml | 1 - .github/workflows/linux-native-build.yml | 1 - .github/workflows/linux-noavx-native-build.yml | 1 - .github/workflows/linux-openvino-native-build.yml | 1 - .github/workflows/linux-vulkan-native-build.yml | 1 - .github/workflows/macos-coreml-native-build.yml | 2 -- .github/workflows/macos-native-build.yml | 2 -- .github/workflows/wasm-native-build.yml | 1 - .github/workflows/windows-cuda-native-build.yml | 1 - .github/workflows/windows-native-build.yml | 2 -- .github/workflows/windows-noavx-native-build.yml | 1 - .github/workflows/windows-openvino-native-build.yml | 1 - .github/workflows/windows-vulkan-native-build.yml | 1 - 14 files changed, 17 deletions(-) diff --git a/.github/workflows/android-native-build.yml b/.github/workflows/android-native-build.yml index 289345a40..30c51e05b 100644 --- a/.github/workflows/android-native-build.yml +++ b/.github/workflows/android-native-build.yml @@ -14,7 +14,6 @@ jobs: - uses: actions/checkout@v4 with: submodules: true - ref: ${{ github.head_ref }} - name: Install Android NDK uses: nttld/setup-ndk@afb4c9964b521afb97c864b7d40b11e6911bd410 diff --git a/.github/workflows/linux-cuda-native-build.yml b/.github/workflows/linux-cuda-native-build.yml index b2df14ad3..d359af99c 100644 --- a/.github/workflows/linux-cuda-native-build.yml +++ b/.github/workflows/linux-cuda-native-build.yml @@ -15,7 +15,6 @@ jobs: - uses: actions/checkout@v4 with: submodules: true - ref: ${{ github.head_ref }} - name: Install aarch64-linux-gnu-gcc run: sudo apt-get update && sudo apt-get install -y gcc-aarch64-linux-gnu && sudo apt-get install -y g++-aarch64-linux-gnu diff --git a/.github/workflows/linux-native-build.yml b/.github/workflows/linux-native-build.yml index 0516a6324..84bd62dde 100644 --- a/.github/workflows/linux-native-build.yml +++ b/.github/workflows/linux-native-build.yml @@ -15,7 +15,6 @@ jobs: - uses: actions/checkout@v4 with: submodules: true - ref: ${{ github.head_ref }} - name: Install aarch64-linux-gnu-gcc run: sudo apt-get update && sudo apt-get install -y gcc-aarch64-linux-gnu && sudo apt-get install -y g++-aarch64-linux-gnu diff --git a/.github/workflows/linux-noavx-native-build.yml b/.github/workflows/linux-noavx-native-build.yml index 67aeb3776..ee7893274 100644 --- a/.github/workflows/linux-noavx-native-build.yml +++ b/.github/workflows/linux-noavx-native-build.yml @@ -15,7 +15,6 @@ jobs: - uses: actions/checkout@v4 with: submodules: true - ref: ${{ github.head_ref }} - name: Install aarch64-linux-gnu-gcc run: sudo apt-get update && sudo apt-get install -y gcc-aarch64-linux-gnu && sudo apt-get install -y g++-aarch64-linux-gnu diff --git a/.github/workflows/linux-openvino-native-build.yml b/.github/workflows/linux-openvino-native-build.yml index 7546749e1..2d4ce3c8b 100644 --- a/.github/workflows/linux-openvino-native-build.yml +++ b/.github/workflows/linux-openvino-native-build.yml @@ -15,7 +15,6 @@ jobs: - uses: actions/checkout@v4 with: submodules: true - ref: ${{ github.head_ref }} - name: Install aarch64-linux-gnu-gcc run: sudo apt-get update && sudo apt-get install -y gcc-aarch64-linux-gnu && sudo apt-get install -y g++-aarch64-linux-gnu diff --git a/.github/workflows/linux-vulkan-native-build.yml b/.github/workflows/linux-vulkan-native-build.yml index df46873ec..48a5c056a 100644 --- a/.github/workflows/linux-vulkan-native-build.yml +++ b/.github/workflows/linux-vulkan-native-build.yml @@ -15,7 +15,6 @@ jobs: - uses: actions/checkout@v4 with: submodules: true - ref: ${{ github.head_ref }} - name: Install aarch64-linux-gnu-gcc run: sudo apt-get update && sudo apt-get install -y gcc-aarch64-linux-gnu && sudo apt-get install -y g++-aarch64-linux-gnu diff --git a/.github/workflows/macos-coreml-native-build.yml b/.github/workflows/macos-coreml-native-build.yml index a33ccd112..bce6a1e67 100644 --- a/.github/workflows/macos-coreml-native-build.yml +++ b/.github/workflows/macos-coreml-native-build.yml @@ -15,7 +15,6 @@ jobs: - uses: actions/checkout@v4 with: submodules: true - ref: ${{ github.head_ref }} - name: Run apple coreml build for x64 run: make apple_coreml_x64 @@ -36,7 +35,6 @@ jobs: - uses: actions/checkout@v4 with: submodules: true - ref: ${{ github.head_ref }} - name: Run apple coreml build for arm run: make apple_coreml_arm diff --git a/.github/workflows/macos-native-build.yml b/.github/workflows/macos-native-build.yml index a686c53bd..1c5fa7a2c 100644 --- a/.github/workflows/macos-native-build.yml +++ b/.github/workflows/macos-native-build.yml @@ -15,7 +15,6 @@ jobs: - uses: actions/checkout@v4 with: submodules: true - ref: ${{ github.head_ref }} - name: Run apple build for x64 run: make apple_x64 @@ -36,7 +35,6 @@ jobs: - uses: actions/checkout@v4 with: submodules: true - ref: ${{ github.head_ref }} - name: Run apple build for arm run: make apple_arm diff --git a/.github/workflows/wasm-native-build.yml b/.github/workflows/wasm-native-build.yml index 148adc4d8..6fe0e4c00 100644 --- a/.github/workflows/wasm-native-build.yml +++ b/.github/workflows/wasm-native-build.yml @@ -15,7 +15,6 @@ jobs: - uses: actions/checkout@v4 with: submodules: true - ref: ${{ github.head_ref }} - name: Install Emscripten uses: mymindstorm/setup-emsdk@6ab9eb1bda2574c4ddb79809fc9247783eaf9021 diff --git a/.github/workflows/windows-cuda-native-build.yml b/.github/workflows/windows-cuda-native-build.yml index cc8f09d69..77383b2cf 100644 --- a/.github/workflows/windows-cuda-native-build.yml +++ b/.github/workflows/windows-cuda-native-build.yml @@ -16,7 +16,6 @@ jobs: with: submodules: true - ref: ${{ github.head_ref }} - name: Add msbuild to PATH uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce diff --git a/.github/workflows/windows-native-build.yml b/.github/workflows/windows-native-build.yml index d18a9da48..a4504d12a 100644 --- a/.github/workflows/windows-native-build.yml +++ b/.github/workflows/windows-native-build.yml @@ -16,7 +16,6 @@ jobs: with: submodules: true - ref: ${{ github.head_ref }} - name: Install Ninja id: install_ninja @@ -43,7 +42,6 @@ jobs: - uses: actions/checkout@v4 with: submodules: true - ref: ${{ github.head_ref }} - name: Install Ninja id: install_ninja diff --git a/.github/workflows/windows-noavx-native-build.yml b/.github/workflows/windows-noavx-native-build.yml index 58e3d5076..1c6544c90 100644 --- a/.github/workflows/windows-noavx-native-build.yml +++ b/.github/workflows/windows-noavx-native-build.yml @@ -15,7 +15,6 @@ jobs: - uses: actions/checkout@v4 with: submodules: true - ref: ${{ github.head_ref }} - name: Install Ninja id: install_ninja diff --git a/.github/workflows/windows-openvino-native-build.yml b/.github/workflows/windows-openvino-native-build.yml index 8e615d48a..ac52ddc90 100644 --- a/.github/workflows/windows-openvino-native-build.yml +++ b/.github/workflows/windows-openvino-native-build.yml @@ -15,7 +15,6 @@ jobs: - uses: actions/checkout@v4 with: submodules: true - ref: ${{ github.head_ref }} - name: Add msbuild to PATH uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce diff --git a/.github/workflows/windows-vulkan-native-build.yml b/.github/workflows/windows-vulkan-native-build.yml index b5a348df2..486e9ce18 100644 --- a/.github/workflows/windows-vulkan-native-build.yml +++ b/.github/workflows/windows-vulkan-native-build.yml @@ -15,7 +15,6 @@ jobs: - uses: actions/checkout@v4 with: submodules: true - ref: ${{ github.head_ref }} - name: Add msbuild to PATH uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce From d155367346681bff2b2f8e240b54a017c7295480 Mon Sep 17 00:00:00 2001 From: Sandro Hanea Date: Thu, 10 Apr 2025 19:36:30 +0200 Subject: [PATCH 3/7] Fixed one more issue in TestApplicationDelegate. CS8765: Nullability of type of parameter 'launchOptions' doesn't match overridden member --- Whisper.net/WhisperProcessor.cs | 2 +- .../Platforms/iOS/TestApplicationDelegate.cs | 3 +-- .../SpeechToText/WhisperSpeechToTextClientTest.cs | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Whisper.net/WhisperProcessor.cs b/Whisper.net/WhisperProcessor.cs index 5a6cfca97..0aca52351 100755 --- a/Whisper.net/WhisperProcessor.cs +++ b/Whisper.net/WhisperProcessor.cs @@ -280,7 +280,7 @@ public IAsyncEnumerable ProcessAsync(float[] samples, CancellationT /// Returns the strings in the given to the string pool. /// /// - /// This method should be used when was activated. + /// This method should be used when was activated. /// Once a is returned, the string values inside it (e.g. ) might be changed. /// public void Return(SegmentData segmentData) diff --git a/tests/Whisper.net.Maui.Tests/Platforms/iOS/TestApplicationDelegate.cs b/tests/Whisper.net.Maui.Tests/Platforms/iOS/TestApplicationDelegate.cs index 4d75b6fce..4e8c80eee 100644 --- a/tests/Whisper.net.Maui.Tests/Platforms/iOS/TestApplicationDelegate.cs +++ b/tests/Whisper.net.Maui.Tests/Platforms/iOS/TestApplicationDelegate.cs @@ -1,6 +1,5 @@ // Licensed under the MIT license: https://opensource.org/licenses/MIT -using System.Globalization; using Foundation; using Microsoft.DotNet.XHarness.TestRunners.Common; using Microsoft.DotNet.XHarness.TestRunners.Xunit; @@ -14,7 +13,7 @@ public class TestApplicationDelegate : UIApplicationDelegate { public override UIWindow? Window { get; set; } - public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions) + public override bool FinishedLaunching(UIApplication application, NSDictionary? launchOptions) { Window = new UIWindow(UIScreen.MainScreen.Bounds) { diff --git a/tests/Whisper.net.Tests/SpeechToText/WhisperSpeechToTextClientTest.cs b/tests/Whisper.net.Tests/SpeechToText/WhisperSpeechToTextClientTest.cs index 2f8aab69a..9cc36e9bb 100644 --- a/tests/Whisper.net.Tests/SpeechToText/WhisperSpeechToTextClientTest.cs +++ b/tests/Whisper.net.Tests/SpeechToText/WhisperSpeechToTextClientTest.cs @@ -184,7 +184,6 @@ public async Task GetTextAsync_CalledMultipleTimes_Serially_WillCompleteEverytim var result3 = await client.GetTextAsync(fileReader3, options); var segments3 = Assert.IsAssignableFrom>(result3.RawRepresentation); - Assert.True(segments1.SequenceEqual(segments2, new SegmentDataComparer())); Assert.True(segments2.SequenceEqual(segments3, new SegmentDataComparer())); } From 8f044ec20c58e1520affd20f03ec7ee8237aed95 Mon Sep 17 00:00:00 2001 From: Sandro Hanea Date: Sun, 13 Apr 2025 12:23:58 +0200 Subject: [PATCH 4/7] Update async patterns and tests; bump xcode version to 16.3 Improved `await using` usage in tests for better async handling and added a new parallel execution test. Fixed minor typos in test method names. Updated GitHub workflow to use Xcode 16.3 and made minor formatting adjustments for consistency. --- .github/workflows/dotnet-maui.yml | 24 +-- .../ProcessAsyncFunctionalTests.cs | 142 +++++++++++++----- 2 files changed, 114 insertions(+), 52 deletions(-) diff --git a/.github/workflows/dotnet-maui.yml b/.github/workflows/dotnet-maui.yml index a1a8a3ffc..00a1d6627 100644 --- a/.github/workflows/dotnet-maui.yml +++ b/.github/workflows/dotnet-maui.yml @@ -27,8 +27,8 @@ jobs: - uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd with: - xcode-version: '16.2' - + xcode-version: '16.3' + - name: Download Artifacts id: download-artifact uses: actions/download-artifact@v4 @@ -40,16 +40,16 @@ jobs: run: | dotnet workload install maui --ignore-failed-sources dotnet workload install tvos --ignore-failed-sources - + - name: Restore dependencies run: dotnet restore ./Whisper.net.Maui.Tests.sln - + - name: Build ios-simulator run: dotnet build ./tests/Whisper.net.Maui.Tests/Whisper.net.Maui.Tests.csproj -c Debug -f net9.0-ios -r iossimulator-arm64 -p:EmbedAssembliesIntoAppBundle=true -p:CodesignKey="" -p:CodesignProvision="" - name: Build android run: dotnet build ./tests/Whisper.net.Maui.Tests/Whisper.net.Maui.Tests.csproj -c Debug -f net9.0-android -p:EmbedAssembliesIntoApk=true - + - name: Upload apk and ios app uses: actions/upload-artifact@v4 with: @@ -80,13 +80,13 @@ jobs: with: name: maui-build-artifacts path: maui-build-artifacts - + - name: Enable KVM group perms run: | echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules sudo udevadm control --reload-rules sudo udevadm trigger --name-match=kvm - + - name: Install xharness run: dotnet tool install Microsoft.DotNet.XHarness.CLI --global --add-source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json --version "10.0.0-*" @@ -96,7 +96,7 @@ jobs: api-level: 29 arch: x86_64 script: xharness android test --app=./maui-build-artifacts/net9.0-android/com.companyname.whisper.net.maui.tests-Signed.apk -p com.companyname.whisper.net.maui.tests -i com.companyname.whisper.net.maui.tests.AndroidMauiTestInstrumentation -o=./test-results/android - + - name: Upload Maui Android xharness test results if: ${{ always() }} uses: actions/upload-artifact@v4 @@ -108,7 +108,7 @@ jobs: dotnet-maui-test-ios: runs-on: macos-15 needs: dotnet-maui-build - + env: USE_WHISPER_MAUI: "TRUE" @@ -120,7 +120,7 @@ jobs: with: dotnet-version: | 8.0.x - + - uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd with: xcode-version: '16.2' @@ -131,14 +131,14 @@ jobs: with: name: maui-build-artifacts path: maui-build-artifacts - + - name: Install xharness run: dotnet tool install Microsoft.DotNet.XHarness.CLI --global --add-source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json --version "10.0.0-*" - name: run ios tests run: xharness apple test --app=./maui-build-artifacts/net9.0-ios/iossimulator-arm64/Whisper.net.Maui.Tests.app --output-directory=./test-results/ios --target=ios-simulator-64 - + - name: Upload Maui iOS xharness test results if: ${{ always() }} uses: actions/upload-artifact@v4 diff --git a/tests/Whisper.net.Tests/ProcessAsyncFunctionalTests.cs b/tests/Whisper.net.Tests/ProcessAsyncFunctionalTests.cs index 8c01934a4..bc068bcfd 100644 --- a/tests/Whisper.net.Tests/ProcessAsyncFunctionalTests.cs +++ b/tests/Whisper.net.Tests/ProcessAsyncFunctionalTests.cs @@ -1,8 +1,10 @@ // Licensed under the MIT license: https://opensource.org/licenses/MIT +using Whisper.net.Wave; using Xunit; namespace Whisper.net.Tests; + public partial class ProcessAsyncFunctionalTests(TinyModelFixture model) : IClassFixture { [Fact] @@ -14,18 +16,18 @@ public async Task TestHappyFlowAsync() var encoderBegins = new List(); using var factory = WhisperFactory.FromPath(model.ModelFile); - using var processor = factory.CreateBuilder() - .WithLanguage("en") - .WithEncoderBeginHandler((e) => - { - encoderBegins.Add(e); - return true; - }) - .WithProgressHandler(progress.Add) - .WithSegmentEventHandler(segments.Add) - .Build(); - - using var fileReader = await TestDataProvider.OpenFileStreamAsync("kennedy.wav"); + await using var processor = factory.CreateBuilder() + .WithLanguage("en") + .WithEncoderBeginHandler((e) => + { + encoderBegins.Add(e); + return true; + }) + .WithProgressHandler(progress.Add) + .WithSegmentEventHandler(segments.Add) + .Build(); + + await using var fileReader = await TestDataProvider.OpenFileStreamAsync("kennedy.wav"); await foreach (var data in processor.ProcessAsync(fileReader)) { segmentsEnumerated.Add(data); @@ -40,7 +42,7 @@ public async Task TestHappyFlowAsync() } [Fact] - public async Task ProcessAsync_Cancelled_WillCancellTheProcessing_AndDispose_WillWaitUntilFullyFinished() + public async Task ProcessAsync_Cancelled_WillCancelTheProcessing_AndDispose_WillWaitUntilFullyFinished() { var segments = new List(); var segmentsEnumerated = new List(); @@ -50,20 +52,20 @@ public async Task ProcessAsync_Cancelled_WillCancellTheProcessing_AndDispose_Wil var encoderBegins = new List(); using var factory = WhisperFactory.FromPath(model.ModelFile); var processor = factory.CreateBuilder() - .WithLanguage("en") - .WithEncoderBeginHandler((e) => - { - encoderBegins.Add(e); - return true; - }) - .WithSegmentEventHandler(s => - { - segments.Add(s); - cts.Cancel(); - }) - .Build(); - - using var fileReader = await TestDataProvider.OpenFileStreamAsync("kennedy.wav"); + .WithLanguage("en") + .WithEncoderBeginHandler((e) => + { + encoderBegins.Add(e); + return true; + }) + .WithSegmentEventHandler(s => + { + segments.Add(s); + cts.Cancel(); + }) + .Build(); + + await using var fileReader = await TestDataProvider.OpenFileStreamAsync("kennedy.wav"); try { await foreach (var data in processor.ProcessAsync(fileReader, cts.Token)) @@ -79,8 +81,8 @@ public async Task ProcessAsync_Cancelled_WillCancellTheProcessing_AndDispose_Wil await processor.DisposeAsync(); Assert.Empty(segmentsEnumerated); - Assert.Single( segments); - Assert.Single( encoderBegins); + Assert.Single(segments); + Assert.Single(encoderBegins); Assert.NotNull(taskCanceledException); Assert.Contains(segments, segmentData => segmentData.Text.Contains("nation should commit")); } @@ -92,10 +94,10 @@ public async Task ProcessAsync_WhenJunkChunkExists_ProcessCorrectly() using var factory = WhisperFactory.FromPath(model.ModelFile); await using var processor = factory.CreateBuilder() - .WithLanguage("en") - .Build(); + .WithLanguage("en") + .Build(); - using var fileReader = await TestDataProvider.OpenFileStreamAsync("junkchunk16khz.wav"); + await using var fileReader = await TestDataProvider.OpenFileStreamAsync("junkchunk16khz.wav"); await foreach (var segment in processor.ProcessAsync(fileReader)) { segments.Add(segment); @@ -111,10 +113,10 @@ public async Task ProcessAsync_WhenMultichannel_ProcessCorrectly() using var factory = WhisperFactory.FromPath(model.ModelFile); await using var processor = factory.CreateBuilder() - .WithLanguage("en") - .Build(); + .WithLanguage("en") + .Build(); - using var fileReader = await TestDataProvider.OpenFileStreamAsync("multichannel.wav"); + await using var fileReader = await TestDataProvider.OpenFileStreamAsync("multichannel.wav"); await foreach (var segment in processor.ProcessAsync(fileReader)) { segments.Add(segment); @@ -132,22 +134,22 @@ public async Task ProcessAsync_CalledMultipleTimes_Serially_WillCompleteEverytim using var factory = WhisperFactory.FromPath(model.ModelFile); await using var processor = factory.CreateBuilder() - .WithLanguage("en") - .Build(); + .WithLanguage("en") + .Build(); - using var fileReader = await TestDataProvider.OpenFileStreamAsync("kennedy.wav"); + await using var fileReader = await TestDataProvider.OpenFileStreamAsync("kennedy.wav"); await foreach (var segment in processor.ProcessAsync(fileReader)) { segments1.Add(segment); } - using var fileReader2 = await TestDataProvider.OpenFileStreamAsync("kennedy.wav"); + await using var fileReader2 = await TestDataProvider.OpenFileStreamAsync("kennedy.wav"); await foreach (var segment in processor.ProcessAsync(fileReader2)) { segments2.Add(segment); } - using var fileReader3 = await TestDataProvider.OpenFileStreamAsync("kennedy.wav"); + await using var fileReader3 = await TestDataProvider.OpenFileStreamAsync("kennedy.wav"); await foreach (var segment in processor.ProcessAsync(fileReader3)) { segments3.Add(segment); @@ -156,4 +158,64 @@ public async Task ProcessAsync_CalledMultipleTimes_Serially_WillCompleteEverytim Assert.True(segments1.SequenceEqual(segments2, new SegmentDataComparer())); Assert.True(segments2.SequenceEqual(segments3, new SegmentDataComparer())); } + + [Fact] + public async Task ProcessAsync_ParallelExecution_WillCompleteEverytime() + { + var segments1 = new List(); + var segments2 = new List(); + var segments3 = new List(); + + using var factory = WhisperFactory.FromPath(model.ModelFile); + await using var fileReader = await TestDataProvider.OpenFileStreamAsync("kennedy.wav"); + var waveParser = new WaveParser(fileReader); + var samples = await waveParser.GetAvgSamplesAsync(); + + var task1 = Task.Run(async () => + { + await using var processor = factory.CreateBuilder() + .WithLanguage("en") + .Build(); + + await foreach (var segment in processor.ProcessAsync(samples)) + { + Thread.Sleep(300); + segments1.Add(segment); + } + }); + + var task2 = Task.Run(async () => + { + await using var processor = factory.CreateBuilder() + .WithLanguage("en") + .Build(); + + await foreach (var segment in processor.ProcessAsync(samples)) + { + Thread.Sleep(300); + segments2.Add(segment); + } + }); + + + var task3 = Task.Run(async () => + { + await using var processor = factory.CreateBuilder() + .WithLanguage("en") + .Build(); + + await foreach (var segment in processor.ProcessAsync(samples)) + { + Thread.Sleep(300); + segments3.Add(segment); + } + }); + + await Task.WhenAll(task1, task2, task3); + + // Assert + Assert.True(segments1.SequenceEqual(segments2, new SegmentDataComparer())); + Assert.True(segments2.SequenceEqual(segments3, new SegmentDataComparer())); + Assert.True(segments1.SequenceEqual(segments3, new SegmentDataComparer())); + } } From 8c15dfad6b3ca726864f17e20bb891d591a1158f Mon Sep 17 00:00:00 2001 From: Sandro Hanea Date: Sun, 13 Apr 2025 12:32:34 +0200 Subject: [PATCH 5/7] net8 issue --- .../ProcessAsyncFunctionalTests.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/Whisper.net.Tests/ProcessAsyncFunctionalTests.cs b/tests/Whisper.net.Tests/ProcessAsyncFunctionalTests.cs index bc068bcfd..728ffde18 100644 --- a/tests/Whisper.net.Tests/ProcessAsyncFunctionalTests.cs +++ b/tests/Whisper.net.Tests/ProcessAsyncFunctionalTests.cs @@ -27,7 +27,7 @@ public async Task TestHappyFlowAsync() .WithSegmentEventHandler(segments.Add) .Build(); - await using var fileReader = await TestDataProvider.OpenFileStreamAsync("kennedy.wav"); + var fileReader = await TestDataProvider.OpenFileStreamAsync("kennedy.wav"); await foreach (var data in processor.ProcessAsync(fileReader)) { segmentsEnumerated.Add(data); @@ -65,7 +65,7 @@ public async Task ProcessAsync_Cancelled_WillCancelTheProcessing_AndDispose_Will }) .Build(); - await using var fileReader = await TestDataProvider.OpenFileStreamAsync("kennedy.wav"); + var fileReader = await TestDataProvider.OpenFileStreamAsync("kennedy.wav"); try { await foreach (var data in processor.ProcessAsync(fileReader, cts.Token)) @@ -97,7 +97,7 @@ public async Task ProcessAsync_WhenJunkChunkExists_ProcessCorrectly() .WithLanguage("en") .Build(); - await using var fileReader = await TestDataProvider.OpenFileStreamAsync("junkchunk16khz.wav"); + using var fileReader = await TestDataProvider.OpenFileStreamAsync("junkchunk16khz.wav"); await foreach (var segment in processor.ProcessAsync(fileReader)) { segments.Add(segment); @@ -116,7 +116,7 @@ public async Task ProcessAsync_WhenMultichannel_ProcessCorrectly() .WithLanguage("en") .Build(); - await using var fileReader = await TestDataProvider.OpenFileStreamAsync("multichannel.wav"); + using var fileReader = await TestDataProvider.OpenFileStreamAsync("multichannel.wav"); await foreach (var segment in processor.ProcessAsync(fileReader)) { segments.Add(segment); @@ -137,19 +137,19 @@ public async Task ProcessAsync_CalledMultipleTimes_Serially_WillCompleteEverytim .WithLanguage("en") .Build(); - await using var fileReader = await TestDataProvider.OpenFileStreamAsync("kennedy.wav"); + using var fileReader = await TestDataProvider.OpenFileStreamAsync("kennedy.wav"); await foreach (var segment in processor.ProcessAsync(fileReader)) { segments1.Add(segment); } - await using var fileReader2 = await TestDataProvider.OpenFileStreamAsync("kennedy.wav"); + using var fileReader2 = await TestDataProvider.OpenFileStreamAsync("kennedy.wav"); await foreach (var segment in processor.ProcessAsync(fileReader2)) { segments2.Add(segment); } - await using var fileReader3 = await TestDataProvider.OpenFileStreamAsync("kennedy.wav"); + using var fileReader3 = await TestDataProvider.OpenFileStreamAsync("kennedy.wav"); await foreach (var segment in processor.ProcessAsync(fileReader3)) { segments3.Add(segment); @@ -167,7 +167,7 @@ public async Task ProcessAsync_ParallelExecution_WillCompleteEverytime() var segments3 = new List(); using var factory = WhisperFactory.FromPath(model.ModelFile); - await using var fileReader = await TestDataProvider.OpenFileStreamAsync("kennedy.wav"); + using var fileReader = await TestDataProvider.OpenFileStreamAsync("kennedy.wav"); var waveParser = new WaveParser(fileReader); var samples = await waveParser.GetAvgSamplesAsync(); From 54d3a3abb1074268e45894c4a07f70e56346b9e9 Mon Sep 17 00:00:00 2001 From: Sandro Hanea Date: Tue, 15 Apr 2025 17:09:51 +0200 Subject: [PATCH 6/7] Ubuntu 22 update as 20 is deprecated --- .github/workflows/android-native-build.yml | 2 +- .github/workflows/linux-cuda-native-build.yml | 2 +- .github/workflows/linux-native-build.yml | 2 +- .github/workflows/linux-noavx-native-build.yml | 2 +- .github/workflows/linux-openvino-native-build.yml | 2 +- .github/workflows/linux-vulkan-native-build.yml | 2 +- .github/workflows/wasm-native-build.yml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/android-native-build.yml b/.github/workflows/android-native-build.yml index 30c51e05b..5f96dab6d 100644 --- a/.github/workflows/android-native-build.yml +++ b/.github/workflows/android-native-build.yml @@ -8,7 +8,7 @@ on: jobs: native-build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/linux-cuda-native-build.yml b/.github/workflows/linux-cuda-native-build.yml index d359af99c..0882151cc 100644 --- a/.github/workflows/linux-cuda-native-build.yml +++ b/.github/workflows/linux-cuda-native-build.yml @@ -9,7 +9,7 @@ on: jobs: native-build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/linux-native-build.yml b/.github/workflows/linux-native-build.yml index 84bd62dde..a2b7dce4d 100644 --- a/.github/workflows/linux-native-build.yml +++ b/.github/workflows/linux-native-build.yml @@ -9,7 +9,7 @@ on: jobs: native-build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/linux-noavx-native-build.yml b/.github/workflows/linux-noavx-native-build.yml index ee7893274..df28c665d 100644 --- a/.github/workflows/linux-noavx-native-build.yml +++ b/.github/workflows/linux-noavx-native-build.yml @@ -9,7 +9,7 @@ on: jobs: native-build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/linux-openvino-native-build.yml b/.github/workflows/linux-openvino-native-build.yml index 2d4ce3c8b..e5dd612a9 100644 --- a/.github/workflows/linux-openvino-native-build.yml +++ b/.github/workflows/linux-openvino-native-build.yml @@ -9,7 +9,7 @@ on: jobs: native-build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/linux-vulkan-native-build.yml b/.github/workflows/linux-vulkan-native-build.yml index 48a5c056a..802db37ce 100644 --- a/.github/workflows/linux-vulkan-native-build.yml +++ b/.github/workflows/linux-vulkan-native-build.yml @@ -9,7 +9,7 @@ on: jobs: native-build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/wasm-native-build.yml b/.github/workflows/wasm-native-build.yml index 6fe0e4c00..814684b7c 100644 --- a/.github/workflows/wasm-native-build.yml +++ b/.github/workflows/wasm-native-build.yml @@ -9,7 +9,7 @@ on: jobs: native-build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 From 3c3166c5de6ace41d1dd4f4962b70a032e304e3a Mon Sep 17 00:00:00 2001 From: Sandro Hanea Date: Tue, 15 Apr 2025 17:44:47 +0200 Subject: [PATCH 7/7] Try again --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 259e81138..4f6527fcf 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ copy_metal_coreml: wasm: rm -rf build/wasm emcmake cmake -S . -B build/wasm -DCMAKE_BUILD_TYPE=$(BUILD_TYPE) - cmake --build build/wasm --config $(BUILD_TYPE) + emcmake cmake --build build/wasm --config $(BUILD_TYPE) mkdir -p runtimes/Whisper.net.Runtime/browser-wasm cp build/wasm/whisper.cpp/src/libwhisper.a ./runtimes/Whisper.net.Runtime/browser-wasm/libwhisper.a cp build/wasm/whisper.cpp/ggml/src/libggml-whisper.a ./runtimes/Whisper.net.Runtime/browser-wasm/libggml-whisper.a