How to get FFProbe to run using dotnet core as an Azure Function in Docker?

ajt*_*tum 3 ubuntu azure docker .net-core azure-functions

I am trying to get video details (length, height, width, and content type) from a video based on a URL. By using the nuget package https://www.nuget.org/packages/NReco.VideoInfo.LT I was able to create an Azure Function running locally pointing to my local install of FFProbe rather easily. However, the trick is now making it compatible with an Azure Function and, to the best of my knowledge, the easiest way to do that is by providing a Docker image that contains everything needed (this would be running on a Linux machine).

So, let's get into the code. Previously, this is what I had working if I ran the function locally:

   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);
Run Code Online (Sandbox Code Playgroud)

Now, (and again, this is the best to my knowledge), to get it to run in a Linux environment using Docker, I've run into several issues.

So, the first attempt was the easy way I suppose and try to do a apt-get install ffmpeg. This was the Dockerfile (Sorry, this is going to be a long post... but better to show everything I suppose):

   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"]
Run Code Online (Sandbox Code Playgroud)

I change the code to

   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);
Run Code Online (Sandbox Code Playgroud)

That builds, but when I run it, I get an error: error while loading shared libraries: libavdevice.so.58

So, I do some digging and it looks like I have to go the manual build route. Which isn't ideal, but I give it a go and adjust the 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"]
Run Code Online (Sandbox Code Playgroud)

Again, that builds and then I try to run, this time getting the same error but for a different file: error while loading shared libraries: libxcb.so.1

So, I should mention that Docker is somewhat new to me, so I could be missing something easy. But I've tried to figure this out all night until I decided that I needed some advice. My main app is also hosted on a linux machine, so that would be a no go there. Besides the Azure Function approach, the other crazy idea is spinning up a low-priority Windows VM for like $20 a month... but then I have to configure IIS and all that stuff. So, it would be great to figure out what I'm doing wrong or if it's even feasible. I've gotten Python/Selenium to work using Docker and Azure Functions before based off of https://github.com/rebremer/azure-function-selenium... so I'm hoping it's just me not being familiar with Docker enough.

任何帮助我完成这项工作的帮助将不胜感激。如果您有任何问题,请随时提出。

谢谢!

ajt*_*tum 6

一旦我意识到 Docker 中 Azure Functions 的映像基本上是从 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
Run Code Online (Sandbox Code Playgroud)

所以,它最终成为一个非常简单的解决方案。让 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);
Run Code Online (Sandbox Code Playgroud)

就是这样!