.net core Docker 容器添加ffmpeg 获取视频信息和截图
2024-08-23 20:33:37
最近在处理上传视频,需要获取视频信息和截图,这里就需要用到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 程序;
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(); 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(); }
}
}
最新文章
- Redis集群(八):Redis Sharding集群
- CC2530使用串口下载(SBL)
- webpack如何与gulpfile联合的使用
- 一次Debug过程的思考
- C安全编码--整数理解
- 【原创】OPA857 TEST模式使用
- django构建blog--页面部分(eclipse+pydev)
- c/c++优秀博文
- Ajax应用常见的HTTP ContentType设置
- [leetcode-623-Add One Row to Tree]
- AOP 面向切面的编程
- seo建站需要注意哪些
- 高版本Sqlserver数据库导入低版本Sqlserver
- Python的list循环遍历中,删除数据的正确方法
- System Generator 参数优化
- Node.js相关——CommonJS规范
- Jmeter 问题集
- 【数学】【P5076】 Tweetuzki 爱整除
- 如何在html中插入图片
- hp-ux 集群,内存 小记
热门文章
- 学习Vue第二节,v-cloak,v-text,v-html,v-bind,v-on使用
- hdu1074之状压dp
- Qt线程池
- Linux高性能服务器技术总结
- JavaWeb实战:报价计算系统(layui+tomcat+cookie实现)
- Java爬虫Ins博主所有帖子的点赞和评论导出excel
- Cannot parse "1986-05-04": Illegal instant due to time zone offset transition (Asia/Shanghai)
- 学习笔记:平衡树-splay
- 「雕爷学编程」Arduino动手做(39)——DS18B20温度传感器
- 王艳 201771010127《面向对象程序设计(java)》第八周学习总结