.net core Docker 容器新增ffmpeg 獲取視訊資訊和截圖

diudiu1發表於2020-06-02

最近在處理上傳視訊,需要獲取視訊資訊和截圖,這裡就需要用到ffmpeg;

由於我的專案是在docker compose中執行除錯,所以ffmpeg也需要在docker中能呼叫;

網上找到的方法在Dockerfile中安裝ffmpeg;

.net core 執行的docker容器可以理解為一個安裝了.net core runtime的輕量型linux,所以我們要在docker中呼叫ffmpeg,就需要在這個linux中安裝ffmpeg;

下面是我的Dockerfile 重點是前面的兩個RUN 命令,複製這兩個RUN 到Dockerfile就可以。(因為我還需要處理Excel所以使用了NPOI,這個linux下也是要安裝libgdiplus才能執行;)

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base

RUN sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list \
    && apt-get update \
    && apt-get install -y ffmpeg \
    && apt-get clean && apt-get autoclean && apt-get autoremove \
    && rm -rf /var/lib/apt/lists/*

RUN apt-get update && apt-get install -y libgdiplus libc6-dev && ln -s /usr/lib/libgdiplus.so /usr/lib/gdiplus.dll
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY ["test/test.csproj", "test/"]
RUN dotnet restore "test/test.csproj"
COPY . .
WORKDIR "/src/test"
RUN dotnet build "test.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "test.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
VOLUME /app/wwwroot
ENTRYPOINT ["dotnet", "test.dll"]

然後就可以使用ffmpeg 命令了,我這裡適配和window和linux 程式,---- mac還沒有試過,請忽略;

 

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace test.Ffmpeg
{
    public static class FfmpegHelper
    {
        private static System.Diagnostics.ProcessStartInfo cmdFfmpeg;
        private static System.Diagnostics.ProcessStartInfo cmdFfprobe;
        static FfmpegHelper()
        {
           
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                string ffmpegPath = "/usr/bin/ffmpeg";
                string ffprobePath = "/usr/bin/ffprobe";
                cmdFfmpeg = new System.Diagnostics.ProcessStartInfo(ffmpegPath);
                cmdFfprobe = new System.Diagnostics.ProcessStartInfo(ffprobePath);
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                string ffmpegPath = AppDomain.CurrentDomain.BaseDirectory+ "Ffmpeg\\ffmpeg.exe";
                string ffprobePath = AppDomain.CurrentDomain.BaseDirectory + "Ffmpeg\\ffprobe.exe";
                cmdFfmpeg = new System.Diagnostics.ProcessStartInfo(ffmpegPath);
                cmdFfprobe = new System.Diagnostics.ProcessStartInfo(ffprobePath);

            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                string ffmpegPath = "/usr/bin/ffmpeg";
                string ffprobePath = "/usr/bin/ffprobe";
                cmdFfmpeg = new System.Diagnostics.ProcessStartInfo(ffmpegPath);
                cmdFfprobe = new System.Diagnostics.ProcessStartInfo(ffprobePath);
            }

            cmdFfmpeg.RedirectStandardError = false; // 輸出錯誤
            cmdFfmpeg.RedirectStandardOutput = true; //輸出列印
            cmdFfmpeg.UseShellExecute = false; //使用Shell
            cmdFfmpeg.CreateNoWindow = true;  //建立黑窗


            cmdFfprobe.RedirectStandardError = false; //set false
            cmdFfprobe.RedirectStandardOutput = true;
            cmdFfprobe.UseShellExecute = false; //set true
            cmdFfprobe.CreateNoWindow = true;  //don't need the black window
        }

        /// <summary>
        /// 獲取視訊資訊
        /// </summary>
        /// <param name="path"></param>
        public static async Task<VideoInfoModel> GetVideoInfo(string path)
        {
            try
            {
                string command = $"-i {path} -print_format json -show_format -show_streams -show_data";
                cmdFfprobe.Arguments = command;

                System.Diagnostics.Process cmd = new System.Diagnostics.Process();
                cmd.StartInfo = cmdFfprobe;
                cmd.Start();

                string InfoStr = await cmd.StandardOutput.ReadToEndAsync();
                cmd.WaitForExit(10000);

                VideoInfoModel resp = JsonConvert.DeserializeObject<VideoInfoModel>(InfoStr);
                return resp;
            }
            catch (Exception)
            {
                return null;
            }
            
        }
        /// <summary>
        /// 視訊截圖
        /// </summary>
        /// <param name="path"></param>
        /// <param name="outPath"></param>
        public static void VideoScreenshot(string path,string outPath)
        {
            string command = $"-i {path} -y -q:v 7 -f image2 -t 0.001 {outPath}";
            

            cmdFfmpeg.Arguments = command;

            System.Diagnostics.Process cmd = new System.Diagnostics.Process();
            cmd.StartInfo = cmdFfmpeg;
            cmd.Start();
            cmd.WaitForExit(10000);

        }
    }
}

 

相關文章