Ubuntu .net core 中使用 ffmpeg
2022-09-14 本文已影响0人
Rinaloving
1. FfmpegHelper.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace com.uplus.ffmpeg
{
/// <summary>
/// FfmpegHelper add by cfl 2022-09-14
/// </summary>
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/local/ffmpeg/ffmpeg";
string ffprobePath = "/usr/local/ffmpeg/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/local/ffmpeg/ffmpeg";
string ffprobePath = "/usr/local/ffmpeg/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>
/// 获取视频信息 add by cfl 2022-09-14
/// </summary>
/// <param name="path"></param>
public static async Task<string> GetVideoInfo(string path)
{
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();
return InfoStr;
}
/// <summary>
/// 视频截图 add by cfl 2022-09-14
/// </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();
}
#region GetMediaTimeLenMinute (秒)
public static int GetMediaTimeLenMinute(string path)
{
int duration = 0;
string curr_duration = "00:00:00"; //视频时长,格式00:08:50
System.Diagnostics.Process cmd = new System.Diagnostics.Process();
cmd.StartInfo = cmdFfmpeg;
cmd.StartInfo.Arguments = " -i " + path;
cmd.StartInfo.RedirectStandardOutput = true;
cmd.StartInfo.UseShellExecute = false;
cmd.StartInfo.CreateNoWindow = true;
cmd.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
cmd.StartInfo.RedirectStandardError = true;
cmd.Start();
StreamReader errorreader = cmd.StandardError;
cmd.WaitForExit(1000);
string result = errorreader.ReadToEnd();
try
{
curr_duration = result.Substring(result.IndexOf("Duration: ") + ("Duration: ").Length, ("00:00:00").Length);
//do something
}
catch (Exception ex)
{
//do something
}
duration = Convert.ToInt32(curr_duration.Split(':')[0]) * 3600 + Convert.ToInt32(curr_duration.Split(':')[1]) * 60 + Convert.ToInt32(curr_duration.Split(':')[2]);
return duration;
}
#endregion
#region ConvertVideo
public static void ConvertVideo(string sourceFile, string playFile)
{
Process cmd = new Process();//建立外部调用线程
cmd.StartInfo = cmdFfmpeg;
string strArg = "-i " + sourceFile + " -y -s 640x480 " + playFile + " ";
cmd.StartInfo.Arguments = strArg;
cmd.StartInfo.UseShellExecute = false;//不使用操作系统外壳程序启动线程(一定为FALSE,详细的请看MSDN)
cmd.StartInfo.RedirectStandardError = true;//把外部程序错误输出写到StandardError流中(这个一定要注意,FFMPEG的所有输出信息,都为错误输出流,用StandardOutput是捕获不到任何消息的...这是我耗费了2个多月得出来的经验...mencoder就是用standardOutput来捕获的)
cmd.StartInfo.CreateNoWindow = false;//不创建进程窗口
cmd.ErrorDataReceived += new DataReceivedEventHandler(Output);//外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN
cmd.Start();//启动线程
cmd.BeginErrorReadLine();//开始异步读取
cmd.WaitForExit();//阻塞等待进程结束
cmd.Close();//关闭进程
cmd.Dispose();//释放资源
}
#endregion
public static void ConvertToMp4(string webRootPath, string fileName, string fName)
{
string path = $"{webRootPath}{Path.DirectorySeparatorChar}Data{Path.DirectorySeparatorChar}{fileName}";
string newPath = $"{webRootPath}{System.IO.Path.DirectorySeparatorChar}Data{System.IO.Path.DirectorySeparatorChar}{fName}.mp4";
if (!File.Exists(newPath))
{
System.Diagnostics.Process cmd = new System.Diagnostics.Process();
var startInfo = new ProcessStartInfo();
cmd.StartInfo = cmdFfmpeg;
//cmd.StartInfo.Arguments = $" -i {path} -y -s 640x480 {newPath}";
cmd.StartInfo.Arguments = $" -i {path} -movflags faststart -pix_fmt yuv420p {newPath}";
// cmd.StartInfo.Arguments = $" -i {path} -vcodec libx264 -pix_fmt yuv420p {newPath}";
//cmd.StartInfo.Arguments = $" -i {path} -c:v libx264 -mbd 0 -c:a aac -strict -2 -pix_fmt yuv420p -movflags faststart {newPath}";
cmd.StartInfo.RedirectStandardOutput = true;
cmd.StartInfo.UseShellExecute = false;
cmd.StartInfo.CreateNoWindow = true;
cmd.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
cmd.StartInfo.RedirectStandardError = true;
cmd.Start();
StreamReader errorreader = cmd.StandardError;
cmd.WaitForExit(1000);
string result = errorreader.ReadToEnd();
}
}
#region Output
private static void Output(object sendProcess, DataReceivedEventArgs output)
{
if (!String.IsNullOrEmpty(output.Data))
{
//处理方法...
//Console.WriteLine(output.Data);
////去获取时长
//string partitio1 = @"Duration: \d{2}:\d{2}:\d{2}.\d{2}";
//if (RegexHelper.IsMatch(partitio1, output.Data))
//{
// string partition = @"(?<=Duration: )\d{2}:\d{2}:\d{2}.\d{2}";
// string timespan = RegexHelper.Matchs(output.Data, partition).FirstOrDefault();
// TimeSpan span;
// if (TimeSpan.TryParse(timespan, out span))
// {
// Console.WriteLine(span.TotalMilliseconds);
// }
//}
////获取时刻
//string partitio2 = @"time=\d{2}:\d{2}:\d{2}.\d{2}";
//if (RegexHelper.IsMatch(partitio2, output.Data))
//{
// string partition = @"(?<=time=)\d{2}:\d{2}:\d{2}.\d{2}";
// string timespan = RegexHelper.Matchs(output.Data, partition).FirstOrDefault();
// TimeSpan span;
// if (TimeSpan.TryParse(timespan, out span))
// {
// Console.WriteLine(span.TotalMilliseconds);
// }
//}
}
}
#endregion
}
}
2. 调用
[HttpGet]
public ActionResult<ResponseData> GetVideoInfo(string fileName)
{
ResponseData result = new ResponseData();
try
{
int duration = FfmpegHelper.GetMediaTimeLenMinute($"{ServiceBase.Get<HostingEnvironment>().WebRootPath} {System.IO.Path.DirectorySeparatorChar}Data{System.IO.Path.DirectorySeparatorChar}{fileName}");
result.ErrorCode = 0;
result.Message = "操作成功";
result.DataList = new ModelData {
DataList = duration
};
return new JsonResult(result);
}
catch (Exception ex)
{
return this.ControllerExHandler(result, "GetVideoInfo", ex);
}
}
3. 效果:
{
"ErrorCode": 0,
"Message": "操作成功",
"Token": null,
"DataList": {
"TotalPage": 0,
"RecordCount": 0,
"Info": null,
"DataList": 185
}
}