Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docker on Apple M2: Failed to load native whisper library #296

Open
pavelzaitsau opened this issue Dec 11, 2024 · 2 comments
Open

Docker on Apple M2: Failed to load native whisper library #296

pavelzaitsau opened this issue Dec 11, 2024 · 2 comments

Comments

@pavelzaitsau
Copy link

*Describtion
I use Whisper.net (AllRuntimes, v1.7.3) in dotnet9 container running MacOS Docker (both Docker VMM and Apple Virtualisation Framework). I got the error "Failed to load native whisper library". The same Dockerfile and codebase works fine on non-ARM Docker or natively on Mac

To Reproduce
Steps to reproduce the behavior:

  1. Dockerfile
    image

  2. Usage
    image

  3. Here is runtime directory of the app
    image

Expected behaviour:
No error like on x64-based docker

Environment:

  • OS Version: Apple M2; MacOS Sequoia 15.1.1 (24B91); Docker (both Docker VMM and Apple Virtualisation Framework)
  • Whisper Version: v1.7.3
  • Runtime: Whisper.net.AllRuntimes, Whisper.net.Runtime
@sandrohanea
Copy link
Owner

Hey @pavelzaitsau,

When running the docker on your M2 mac, which is the base image that you used?

Some workarounds:

You can try to build and run your docker file on M2 mac using:

docker build --platform linux/amd64 -t <image-name> .

docker run --platform linux/amd64 <image-name>

However, Whisper.net should support linux arm64 as well, so just running in on that should generally work. Maybe you're missing some dependencies for that base image (e.g. the libstdc++6 or glibc 2.31)

You can also debug this further by running ldd libwhisper.so and ldd libggml-whisper.so in the docker for those linux-arm64 runtimes => that will show you the dependencies and if they are available on that system.

@pavelzaitsau
Copy link
Author

Hi @sandrohanea!
I tried both your options with no luck. Probably something does not works especially on ARM64 platform or i missed something with the packages. But all the libraries you mentioned are in place

image

I'm attaching the complete test project to test on your side if needed

docker build -f test-whisper-net/Dockerfile . -t whisper --platform linux/arm64

test_whisper_net.csproj (took test audio files from the repo)

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net9.0</TargetFramework>
        <RootNamespace>test_whisper_net</RootNamespace>
        <LangVersion>latestmajor</LangVersion>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
    </PropertyGroup>

    <ItemGroup>
        <Content Include="..\.dockerignore">
            <Link>.dockerignore</Link>
        </Content>
    </ItemGroup>

    <ItemGroup>
      <Folder Include="audio\" />
      <Folder Include="model\" />
    </ItemGroup>

    <ItemGroup>
      <PackageReference Include="Whisper.net" Version="1.7.3" />
      <PackageReference Include="Whisper.net.AllRuntimes" Version="1.7.3" />
    </ItemGroup>

    <ItemGroup>
      <None Update="model\ggml-base.bin">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      </None>
      <None Update="audio\bush.wav">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      </None>
      <None Update="audio\kennedy.wav">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      </None>
      <None Update="audio\multichannel.wav">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      </None>
    </ItemGroup>
</Project>

program.cs

using System.Diagnostics;
using Whisper.net;

var result = new List<string>();
var whisperFactory = WhisperFactory.FromPath("model/ggml-base.bin");
var files = new DirectoryInfo("audio").EnumerateFiles("*", SearchOption.TopDirectoryOnly);
foreach (var file in files)
{
    var stopwatch = Stopwatch.StartNew();
    Console.ForegroundColor = ConsoleColor.Green;
    Console.WriteLine($"Processing {file}");
    using var processor = whisperFactory
        .CreateBuilder()
        .WithLanguage("auto")
        .WithNoContext()
        .WithSegmentEventHandler(segment =>
        {
            result.AddRange(
                segment.Text
                    .Trim()
                    .Split(['\n', '\r'], StringSplitOptions.RemoveEmptyEntries)
                    .Select(x => x.Trim())
                    .Where(x => !string.IsNullOrWhiteSpace(x)));
        })
        .Build();

    await using var stream = file.OpenRead();
    try
    {
        processor.Process(stream);
        
        Console.ForegroundColor = ConsoleColor.Magenta;
        Console.WriteLine($"Processed in {stopwatch.Elapsed.TotalSeconds:0.00}s.");
    }
    catch (Exception e)
    {
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine($"Error processing {file}: {e.Message}");
        continue;
    }

    if (result.Count > 0)
    {
        foreach (var line in result)
        {
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine(line);
        }
    }
    else
    {
        Console.ForegroundColor = ConsoleColor.Yellow;
        Console.WriteLine("No text detected");
    }
    
    Console.WriteLine();
}

Dockerfile

FROM debian:stable AS base

ENV \
  APP_UID=1654 \
  DOTNET_VERSION=9.0 \
  DOTNET_RUNNING_IN_CONTAINER=true \
  DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false

USER root

# Install dependencies
RUN apt update && apt install -y --no-install-recommends \
    ca-certificates \
    curl \
    libc6 \
    libicu-dev \
    libgcc-s1 \
    libstdc++6 \
    tzdata \
    gnupg \
    libsndfile1\
    xz-utils \
    && apt clean && rm -rf /var/lib/apt/lists/*

# Install dotnet 9.0 runtimes
RUN curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin -Channel 9.0 -Runtime dotnet -Runtime aspnetcore -InstallDir /usr/share/dotnet \
    && ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet

USER $APP_UID
WORKDIR /app

FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["test-whisper-net/test-whisper-net.csproj", "test-whisper-net/"]
RUN dotnet restore "test-whisper-net/test-whisper-net.csproj"
COPY . .
WORKDIR "/src/test-whisper-net"
RUN dotnet build "test-whisper-net.csproj" -c $BUILD_CONFIGURATION -o /app/build

FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "test-whisper-net.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false

FROM base AS final

RUN dotnet --list-runtimes

WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "test-whisper-net.dll"]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants