需要ffmpeg文件下載方式
可跳轉到:C#使用ffmpeg對畫面進行旋轉
更多命令可參考:https://www.cnblogs.com/zlp520/p/4241088.html
視頻添加水印命令參考自:https://www.cnblogs.com/1175429393wljblog/p/11601817.html
該幫助類加入了,截圖、獲取視頻寬高參數、加水印、視頻旋轉等基本功能。
//添加水印 ffmpeg -i "D:\VideoText\video.mp4" -i "D:\VideoText\water.png" -filter_complex overlay=10:10 "D:\VideoText\videoWater.mp4"
1 public class ffmpegHepler 2 { 3 //ffmpeg執行文件的路徑 4 private static string ffmpeg = System.AppDomain.CurrentDomain.BaseDirectory + "ffmpeg\\ffmpeg.exe"; 5 private static int? width; //視頻寬度 6 private static int? height; //視頻高度 7 8 #region 屬性訪問 9 /// <summary> 10 /// 獲取寬度 11 /// </summary> 12 /// <returns></returns> 13 public static int? GetWidth() 14 { 15 return width; 16 } 17 /// <summary> 18 /// 獲取高度 19 /// </summary> 20 /// <returns></returns> 21 public static int? GetHeight() 22 { 23 return height; 24 } 25 #endregion 26 27 #region 從視頻畫面中截取一幀畫面為圖片 28 /// <summary> 29 /// 從視頻畫面中截取一幀畫面為圖片 30 /// </summary> 31 /// <param name="VideoName">視頻文件,絕對路徑</param> 32 /// <param name="Width">圖片的寬:620</param> 33 /// <param name="Height">圖片的長:360</param> 34 /// <param name="CutTimeFrame">開始截取的時間如:"1"【單位秒】</param> 35 /// <param name="PicPath">截圖文件的保存路徑【含文件名及后綴名】</param> 36 /// <param name="SleepTime">線程掛起等待時間,單位毫秒【默認值是7000】</param> 37 /// <returns>截圖成功返回截圖路徑,失敗返回空</returns> 38 public static string GetPicFromVideo(string VideoName, int Width,int Height, string CutTimeFrame,string PicPath,int SleepTime) 39 { 40 //獲取視頻長寬尺寸 41 GetMovWidthAndHeight(VideoName); 42 if (!string.IsNullOrWhiteSpace(width.ToString())) //說明獲取到了視頻的長寬參數 43 { 44 int resultWidht; 45 int resultHeight; 46 DealWidthAndHeight(int.Parse(width.ToString()), int.Parse(height.ToString()), Width, Height, out resultWidht, out resultHeight); 47 48 System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(ffmpeg); 49 startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; 50 startInfo.Arguments = " -i " + VideoName 51 + " -y -f image2 -ss " + CutTimeFrame 52 + " -t 0.001 -s " + resultWidht.ToString() + "*" + resultHeight.ToString() 53 + " " + PicPath; //設定程式執行參數 54 try 55 { 56 System.Diagnostics.Process.Start(startInfo); 57 Thread.Sleep(SleepTime);//線程掛起,等待ffmpeg截圖完畢 58 } 59 catch (Exception e) 60 { 61 return e.Message; 62 } 63 64 //返回視頻圖片完整路徑 65 if (System.IO.File.Exists(PicPath)) 66 return PicPath; 67 return ""; 68 } 69 else 70 return ""; 71 } 72 #endregion 73 74 #region 獲取視頻的幀寬度和幀高度 75 /// <summary> 76 /// 獲取視頻的幀寬度和幀高度 77 /// </summary> 78 /// <param name="videoFilePath">mov文件的路徑</param> 79 /// <returns>null表示獲取寬度或高度失敗</returns> 80 public static void GetMovWidthAndHeight(string videoFilePath) 81 { 82 width = null; 83 height = null; 84 try 85 { 86 //判斷文件是否存在 87 if (File.Exists(videoFilePath)) 88 { 89 string output; 90 string error; 91 //執行命令 92 ExecuteCommand("\"" + ffmpeg + "\"" + " -i " + "\"" + videoFilePath + "\"", out output, out error); 93 94 if (!string.IsNullOrEmpty(error)) 95 { 96 width = null; 97 height = null; 98 99 //通過正則表達式獲取信息里面的寬度信息 100 Regex regex = new Regex("(\\d{2,4})x(\\d{2,4})", RegexOptions.Compiled); 101 Match m = regex.Match(error); 102 if (m.Success) 103 { 104 width = int.Parse(m.Groups[1].Value); 105 height = int.Parse(m.Groups[2].Value); 106 } 107 } 108 } 109 } 110 catch (Exception) 111 {} 112 } 113 #endregion 114 115 #region 處理圖片寬高比例截圖問題 116 /// <summary> 117 /// 處理圖片寬高比例截圖問題 118 /// </summary> 119 /// <param name="videoWidht">304</param> 120 /// <param name="videoHeight">640</param> 121 /// <param name="imgWidth">640</param> 122 /// <param name="imgHeight">360</param> 123 /// <param name="width">最終處理的圖片寬</param> 124 /// <param name="height">最終處理的圖片高</param> 125 private static void DealWidthAndHeight(int videoWidht,int videoHeight,int imgWidth,int imgHeight,out int width, out int height) 126 { 127 if (videoWidht < videoHeight) //說明是豎屏拍攝 128 { 129 if (imgWidth > videoWidht) 130 width = videoWidht; 131 else 132 width = imgWidth; 133 height = videoHeight; 134 } 135 else //說明是橫屏拍攝 136 { 137 if (imgHeight > videoHeight) 138 height = videoHeight; 139 else 140 height = imgHeight; 141 width = videoWidht; 142 } 143 } 144 #endregion 145 146 #region 視頻旋轉 147 /// <summary> 148 /// 視頻旋轉 149 /// </summary> 150 /// <param name="videoFilePath">視頻絕對路徑</param> 151 /// <param name="dealVideFilePath">視頻旋轉后保存路徑</param> 152 /// <param name="flag">1=順時針旋轉90度 2=逆時針旋轉90度</param> 153 /// <returns>true 成功 false 失敗</returns> 154 public static bool VideoRotate(string videoFilePath,string dealVideFilePath,string flag) 155 { 156 //ffmpeg -i success.mp4 -metadata:s:v rotate="90" -codec copy output_success.mp4 157 string output; 158 string error; 159 //執行命令 160 ExecuteCommand("\"" + ffmpeg + "\"" + " -y -i " + "\"" + videoFilePath + "\"" + " -vf transpose=" + flag + " -acodec copy " + "\"" + dealVideFilePath + "\"", out output, out error); 161 if (File.Exists(dealVideFilePath)) 162 return true; 163 else 164 return false; 165 } 166 #endregion 167 168 #region 給視頻添加水印 169 /// <summary> 170 /// 給視頻添加水印 171 /// </summary> 172 /// <param name="videoFilePath">原視頻位置</param> 173 /// <param name="dealVideFilePath">處理后的視頻位置</param> 174 /// <param name="waterPicPath">水印圖片</param> 175 /// <param name="location">水印距離視頻的左上角坐標比如: 10:10</param> 176 /// <returns></returns> 177 public static bool VideoWaterMark(string videoFilePath, string dealVideFilePath,string waterPicPath,string location) 178 { 179 //ffmpeg -i success.mp4 -metadata:s:v rotate="90" -codec copy output_success.mp4 180 string output; 181 string error; 182 //執行命令 183 ExecuteCommand("\"" + ffmpeg + "\"" + " -i " + "\"" + videoFilePath + "\"" + " -i " + "\"" + waterPicPath + "\"" + " -filter_complex overlay=" + location + " \"" + dealVideFilePath + "\"", out output, out error); 184 if (File.Exists(dealVideFilePath)) 185 return true; 186 else 187 return false; 188 } 189 #endregion 190 191 #region 讓ffmpeg執行一條命令 192 /// <summary> 193 /// 讓ffmpeg執行一條command命令 194 /// </summary> 195 /// <param name="command">需要執行的Command</param> 196 /// <param name="output">輸出</param> 197 /// <param name="error">錯誤</param> 198 private static void ExecuteCommand(string command, out string output, out string error) 199 { 200 try 201 { 202 //創建一個進程 203 Process pc = new Process(); 204 pc.StartInfo.FileName = command; 205 pc.StartInfo.UseShellExecute = false; 206 pc.StartInfo.RedirectStandardOutput = true; 207 pc.StartInfo.RedirectStandardError = true; 208 pc.StartInfo.CreateNoWindow = true; 209 210 //啟動進程 211 pc.Start(); 212 213 //准備讀出輸出流和錯誤流 214 string outputData = string.Empty; 215 string errorData = string.Empty; 216 pc.BeginOutputReadLine(); 217 pc.BeginErrorReadLine(); 218 219 pc.OutputDataReceived += (ss, ee) => 220 { 221 outputData += ee.Data; 222 }; 223 224 pc.ErrorDataReceived += (ss, ee) => 225 { 226 errorData += ee.Data; 227 }; 228 229 //等待退出 230 pc.WaitForExit(); 231 232 //關閉進程 233 pc.Close(); 234 235 //返回流結果 236 output = outputData; 237 error = errorData; 238 } 239 catch (Exception ex) 240 { 241 output = null; 242 error = null; 243 } 244 } 245 #endregion 246 }