星火微课系统客户端
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

FFMpeg.cs 29KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Threading;
  5. using VisioForge.Shared.NAudio.CoreAudioApi;
  6. using VisioForge.Shared.NAudio.Wave;
  7. namespace Common.system
  8. {
  9. /// <summary>
  10. /// ffmpeg帮助类
  11. /// 创建人:赵耀
  12. /// 创建时间::2020年8月22日
  13. /// 需要安装\ffmpeg\bin\Setup Screen Capturer Recorder v0.12.10.exe
  14. /// 本地调试需要配置环境变量 将ffmpeg.exe位置配置到环境变量的path中
  15. /// </summary>
  16. public class FFMpeg
  17. {
  18. public Process myProcess = null;
  19. /// <summary>
  20. /// ffmpeg输出日志文件地址 每个文件2MB左右
  21. /// </summary>
  22. string LogPath = "";
  23. /// <summary>
  24. /// 录制屏幕
  25. /// </summary>
  26. /// <param name="FilePath">文件存储路径</param>
  27. public void StartRecordingVideo(string FilePath)
  28. {
  29. while (myProcess != null)
  30. {
  31. Thread.Sleep(100);
  32. }
  33. //路径
  34. string Path = FileToolsCommon.GetDirectoryName(FilePath);
  35. string Extension = FileToolsCommon.GetIOExtension(FilePath);//扩展名
  36. //文件保存路径
  37. string PathName = GetRSFilePathName(FilePath);
  38. Process[] KillProcessArray = Process.GetProcessesByName("ffmpeg");
  39. foreach (var KillProcess in KillProcessArray)
  40. {
  41. KillProcess.Kill();
  42. }
  43. myProcess = new Process();
  44. LogPath = CreateffmpegLog();
  45. string MicrophoneName = null;
  46. string audioTestPath = FileToolsCommon.GetFileAbsolutePath("ado.m");
  47. try
  48. {
  49. FileToolsCommon.DeleteFile(audioTestPath);
  50. }
  51. catch (Exception)
  52. {
  53. }
  54. if (StartRecordAudio(audioTestPath))
  55. {
  56. MicrophoneName = GetMicrophone();
  57. }
  58. StopRecordAudio();
  59. myProcess.StartInfo.FileName = FileToolsCommon.GetFileAbsolutePath(@"/ffmpeg/bin/ffmpeg.exe"); //ffmpeg.exe的绝对路径
  60. switch (Extension.ToUpper())
  61. {
  62. case "MP4":
  63. if (string.IsNullOrWhiteSpace(MicrophoneName))
  64. {
  65. myProcess.StartInfo.Arguments = "-f dshow -i video=\"screen-capture-recorder\" -f dshow -i audio=\"virtual-audio-capturer\" -vcodec libx264 -acodec libmp3lame -r 15 -crf 22 -f avi " + PathName; //ffmpeg的参数
  66. }
  67. else
  68. {
  69. myProcess.StartInfo.Arguments = "-f dshow -i audio=\"virtual-audio-capturer\" -f dshow -i audio=\"" +
  70. MicrophoneName + "\" -filter_complex amix=inputs=2:duration=first:dropout_transition=2 -f dshow -i video=\"screen-capture-recorder\" -pix_fmt yuv420p -vcodec h264 -preset:v ultrafast -tune:v zerolatency -acodec aac -ar 44100 -ac 2 " + PathName; //ffmpeg的参数
  71. }
  72. break;
  73. case "AVI":
  74. case "FLV":
  75. if (string.IsNullOrWhiteSpace(MicrophoneName))
  76. {
  77. myProcess.StartInfo.Arguments = "-f dshow -i video=\"screen-capture-recorder\" -f dshow -i audio=\"virtual-audio-capturer\" -vcodec libx264 -acodec libmp3lame -r 15 -crf 22 -f " + Extension.ToLower() + " " + PathName; //ffmpeg的参数
  78. }
  79. else
  80. {
  81. myProcess.StartInfo.Arguments = "-f dshow -i audio=\"virtual-audio-capturer\" -f dshow -i audio=\"" +
  82. MicrophoneName + "\" -filter_complex amix=inputs=2:duration=first:dropout_transition=2 -f dshow -i video=\"screen-capture-recorder\" -pix_fmt yuv420p -vcodec h264 -preset:v ultrafast -tune:v zerolatency -acodec aac -ar 44100 -ac 2 -f " + Extension.ToLower() + " " + PathName; //ffmpeg的参数
  83. }
  84. break;
  85. default:
  86. if (string.IsNullOrWhiteSpace(MicrophoneName))
  87. {
  88. myProcess.StartInfo.Arguments = "-f dshow -i video=\"screen-capture-recorder\" -f dshow -i audio=\"virtual-audio-capturer\" -vcodec libx264 -acodec libmp3lame -r 15 -crf 22 -f avi " + PathName; //ffmpeg的参数
  89. }
  90. else
  91. {
  92. myProcess.StartInfo.Arguments = "-f dshow -i audio=\"virtual-audio-capturer\" -f dshow -i audio=\"" +
  93. MicrophoneName + "\" -filter_complex amix=inputs=2:duration=first:dropout_transition=2 -f dshow -i video=\"screen-capture-recorder\" -pix_fmt yuv420p -vcodec h264 -preset:v ultrafast -tune:v zerolatency -acodec aac -ar 44100 -ac 2 " + PathName; //ffmpeg的参数
  94. }
  95. break;
  96. }
  97. myProcess.StartInfo.UseShellExecute = false; //不使用操作系统外壳程序启动
  98. myProcess.StartInfo.RedirectStandardError = true; //重定向标准错误输出
  99. myProcess.StartInfo.CreateNoWindow = true; //不显示程序窗口
  100. myProcess.StartInfo.RedirectStandardInput = true; //用于模拟该进程控制台的输入
  101. myProcess.ErrorDataReceived += new DataReceivedEventHandler(Output);
  102. myProcess.Start();
  103. myProcess.BeginErrorReadLine();
  104. }
  105. /// <summary>
  106. /// 录制音频
  107. /// </summary>
  108. /// <param name="Mp3Path">MP3音频位置</param>
  109. public void StartRecordingAudio(string Mp3Path)
  110. {
  111. while (myProcess != null)
  112. {
  113. Thread.Sleep(100);
  114. }
  115. //路径
  116. string Path = FileToolsCommon.GetDirectoryName(Mp3Path);
  117. //文件保存路径
  118. string PathName = GetFilePathName(Mp3Path);
  119. Process[] KillProcessArray = Process.GetProcessesByName("ffmpeg");
  120. foreach (var KillProcess in KillProcessArray)
  121. {
  122. KillProcess.Kill();
  123. }
  124. myProcess = new Process();
  125. LogPath = CreateffmpegLog();
  126. this.myProcess.StartInfo.FileName = FileToolsCommon.GetFileAbsolutePath(@"/ffmpeg/bin/ffmpeg.exe"); //ffmpeg.exe的绝对路径
  127. string MicrophoneName = null;
  128. string audioTestPath = FileToolsCommon.GetFileAbsolutePath("ado.m");
  129. try
  130. {
  131. FileToolsCommon.DeleteFile(audioTestPath);
  132. }
  133. catch (Exception)
  134. {
  135. }
  136. if (StartRecordAudio(audioTestPath))
  137. {
  138. MicrophoneName = GetMicrophone();
  139. }
  140. StopRecordAudio();
  141. if (string.IsNullOrWhiteSpace(MicrophoneName))
  142. {
  143. myProcess.StartInfo.Arguments = "-f dshow -i audio=\"virtual-audio-capturer\" " + PathName;
  144. }
  145. else
  146. {
  147. myProcess.StartInfo.Arguments = "-f dshow -i audio=\"virtual-audio-capturer\" -f dshow -i audio=\"" +
  148. MicrophoneName + "\" -filter_complex amix=inputs=2:duration=first:dropout_transition=2 " + PathName;
  149. }
  150. myProcess.StartInfo.UseShellExecute = false; //不使用操作系统外壳程序启动
  151. myProcess.StartInfo.RedirectStandardError = true; //重定向标准错误输出
  152. myProcess.StartInfo.CreateNoWindow = true; //不显示程序窗口
  153. myProcess.StartInfo.RedirectStandardInput = true; //用于模拟该进程控制台的输入
  154. //外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN
  155. myProcess.ErrorDataReceived += new DataReceivedEventHandler(Output);
  156. myProcess.Start(); //启动线程
  157. myProcess.BeginErrorReadLine(); //开始异步读取
  158. }
  159. /// <summary>
  160. /// 暂停录制
  161. /// </summary>
  162. public bool SuspendFFmpeg()
  163. {
  164. if (myProcess != null)
  165. {
  166. myProcess.StandardInput.WriteLine("q");//在这个进程的控制台中模拟输入q,用于暂停录制
  167. myProcess.Close();//关闭进程
  168. myProcess.Dispose();//释放资源
  169. }
  170. #region 进程是否已经释放
  171. bool IsRunning = true;
  172. while (IsRunning)
  173. {
  174. IsRunning = false;
  175. Process[] ProcessArray = Process.GetProcessesByName("ffmpeg");
  176. foreach (var KillProcess in ProcessArray)
  177. {
  178. IsRunning = true;
  179. Thread.Sleep(100);
  180. }
  181. }
  182. #endregion
  183. myProcess = null;
  184. return true;
  185. //myProcess.Kill();
  186. }
  187. /// <summary>
  188. /// 停止录制并合成文件
  189. /// </summary>
  190. /// <param name="FilePath">文件存储路径 必须与开始时的路径完全一致</param>
  191. public bool StopFFmpeg(string FilePath)
  192. {
  193. //文件完整路径
  194. if (myProcess != null)
  195. {
  196. myProcess.StandardInput.WriteLine("q");//在这个进程的控制台中模拟输入q,用于暂停录制
  197. myProcess.Close();//关闭进程
  198. myProcess.Dispose();//释放资源
  199. }
  200. #region 进程是否已经释放
  201. bool IsRunning = true;
  202. while (IsRunning)
  203. {
  204. IsRunning = false;
  205. Process[] ProcessArray = Process.GetProcessesByName("ffmpeg");
  206. foreach (var KillProcess in ProcessArray)
  207. {
  208. IsRunning = true;
  209. Thread.Sleep(100);
  210. }
  211. }
  212. #endregion
  213. myProcess = null;
  214. Thread t1 = new Thread(MergeVideoOrAudio);
  215. t1.Start(FilePath);
  216. return true;
  217. //文件合成
  218. }
  219. /// <summary>
  220. /// 图片音频合成视频
  221. /// </summary>
  222. /// <param name="ImageListPath">图片列表位置 命名为1.png 2.png</param>
  223. /// <param name="Mp3Path">MP3音频位置</param>
  224. /// <param name="VideoSavePath">视频保存位置</param>
  225. /// <param name="Frequency">每秒帧率</param>
  226. /// <param name="VideoWidth">视频宽度</param>
  227. /// <param name="VideoHeight">视频高度</param>
  228. public void SynthesisVideo(string ImageListPath, string Mp3Path, string VideoSavePath, int Frequency, int VideoWidth, int VideoHeight)
  229. {
  230. //new Thread(new ThreadStart(new Action(() =>
  231. //{
  232. //}))).Start();
  233. while (myProcess != null)
  234. {
  235. Thread.Sleep(100);
  236. }
  237. string Extension = FileToolsCommon.GetIOExtension(VideoSavePath);//扩展名
  238. Process[] KillProcessArray = Process.GetProcessesByName("ffmpeg");
  239. //Debug.WriteLine(KillProcessArray.Length.ToString());
  240. foreach (var KillProcess in KillProcessArray)
  241. {
  242. KillProcess.Kill();
  243. }
  244. myProcess = new Process();
  245. LogPath = CreateffmpegLog();
  246. this.myProcess.StartInfo.FileName = FileToolsCommon.GetFileAbsolutePath(@"/ffmpeg/bin/ffmpeg.exe"); //ffmpeg.exe的绝对路径
  247. switch (Extension.ToUpper())
  248. {
  249. case "MP4":
  250. myProcess.StartInfo.Arguments = @"-y -r " + Frequency + " -i " +
  251. ImageListPath + @"%d.png -i " +
  252. Mp3Path + @" -s " + VideoWidth + "x" + VideoHeight + " -vcodec mpeg4 " +
  253. VideoSavePath;
  254. break;
  255. case "AVI":
  256. myProcess.StartInfo.Arguments = @"-y -r " + Frequency + " -i " +
  257. ImageListPath + @"%d.png -i " +
  258. Mp3Path + @" -s " + VideoWidth + "x" + VideoHeight + " -f AVI " +
  259. VideoSavePath;
  260. break;
  261. case "FLV":
  262. myProcess.StartInfo.Arguments = @"-y -r " + Frequency + " -i " +
  263. ImageListPath + @"%d.png -i " +
  264. Mp3Path + @" -s " + VideoWidth + "x" + VideoHeight + " -f FLV " +
  265. VideoSavePath;
  266. break;
  267. default:
  268. myProcess.StartInfo.Arguments = @"-y -r " + Frequency + " -i " +
  269. ImageListPath + @"%d.png -i " +
  270. Mp3Path + @" -s " + VideoWidth + "x" + VideoHeight + " -vcodec mpeg4 " +
  271. VideoSavePath;
  272. break;
  273. }
  274. myProcess.StartInfo.UseShellExecute = false; //不使用操作系统外壳程序启动
  275. myProcess.StartInfo.RedirectStandardError = true; //重定向标准错误输出
  276. myProcess.StartInfo.CreateNoWindow = true; //不显示程序窗口
  277. myProcess.StartInfo.RedirectStandardInput = true; //用于模拟该进程控制台的输入
  278. //外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN
  279. myProcess.ErrorDataReceived += new DataReceivedEventHandler(Output);
  280. myProcess.Start(); //启动线程
  281. myProcess.BeginErrorReadLine(); //开始异步读取
  282. myProcess.WaitForExit(); //阻塞等待进程结束
  283. myProcess.Close(); //关闭进程
  284. myProcess.Dispose(); //释放资源
  285. #region 进程是否已经释放
  286. bool IsRunning = true;
  287. while (IsRunning)
  288. {
  289. IsRunning = false;
  290. Process[] ProcessArray = Process.GetProcessesByName("ffmpeg");
  291. foreach (var KillProcess in ProcessArray)
  292. {
  293. IsRunning = true;
  294. Thread.Sleep(100);
  295. }
  296. }
  297. #endregion
  298. myProcess = null;
  299. //生成视频后删除图片和音频保存列表
  300. //FileToolsCommon.DeleteDirectory(ImageListPath);
  301. //FileToolsCommon.DeleteDirectory(FileToolsCommon.GetDirectoryName(Mp3Path));
  302. Thread.Sleep(100);
  303. FileToolsCommon.DeleteDirectory(FileToolsCommon.GetDirectoryName(VideoSavePath) + "temp");
  304. //Dispatcher.Invoke(() =>
  305. //{
  306. //});
  307. //// 允许不同线程间的调用
  308. //Control.CheckForIllegalCrossThreadCalls = false;
  309. }
  310. /// <summary>
  311. /// 视频音频合成
  312. /// </summary>
  313. /// <param name="FilePath">存储路径</param>
  314. public void MergeVideoOrAudio(object FilePathobj)
  315. {
  316. //new Thread(new ThreadStart(new Action(() =>
  317. //{
  318. //Dispatcher.Invoke(() =>
  319. //{
  320. //});
  321. //}))).Start();
  322. while (myProcess != null)
  323. {
  324. Thread.Sleep(100);
  325. }
  326. //路径
  327. string FilePath = (string)FilePathobj;
  328. string Path = FileToolsCommon.GetDirectoryName(FilePath);
  329. string Extension = FileToolsCommon.GetIOExtension(FilePath);//扩展名
  330. //Process[] KillProcessArray = Process.GetProcessesByName("ffmpeg");
  331. //foreach (var KillProcess in KillProcessArray)
  332. //{
  333. // KillProcess.Kill();
  334. //}
  335. myProcess = new Process();
  336. LogPath = CreateffmpegLog();
  337. this.myProcess.StartInfo.FileName = FileToolsCommon.GetFileAbsolutePath(@"/ffmpeg/bin/ffmpeg.exe"); //ffmpeg.exe的绝对路径
  338. if (Extension.ToUpper() == ".MP3")
  339. {
  340. myProcess.StartInfo.Arguments = "-f concat -safe 0 -i " + Path + "temp/filelist.d -c copy " + FilePath;
  341. }
  342. else
  343. {
  344. myProcess.StartInfo.Arguments = "-f concat -safe 0 -i " + Path + "temprs/filelist.d -c copy " + FilePath;
  345. }
  346. myProcess.StartInfo.UseShellExecute = false; //不使用操作系统外壳程序启动
  347. myProcess.StartInfo.RedirectStandardError = true; //重定向标准错误输出
  348. myProcess.StartInfo.CreateNoWindow = true; //不显示程序窗口
  349. myProcess.StartInfo.RedirectStandardInput = true; //用于模拟该进程控制台的输入
  350. //外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN
  351. myProcess.ErrorDataReceived += new DataReceivedEventHandler(Output);
  352. myProcess.Start(); //启动线程
  353. myProcess.BeginErrorReadLine(); //开始异步读取
  354. myProcess.WaitForExit(); //阻塞等待进程结束
  355. myProcess.Close(); //关闭进程
  356. myProcess.Dispose(); //释放资源
  357. #region 进程是否已经释放
  358. bool IsRunning = true;
  359. while (IsRunning)
  360. {
  361. IsRunning = false;
  362. Process[] ProcessArray = Process.GetProcessesByName("ffmpeg");
  363. foreach (var KillProcess in ProcessArray)
  364. {
  365. IsRunning = true;
  366. Thread.Sleep(100);
  367. }
  368. }
  369. #endregion
  370. myProcess = null;
  371. if (Extension.ToUpper() == ".MP3")
  372. {
  373. FileToolsCommon.DeleteDirectory(Path + "temp/");
  374. }
  375. else
  376. FileToolsCommon.DeleteDirectory(Path + "temprs/");
  377. }
  378. /// <summary>
  379. /// 获取文件完整路径 音频
  380. /// </summary>
  381. /// <param name="FilePath">文件路径</param>
  382. /// <returns></returns>
  383. string GetFilePathName(string FilePath)
  384. {
  385. //路径
  386. string Path = FileToolsCommon.GetDirectoryName(FilePath);
  387. //Path.GetFileName(FilePath);//获取文件名
  388. string Extension = FileToolsCommon.GetIOExtension(FilePath);//扩展名
  389. string tempFilePath = Path + "temp/";
  390. //创建临时目录
  391. FileToolsCommon.CreateDirectory(tempFilePath);
  392. //创建记录文件
  393. if (!FileToolsCommon.IsExistFile(tempFilePath + "filelist.d"))
  394. {
  395. FileToolsCommon.CreateFile(tempFilePath + "filelist.d");
  396. }
  397. int num = 1;
  398. string CompleteFilePath = tempFilePath + num + Extension;
  399. while (FileToolsCommon.IsExistFile(CompleteFilePath))
  400. {
  401. num++;
  402. CompleteFilePath = tempFilePath + num + Extension;
  403. }
  404. FileToolsCommon.AppendText(tempFilePath + "filelist.d", "file ./" + num + Extension + "\r\n");
  405. return CompleteFilePath;
  406. }
  407. /// <summary>
  408. /// 获取文件完整路径 录屏
  409. /// </summary>
  410. /// <param name="FilePath">文件路径</param>
  411. /// <returns></returns>
  412. string GetRSFilePathName(string FilePath)
  413. {
  414. //路径
  415. string Path = FileToolsCommon.GetDirectoryName(FilePath);
  416. //Path.GetFileName(FilePath);//获取文件名
  417. string Extension = FileToolsCommon.GetIOExtension(FilePath);//扩展名
  418. string tempFilePath = Path + "temprs/";
  419. //创建临时目录
  420. FileToolsCommon.CreateDirectory(tempFilePath);
  421. //创建记录文件
  422. if (!FileToolsCommon.IsExistFile(tempFilePath + "filelist.d"))
  423. {
  424. FileToolsCommon.CreateFile(tempFilePath + "filelist.d");
  425. }
  426. int num = 1;
  427. string CompleteFilePath = tempFilePath + num + Extension;
  428. while (FileToolsCommon.IsExistFile(CompleteFilePath))
  429. {
  430. num++;
  431. CompleteFilePath = tempFilePath + num + Extension;
  432. }
  433. FileToolsCommon.AppendText(tempFilePath + "filelist.d", "file ./" + num + Extension + "\r\n");
  434. return CompleteFilePath;
  435. }
  436. /// <summary>
  437. /// 生成缩略图
  438. /// </summary>
  439. /// <param name="VideoPath">视频地址</param>
  440. /// <param name="ImagePath">图片地址</param>
  441. public void GenerateThumbnails(string VideoPath, string ImagePath)
  442. {
  443. while (myProcess != null)
  444. {
  445. Thread.Sleep(100);
  446. }
  447. Process[] KillProcessArray = Process.GetProcessesByName("ffmpeg");
  448. foreach (var KillProcess in KillProcessArray)
  449. {
  450. KillProcess.Kill();
  451. }
  452. myProcess = new Process();
  453. LogPath = CreateffmpegLog();
  454. this.myProcess.StartInfo.FileName = FileToolsCommon.GetFileAbsolutePath(@"/ffmpeg/bin/ffmpeg.exe"); //ffmpeg.exe的绝对路径
  455. //myProcess.StartInfo.Arguments = "-i \"" + VideoPath + "\" -ss 1 -vframes 1 -r 1 -ac 1 -ab 2 -s " + thubWidth + "*" + thubHeight + " -f image2 \"" + ImagePath + "\"";
  456. myProcess.StartInfo.Arguments = "-i \"" + VideoPath + "\" -ss 1 -vframes 1 -r 1 -ac 1 -ab 2 -f image2 \"" + ImagePath + "\"";
  457. myProcess.StartInfo.UseShellExecute = false; //不使用操作系统外壳程序启动
  458. myProcess.StartInfo.RedirectStandardError = true; //重定向标准错误输出
  459. myProcess.StartInfo.CreateNoWindow = true; //不显示程序窗口
  460. myProcess.StartInfo.RedirectStandardInput = true; //用于模拟该进程控制台的输入
  461. //外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN
  462. myProcess.ErrorDataReceived += new DataReceivedEventHandler(Output);
  463. myProcess.Start(); //启动线程
  464. myProcess.BeginErrorReadLine(); //开始异步读取
  465. myProcess.WaitForExit(); //阻塞等待进程结束
  466. myProcess.Close(); //关闭进程
  467. myProcess.Dispose(); //释放资源
  468. #region 进程是否已经释放
  469. bool IsRunning = true;
  470. while (IsRunning)
  471. {
  472. IsRunning = false;
  473. Process[] ProcessArray = Process.GetProcessesByName("ffmpeg");
  474. foreach (var KillProcess in ProcessArray)
  475. {
  476. IsRunning = true;
  477. Thread.Sleep(100);
  478. }
  479. }
  480. #endregion
  481. myProcess = null;
  482. }
  483. /// <summary>
  484. /// 创建日志文件
  485. /// </summary>
  486. /// <returns></returns>
  487. string CreateffmpegLog()
  488. {
  489. string LogFileName = DateTime.Now.ToString("yyyyMMdd");
  490. string LogFilePath = FileToolsCommon.GetFileAbsolutePath("/Log/FFMpegLog/");
  491. FileToolsCommon.CreateDirectory(LogFilePath);
  492. string LogName = LogFilePath + LogFileName + ".log";
  493. try
  494. {
  495. if (!FileToolsCommon.IsExistFile(LogName))
  496. {
  497. FileToolsCommon.CreateFile(LogName);
  498. FileToolsCommon.AppendText(LogName, "\r\n****************************************************************************************************" +
  499. "****************************************************************************************************\r\n");
  500. return LogName;
  501. }
  502. else
  503. {
  504. int num = 0;
  505. while (FileToolsCommon.GetFileSizeByMB(LogName) > 2)
  506. {
  507. num++;
  508. LogName = LogFilePath + LogFileName + "_" + num + ".log";
  509. FileToolsCommon.CreateFile(LogName);
  510. }
  511. FileToolsCommon.AppendText(LogName, "\r\n****************************************************************************************************" +
  512. "****************************************************************************************************\r\n");
  513. return LogName;
  514. }
  515. }
  516. catch (Exception)
  517. {
  518. return LogName;
  519. }
  520. }
  521. /// <summary>
  522. /// 输出结果
  523. /// </summary>
  524. /// <param name="sendProcess"></param>
  525. /// <param name="output"></param>
  526. private void Output(object sendProcess, DataReceivedEventArgs output)
  527. {
  528. if (!String.IsNullOrEmpty(output.Data))
  529. {
  530. FileToolsCommon.AppendText(LogPath, output.Data);
  531. }
  532. }
  533. //private void P_ErrorDataReceived(object sender, DataReceivedEventArgs e)
  534. //{
  535. // //+= new DataReceivedEventHandler((s, message) => { Console.WriteLine(message.Data); })
  536. // using (StreamWriter fs = new StreamWriter("E:\\项目\\测试\\Wpf测试\\bin\\Debug\\ffmpeg\\log.txt", true))
  537. // {
  538. // fs.WriteLine(e.Data);
  539. // Debug.WriteLine(output.Data.ToString());
  540. // }
  541. //}
  542. /// <summary>
  543. /// 获取麦克风
  544. /// </summary>
  545. string GetMicrophone()
  546. {
  547. List<string> devs = new List<string>();
  548. MMDeviceEnumerator enumberator = new MMDeviceEnumerator();
  549. MMDeviceCollection deviceCollection = enumberator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.All);
  550. for (int waveInDevice = 0; waveInDevice < WaveIn.DeviceCount; waveInDevice++)
  551. {
  552. WaveInCapabilities deviceInfo = WaveIn.GetCapabilities(waveInDevice);
  553. foreach (MMDevice device in deviceCollection)
  554. {
  555. try
  556. {
  557. if (device.FriendlyName.StartsWith(deviceInfo.ProductName))
  558. {
  559. devs.Add(device.FriendlyName);
  560. break;
  561. }
  562. }
  563. catch (Exception)
  564. {
  565. }
  566. }
  567. }
  568. if (devs.Count > 0)
  569. {
  570. return devs[0];
  571. }
  572. else
  573. {
  574. return "";
  575. }
  576. }
  577. /// <summary>
  578. /// 获取麦克风列表
  579. /// </summary>
  580. public List<string> GetMicrophoneList()
  581. {
  582. List<string> devs = new List<string>();
  583. MMDeviceEnumerator enumberator = new MMDeviceEnumerator();
  584. MMDeviceCollection deviceCollection = enumberator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.All);
  585. for (int waveInDevice = 0; waveInDevice < WaveIn.DeviceCount; waveInDevice++)
  586. {
  587. WaveInCapabilities deviceInfo = WaveIn.GetCapabilities(waveInDevice);
  588. foreach (MMDevice device in deviceCollection)
  589. {
  590. try
  591. {
  592. if (device.FriendlyName.StartsWith(deviceInfo.ProductName))
  593. {
  594. devs.Add(device.FriendlyName);
  595. break;
  596. }
  597. }
  598. catch (Exception)
  599. {
  600. }
  601. }
  602. }
  603. return devs;
  604. }
  605. //录制麦克风的声音
  606. WaveInEvent waveIn = null; //new WaveInEvent();
  607. /// <summary>
  608. /// 开始录制
  609. /// </summary>
  610. public bool StartRecordAudio(string audioFile)
  611. {
  612. try
  613. {
  614. waveIn = new WaveInEvent();
  615. //生成音频文件的对象
  616. WaveFileWriter writer = new WaveFileWriter(audioFile, waveIn.WaveFormat);
  617. //开始录音,写数据
  618. waveIn.DataAvailable += (s, a) =>
  619. {
  620. writer.Write(a.Buffer, 0, a.BytesRecorded);
  621. };
  622. //结束录音
  623. waveIn.RecordingStopped += (s, a) =>
  624. {
  625. writer.Dispose();
  626. writer = null;
  627. waveIn.Dispose();
  628. };
  629. waveIn.StartRecording();
  630. return true;
  631. }
  632. catch (Exception ex)
  633. {
  634. LogHelper.WriteErrLog("【麦克风】麦克风不可用:" + ex.Message, ex);
  635. return false;
  636. }
  637. }
  638. //结束录制
  639. public void StopRecordAudio()
  640. {
  641. try
  642. {
  643. waveIn.StopRecording();
  644. }
  645. catch (Exception ex)
  646. {
  647. LogHelper.WriteErrLog("【麦克风】麦克风不可用:" + ex.Message, ex);
  648. }
  649. }
  650. }
  651. }