如何在Docker中使用dotnet core作为Azure函数来运行FFProbe?

4
我正在尝试从基于URL的视频获取视频详细信息(长度、高度、宽度和内容类型)。通过使用nuget包https://www.nuget.org/packages/NReco.VideoInfo.LT,我能够轻松地创建一个指向我本地安装的FFProbe的Azure函数。然而,关键是使它与Azure Function兼容,据我所知,最简单的方法是提供一个包含所有必需内容的Docker镜像(这将在Linux机器上运行)。
因此,让我们进入代码。如果我在本地运行该函数,先前我就已成功运行如下所示:
   var ffProbe = new NReco.VideoInfo.FFProbe();
   ffProbe.FFProbeExeName = "ffprobe.exe";  // just "ffprobe" for Linux/OS-X
   ffProbe.ToolPath = "C:\\tools\\ffmpeg\\bin";
   var videoInfo = ffProbe.GetMediaInfo(videoUrl);

现在,(再次强调,据我所知这是最佳方式),要在Linux环境下使用Docker运行它,我遇到了一些问题。

因此,第一次尝试采用了简单的方法,即apt-get install ffmpeg。以下是Dockerfile(抱歉,这将是一篇很长的文章...但最好展示所有内容):

   FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS installer-env
   
   # 0. Install essential packages
   RUN apt-get -y update
   RUN apt-get -y upgrade
   RUN apt-get install -y ffmpeg
   
   ENV AzureWebJobsStorage=""
   
   COPY . /src/dotnet-function-app
   RUN cd /src/dotnet-function-app && \
   mkdir -p /home/site/wwwroot && \
   dotnet publish *.csproj --output /home/site/wwwroot
    
   RUN mkdir -p /home/site/wwwroot/bin
   RUN mv /usr/bin/* /home/site/wwwroot/bin
   
   # To enable ssh & remote debugging on app service change the base image to the one below
   # FROM mcr.microsoft.com/azure-functions/dotnet:3.0-appservice
   FROM mcr.microsoft.com/azure-functions/dotnet:3.0
   ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
   AzureFunctionsJobHost__Logging__Console__IsEnabled=true

   COPY --from=installer-env ["/home/site/wwwroot", "/home/site/wwwroot"]

我修改了代码为

   var ffProbe = new NReco.VideoInfo.FFProbe();
   ffProbe.FFProbeExeName = "ffprobe";  // just "ffprobe" for Linux/OS-X
   ffProbe.ToolPath = "/home/site/wwwroot/bin";
   var videoInfo = ffProbe.GetMediaInfo(videoUrl);

我编译代码后出现错误:加载共享库libavdevice.so.58时出错

因此,我进行了一些调查,发现我需要手动构建。虽然这并不是最理想的选择,但我尝试了一下并修改了Dockerfile文件:

   FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS installer-env

   # 0. Install essential packages
   RUN apt-get update -qq && apt-get -y install \
       autoconf \
       automake \
       build-essential \
       cmake \
       git-core \
       libass-dev \
       libfreetype6-dev \
       libsdl2-dev \
       libtool \
       libva-dev \
       libvdpau-dev \
       libvorbis-dev \
       libxcb1-dev \
       libxcb-shm0-dev \
       libxcb-xfixes0-dev \
       pkg-config \
       texinfo \
       wget \
       zlib1g-dev \
       nasm \
       yasm \
       libx265-dev \
       libnuma-dev \
       libvpx-dev \
       libmp3lame-dev \
       libopus-dev \
       libx264-dev
   
   RUN mkdir -p /home/site/wwwroot
   
   RUN mkdir -p /home/site/wwwroot/ffmpeg_sources /home/site/wwwroot/bin && cd /home/site/wwwroot/ffmpeg_sources && \
       wget -O ffmpeg-4.3.1.tar.bz2 https://ffmpeg.org/releases/ffmpeg-4.3.1.tar.bz2 && \
       tar xjvf ffmpeg-4.3.1.tar.bz2 && \
       cd ffmpeg-4.3.1 && \
       PATH="/home/site/wwwroot/bin:$PATH" PKG_CONFIG_PATH="/home/site/wwwroot/ffmpeg_build/lib/pkgconfig" ./configure \
       --prefix="/home/site/wwwroot/ffmpeg_build" \
       --pkg-config-flags="--static" \
       --extra-cflags="-I/home/site/wwwroot/ffmpeg_build/include" \
       --extra-ldflags="-L/home/site/wwwroot/ffmpeg_build/lib" \
       --extra-libs="-lpthread -lm" \
       --bindir="/home/site/wwwroot/bin" \
       --enable-gpl \
       --enable-libass \
       --enable-libfreetype \
       --enable-libmp3lame \
       --enable-libopus \
       --enable-libvorbis \
       --enable-libvpx \
       --enable-libx264 \
       --enable-libx265 \
       --enable-nonfree && \
       PATH="/home/site/wwwroot/bin:$PATH" make -j8 && \
       make install -j8 && \
       hash -r
   
   ENV AzureWebJobsStorage=""
   
   COPY . /src/dotnet-function-app
   RUN cd /src/dotnet-function-app && \
   dotnet publish *.csproj --output /home/site/wwwroot
   
   FROM mcr.microsoft.com/azure-functions/dotnet:3.0
   ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
       AzureFunctionsJobHost__Logging__Console__IsEnabled=true
   
   COPY --from=installer-env ["/home/site/wwwroot", "/home/site/wwwroot"]

再次构建后,我尝试运行,这次出现了同样的错误,但是是针对另一个文件:error while loading shared libraries: libxcb.so.1

所以,我应该提到Docker对我来说有点新,所以我可能会忽略一些简单的东西。但我一整晚都在努力解决问题,直到我决定需要一些建议。我的主要应用程序也托管在Linux机器上,所以那里是不行的。除了Azure函数方法之外,另一个疯狂的想法是启动一个低优先级的Windows虚拟机,大约花费20美元每月......但然后我必须配置IIS和所有这些东西。因此,弄清楚我做错了什么或者它是否可行将是很好的。我之前已经使用Docker和Azure功能使Python / Selenium正常工作,基于https://github.com/rebremer/azure-function-selenium..,因此我希望只是我对Docker还不够熟悉。

如果您能帮助我让这个工作起来,我将非常感激。如果您有任何问题,请随时问我。

谢谢!


对于 Docker,如果基础镜像不包含所有依赖项,则需要安装它们。 - Charles Xu
你能再详细解释一下吗?我已经尝试在 Dockerfile 的不同部分包含“FROM jrottenberg/ffmpeg”,但最终它仍然找不到 ffprobe。我将路径更改为查找 /usr/local/bin,但我认为 FROM mcr.microsoft.com/azure-functions/dotnet 会覆盖从其他 Docker 镜像中拉取的任何内容。正如我所说,我对 Docker 还比较新……所以您能提供的更多信息将非常有帮助。谢谢您的帮助! - AJ Tatum
还有其他问题或更新吗? - Charles Xu
3个回答

7

当我意识到Azure Functions在Docker中的镜像基于Ubuntu时,我的解决方案最终没有使用另一个Docker镜像。因此,我撰写的Dockerfile如下:

FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS installer-env

COPY . /src/dotnet-function-app
RUN cd /src/dotnet-function-app && \
    mkdir -p /home/site/wwwroot && \
    dotnet publish *.csproj --output /home/site/wwwroot

FROM mcr.microsoft.com/azure-functions/dotnet:3.0
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
    AzureFunctionsJobHost__Logging__Console__IsEnabled=true \
    AzureWebJobsStorage=""

COPY --from=installer-env ["/home/site/wwwroot", "/home/site/wwwroot"]

RUN apt-get update && apt-get install -y ffmpeg

因此,最终的解决方案非常简单。让Azure构建镜像,将网站复制到wwwroot,然后像在Ubuntu上一样安装ffmpeg!然后,只需要更新代码:

var ffProbe = new NReco.VideoInfo.FFProbe();
ffProbe.FFProbeExeName = "ffprobe";  // just "ffprobe" for Linux/OS-X
ffProbe.ToolPath = "/usr/bin";
var mediaInfo = ffProbe.GetMediaInfo(videoUrl);

就这样了!


谢谢!这对我很有帮助。我的Dockerfile和你的差不多,只是在安装两个SDK之间安装了FFmpeg,而不是作为最后一步。将其移动到最后一步使其在最终阶段可用。 :) - Steve Ellis

0

由于您是 Docker 的新手,我将向您展示一些我所知道的内容。

您的 Dockerfile 是使用 多阶段构建 创建镜像的:

使用多阶段构建,在 Dockerfile 中使用多个 FROM 语句。每个 FROM 指令可以使用不同的基础镜像,并且每个指令都开始了构建的一个新阶段。您可以有选择地从一个阶段复制构件到另一个阶段,留下您不想要的所有内容,只保留最终镜像中需要的部分。

从描述中可以看出,除了最后一个 FROM 之外,您需要知道所有的 FROM 都是构建模式,只有完成应用程序的构建后才会将其复制到最后的基础镜像中并在其中运行。因此,这不是覆盖,而是一个新的运行环境。如果最后的基础镜像中没有安装您应用程序所需的所有依赖项,则需要在其中安装它们。


0

我是新手,所以我的解决方案可能不够高效。我也遇到了在dotnet core docker容器中使用FFMpegCore生成视频缩略图的问题。这是我在Dockerfile中想出来的解决方案。我会指出其中的重要行。

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-alpine
RUN apk add libgdiplus --update-cache --repository http://dl-3.alpinelinux.org/alpine/edge/testing/ --allow-untrusted
RUN apk update && apk add ffmpeg
... [onwards]

已添加FFMpegCore的软件包引用

<PackageReference Include="FFMpegCore" Version="2.2.6"/>

现在我的生成缩略图的代码:

public async Task<Stream> CreateVideoThumbnailAsync(IFormFile file, string thumbnailName)
    {
        // Creating a temporary folder in project directory
        string path = Directory.GetCurrentDirectory() + Path.GetTempPath();
        Directory.CreateDirectory("tmp");
        var filePath = Path.Combine(path, file.FileName);

        using (var fileStream = new FileStream(filePath, FileMode.Create)) {
            // Copying file to temporary folder
            await file.CopyToAsync(fileStream);
            
            // Generating thumbnail
            var mediaFileAnalysis = await FFProbe.AnalyseAsync(filePath);
            var bitmap = await FFMpeg.SnapshotAsync(mediaFileAnalysis, new Size(), TimeSpan.FromMinutes(1));
            
            // Cleaning project directory
            Directory.Delete("tmp", true);

            return bitmap.ToStream(ImageFormat.Jpeg);
        }
    }

public static Stream ToStream(this Image image, ImageFormat format) {
        var stream = new System.IO.MemoryStream();
        image.Save(stream, format);
        stream.Position = 0;
        return stream;
    }

我需要使用返回的流将其上传到 Azurite(用于本地 Azure 存储开发的仿真器)。 您可以查看 FFMpegCore 的文档。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接