1.资源下载
下载资源路径:http://ffmpeg.org/download.html#build-windows
https://github.com/BtbN/FFmpeg-Builds/releases
下载完成后解压,在bin目录下打开控制台,可检测下载版本或查看帮助
2.工具介绍(具体可以查看https://www.cnblogs.com/fps2tao/p/14234396.html)
ffmpeg.exe:音视频转码、转换器
ffplay.exe:简单的音视频播放器
ffserver.exe:流媒体服务器(这个下载并没有发现)
ffprobe.exe:简单的多媒体码流分析器
3.单机命令及其参数(具体可以查看https://blog.csdn.net/wangyjfrecky/article/details/81109810)
3.1音频
3.2视频
1.将视频全部转换为图片
ffmpeg.exe -i testsource/e26d801cea1f4ecab544c3bf8078c6b2.mp4 -r 1 -f image2 testsource/image-%d.jpeg
-i testsource/e26d801cea1f4ecab544c3bf8078c6b2.mp4表示指定资源地址
-r 1表示设置每秒提取一帧
-f image2表示采用的是image2格式
testsource/image-%d.jpeg表示输出地址,%d是顺序数字
2.设置截取时间和截取张数
ffmpeg.exe -i testsource/e26d801cea1f4ecab544c3bf8078c6b2.mp4 -r 1 -ss 00:00:24 -t 2 -f image2 -s 48x48 testsource/image-%d.jpeg
-ss 00:00:24表示设置起始时间
-t 2表示持续的时间 如果需要使用帧来设置持续时间可以使用 -vframes 2
-s 48x48表示设置输出图片的大小,单位像素
4.C#结合使用按钮
/// <summary> /// 根据视频截取封面(封装) /// </summary> /// <param name="ImagePath">视频路径</param> /// <param name="ScrrenTime"></param> /// <returns></returns> public static string GetScrrenImageFunc(string ImagePath, int ScrrenTime) { string ReStr = string.Empty; try { if (string.IsNullOrEmpty(ImagePath)) { return ReStr; } string ffmpeg = @"bin\ffmpeg.exe"; ffmpeg = AppDomain.CurrentDomain.BaseDirectory + ffmpeg; ProcessStartInfo startInfo = new ProcessStartInfo(ffmpeg); // 使用进程打开 startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; // 隐藏样式窗口 ReStr = GetImageNameFunc(ImagePath); startInfo.Arguments = " -i " + ImagePath + " -r 1 -ss " + GetTimeStrFunc(ScrrenTime) + " -t 1 -s 1725x975 -f image2 " + AppDomain.CurrentDomain.BaseDirectory + ReStr; Process TPHandel = new Process(); TPHandel.StartInfo = startInfo; TPHandel.Start(); TPHandel.WaitForExit(3000); } catch (Exception err) { LogHelper.Exception(typeof(LGRES_Resources), "GetScrrenImageFunc", err); LogHelper.Exception(typeof(LGRES_Resources), "打印视频路径:"+ ImagePath, new Exception("")); } return ReStr; } /// <summary> /// iis回收清除上次的进程 /// </summary> public static void FfmpegProcessKill() { foreach(Process TProcess in Process.GetProcesses()) { if (TProcess.ProcessName == "ffmpeg") { TProcess.Kill(); } } } /// <summary> /// 获取图片名称 /// </summary> /// <param name="ImagePath">资源路径</param> /// <returns></returns> private static string GetImageNameFunc(string ImagePath) { // 获取指定的名称 if (ImagePath.IndexOf("/") > -1) { string[] ImagePathArr = ImagePath.Split('/'); ImagePath = ImagePathArr[ImagePathArr.Length - 1]; } if (ImagePath.IndexOf(".") > -1) { string[] ImagePathArr = ImagePath.Split('.'); ImagePath = ImagePathArr[0]; } // 设置指定的目录 string FilePath = @"FrameImageUrl"; if (!Directory.Exists(AppDomain.CurrentDomain.BaseDirectory + FilePath)) { Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + FilePath); } return FilePath + @"\" + ImagePath + ".jpeg"; } private static Random TRandom = new Random(); /// <summary> /// 转换截取时间 /// </summary> /// <param name="ScrrenTime"></param> /// <returns></returns> private static string GetTimeStrFunc(int ScrrenTime) { if (ScrrenTime>=5000) { ScrrenTime = TRandom.Next(5000, ScrrenTime); } else { ScrrenTime = TRandom.Next(0, ScrrenTime); } string ReStr = string.Empty; // 计算时 if (ScrrenTime >= 1000 * 60 * 60) { int THours = Convert.ToInt32(Math.Floor(Convert.ToDouble(ScrrenTime) / (1000 * 60 * 60))); if (THours > 9) { ReStr += THours.ToString() + ":"; } else { ReStr += "0" + THours.ToString() + ":"; } ScrrenTime -= THours * 1000 * 60 * 60; } else { ReStr += "00:"; } // 计算分 if (ScrrenTime >= 1000 * 60) { int THours = Convert.ToInt32(Math.Floor(Convert.ToDouble(ScrrenTime) / (1000 * 60))); if (THours > 9) { ReStr += THours.ToString() + ":"; } else { ReStr += "0" + THours.ToString() + ":"; } ScrrenTime -= THours * 1000 * 60; } else { ReStr += "00:"; } // 计算秒 if (ScrrenTime >= 1000) { int THours = Convert.ToInt32(Math.Floor(Convert.ToDouble(ScrrenTime) / (1000))); if (THours > 9) { ReStr += THours.ToString() + "."; } else { ReStr += "0" + THours.ToString() + "."; } ScrrenTime -= THours * 1000; } else { ReStr += "00."; } // 计算毫秒 ReStr += ScrrenTime; return ReStr; }
Add By 2024-03-22
/** * FFmpeg静态帮助类
命令行 PS D:\下载> .\ffmpeg.exe -i '.\1.mp3' -ac 1 -ar 22050 -b:a 128k -y "2.mp3" * */ public class FFmpegHelper { /** * 重新编码处理,资源库规定资源格式: * 音频的采样率/比特率/声道: 128bit/22050hz/单声道 * 返回时长 * */ public static int getResourceFormatConversion(String resourcePathUrl,String targetPathUrl) throws Exception { String ffmpegPathUrl=PublicHelperUtil.getFilePathUrl("ffmpeg.exe"); ffmpegPathUrl = ffmpegPathUrl.replace("file:/", ""); String charSet; ProcessBuilder pb = new ProcessBuilder(); // 设置第三方应用命令 List<String> list = new ArrayList<>(); list.add(ffmpegPathUrl); list.add("-i"); list.add(resourcePathUrl); list.add("-ac"); list.add("1"); // 设置单声道 list.add("-ar"); list.add("22050"); // 设置比特率:22050hz list.add("-b:a"); list.add("128kb"); // 采样率:128bit list.add("-y"); list.add(targetPathUrl); pb.command(list); String os = System.getProperty("os.name"); if (os.toLowerCase().contains("win")) { charSet = "gbk"; } else { charSet = "utf-8"; } // 重定向错误日志信息到 inputstream,很重要,不然错误信息无法抓取到 pb.redirectErrorStream(true); Process process = pb.start(); BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream(), charSet)); String line = null; int secondNum=0; while ((line = br.readLine()) != null) { line = line.trim(); // Duration: 00:03:52.44, String tempPatterStr="Duration: ([0-9|:|\\.]*?),"; Pattern tempPatter=Pattern.compile(tempPatterStr,Pattern.DOTALL); Matcher tempMatcher=tempPatter.matcher(line); while (tempMatcher.find()){ String tempTimeStrInfo=tempMatcher.group(1); secondNum=strTimeToSecond(tempTimeStrInfo); } //System.out.println(line); } // 等待命令执行完成 int code = process.waitFor(); if (code == 0) { // 通常情况0 表示命令或者脚本正常退出,但是如果脚本自己有返回状态这里需要根据自己状态判断 System.out.println("success"); } else { System.out.println("fail,code=" + code); } return secondNum; } /** * 获取音频时长 * */ public static int getResourcePlayTime(String targetPathUrl) throws Exception { String ffmpegPathUrl=PublicHelperUtil.getFilePathUrl("ffmpeg.exe"); ffmpegPathUrl = ffmpegPathUrl.replace("file:/", ""); String charSet; ProcessBuilder pb = new ProcessBuilder(); // 设置第三方应用命令 List<String> list = new ArrayList<>(); list.add(ffmpegPathUrl); list.add("-i"); list.add(targetPathUrl); pb.command(list); String os = System.getProperty("os.name"); if (os.toLowerCase().contains("win")) { charSet = "gbk"; } else { charSet = "utf-8"; } // 重定向错误日志信息到 inputstream,很重要,不然错误信息无法抓取到 pb.redirectErrorStream(true); Process process = pb.start(); BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream(), charSet)); String line = null; int secondNum=0; while ((line = br.readLine()) != null) { line = line.trim(); // Duration: 00:03:52.44, String tempPatterStr="Duration: ([0-9|:|\\.]*?),"; Pattern tempPatter=Pattern.compile(tempPatterStr,Pattern.DOTALL); Matcher tempMatcher=tempPatter.matcher(line); while (tempMatcher.find()){ String tempTimeStrInfo=tempMatcher.group(1); secondNum=strTimeToSecond(tempTimeStrInfo); } System.out.println(line); } // 等待命令执行完成 int code = process.waitFor(); if (code == 0) { // 通常情况0 表示命令或者脚本正常退出,但是如果脚本自己有返回状态这里需要根据自己状态判断 System.out.println("success"); } else { System.out.println("fail,code=" + code); } return secondNum; } // 将String(00:03:52.44)转换成long时长 public static int strTimeToSecond(String dataStr) throws Exception { if(StringUtils.isBlank(dataStr)){ return 0; } dataStr=dataStr.split("\\.",-1)[0]; String[] hmsTimeInfos=dataStr.split(":",-1); int backTimeStamp=0; if(hmsTimeInfos.length>0){ backTimeStamp+=Integer.parseInt(hmsTimeInfos[hmsTimeInfos.length-1]); } if(hmsTimeInfos.length>1){ backTimeStamp+=Integer.parseInt(hmsTimeInfos[hmsTimeInfos.length-2])*60; } if(hmsTimeInfos.length>2){ backTimeStamp+=Integer.parseInt(hmsTimeInfos[hmsTimeInfos.length-3])*3600; } return backTimeStamp; } /* * 将秒时长转换为 HH:mm:ss * */ public String secondToStrTime(long secondNum) throws Exception { String[] tempReInfos = new String[3]; if (secondNum >= 3600) { int hourNum = (int) Math.floor((double) secondNum / 3600); if (hourNum > 9) { tempReInfos[0] = String.valueOf(hourNum); } else { tempReInfos[0] = "0" + hourNum; } secondNum -= hourNum * 3600L; } else { tempReInfos[0] = "00"; } if (secondNum >= 60) { int minutesNum = (int) Math.floor(Double.valueOf(secondNum) / 60); if (minutesNum > 9) { tempReInfos[1] = String.valueOf(minutesNum); } else { tempReInfos[1] = "0" + minutesNum; } secondNum -= minutesNum * 60L; } else { tempReInfos[1] = "00"; } if (secondNum > 9) { tempReInfos[2] = String.valueOf(secondNum); } else { tempReInfos[2] = "0" + secondNum; } return String.join(":", tempReInfos); } }
End By 2024-03-22
待续、、