Как заставить FFProbe работать с использованием ядра do tnet в качестве функции Azure в Docker? - PullRequest
3 голосов
/ 07 августа 2020

Я пытаюсь получить сведения о видео (длину, высоту, ширину и тип содержимого) из видео на основе URL-адреса. Используя пакет nuget https://www.nuget.org/packages/NReco.VideoInfo.LT, я довольно легко смог создать функцию Azure, работающую локально и указывающую на мою локальную установку FFProbe. Однако теперь уловка заключается в том, чтобы сделать его совместимым с функцией Azure, и, насколько мне известно, самый простой способ сделать это - предоставить изображение 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. Это был файл Docker (извините, это будет длинный пост ... но лучше показать все, что я полагаю):

   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

Итак, я немного покопаюсь, и, похоже, мне нужно go маршрут сборки вручную. Это не идеально, но я даю ему go и настраиваю 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"]

Опять же, это строится, а затем я пытаюсь запустить, на этот раз получаю ту же ошибку, но для другого файла : ошибка при загрузке разделяемых библиотек: libxcb.so.1

Итак, я должен упомянуть, что Docker является для меня чем-то новым, так что мне может не хватать чего-то простого. Но я всю ночь пытался понять это, пока не решил, что мне нужен совет. Мое основное приложение также размещено на машине linux, так что там не будет go. Помимо подхода Azure Function, есть еще одна безумная идея - развернуть низкоприоритетную Windows виртуальную машину примерно за 20 долларов в месяц ... но затем мне нужно настроить IIS и все такое. Так что было бы здорово выяснить, что я делаю не так и возможно ли это вообще. Я получил Python / Selenium для работы с использованием функций Docker и Azure, прежде чем основывался на https://github.com/rebremer/azure-function-selenium... так что я надеюсь, что я просто недостаточно знаком с Docker.

Любая помощь, чтобы заставить это работать для меня, была бы очень признательна. Если у вас есть вопросы, не стесняйтесь спрашивать.

Спасибо!

Ответы [ 3 ]

5 голосов
/ 11 августа 2020

В моем решении не использовалось другое изображение Docker, как только я понял, что в основном образ для Azure функций в Docker начинается с Ubuntu. Понимая это, мой 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, а затем установите ffmpeg, как обычно в Ubuntu! Затем нужно было просто обновить код до:

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

И все!

0 голосов
/ 30 августа 2020

Я новичок ie, поэтому мое решение может не иметь эффективности. Я также столкнулся с проблемой использования FFMpegCore в контейнере do tnet core docker для создания миниатюр из видео. Это то, что я придумал в моем 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;
    }

Мне нужно чтобы загрузить его в Азурите (эмулятор для разработки локального хранилища Azure) с помощью возвращенного потока. Вы можете посмотреть документацию на FFMpegCore .

0 голосов
/ 10 августа 2020

Поскольку вы новичок в Docker. Здесь я покажу вам кое-что, что я знал.

Dockerfile предназначен для создания образа с несколькими этапами :

В многоступенчатых сборках вы используете несколько операторов FROM в вашем Dockerfile. Каждая инструкция FROM может использовать другую базу, и каждая из них начинает новый этап сборки. Вы можете выборочно копировать артефакты с одного этапа на другой, оставляя в конечном изображении все, что вам не нужно.

Из описания вам нужно знать все FROM, кроме последнего является шаблоном сборки, только полное приложение будет скопировано в последний базовый образ и запущено в нем. Так что это не перезапись, это новая рабочая среда. Вам необходимо установить все зависимости для вашего приложения в последний базовый образ, если он еще не установлен.

...