星火微课系统客户端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

FFMpeg.cs 51KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224
  1. using AForge.Video.DirectShow;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Diagnostics;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading;
  9. using VisioForge.Shared.NAudio.CoreAudioApi;
  10. using VisioForge.Shared.NAudio.Wave;
  11. namespace Common.system
  12. {
  13. /// <summary>
  14. /// ffmpeg帮助类
  15. /// 创建人:赵耀
  16. /// 创建时间::2020年8月22日
  17. /// 需要安装\ffmpeg\bin\Setup Screen Capturer Recorder v0.12.10.exe
  18. /// 本地调试需要配置环境变量 将ffmpeg.exe位置配置到环境变量的path中
  19. /// </summary>
  20. public class FFMpeg
  21. {
  22. public Process myProcess = null;
  23. /// <summary>
  24. /// 是否输出录课录屏日志
  25. /// </summary>
  26. public bool OutputVideoLog = FileToolsCommon.GetConfigValue("OutputVideoLog") != "0";
  27. /// <summary>
  28. /// ffmpeg输出日志文件地址 每个文件2MB左右
  29. /// </summary>
  30. private string LogPath = "";
  31. /// <summary>
  32. /// 是否可以录制扬声器
  33. /// </summary>
  34. private bool IsRecordSpeaker = true;
  35. /// <summary>
  36. /// 是否可以录制麦克风
  37. /// </summary>
  38. private bool IsRecordMicrophone = true;
  39. /// <summary>
  40. /// 录制屏幕
  41. /// </summary>
  42. /// <param name="FilePath">文件存储路径</param>
  43. public void StartRecordingVideo(string FilePath)
  44. {
  45. while (myProcess != null)
  46. {
  47. Thread.Sleep(100);
  48. }
  49. //路径
  50. string Path = FileToolsCommon.GetDirectoryName(FilePath);
  51. string Extension = FileToolsCommon.GetIOExtension(FilePath);//扩展名
  52. //文件保存路径
  53. string PathName = GetRSFilePathName(FilePath);
  54. Process[] KillProcessArray = Process.GetProcessesByName("ffmpeg");
  55. foreach (Process KillProcess in KillProcessArray)
  56. {
  57. KillProcess.Kill();
  58. }
  59. myProcess = new Process();
  60. LogPath = CreateffmpegLog();
  61. string MicrophoneName = null;
  62. #region 检测麦克风扬声器
  63. string audioSpeakerPath = FileToolsCommon.GetFileAbsolutePath("adoS.m");
  64. string audioMicrophonePath = FileToolsCommon.GetFileAbsolutePath("adoM.m");
  65. try
  66. {
  67. FileToolsCommon.DeleteFile(audioSpeakerPath);
  68. FileToolsCommon.DeleteFile(audioMicrophonePath);
  69. }
  70. catch (Exception)
  71. {
  72. }
  73. if (StartRecordSpeakerAudio(audioSpeakerPath))
  74. {
  75. IsRecordSpeaker = true;
  76. }
  77. else
  78. {
  79. //无法录制扬声器音频
  80. IsRecordSpeaker = false;
  81. }
  82. StopRecordAudio(2);
  83. Thread.Sleep(100);
  84. if (StartRecordAudio(audioMicrophonePath))
  85. {
  86. IsRecordMicrophone = true;
  87. }
  88. else
  89. {
  90. //无法录制麦克风
  91. IsRecordMicrophone = false;
  92. }
  93. StopRecordAudio(1);
  94. #endregion
  95. myProcess.StartInfo.FileName = FileToolsCommon.GetFileAbsolutePath(@"/ffmpeg/bin/ffmpeg.exe"); //ffmpeg.exe的绝对路径
  96. string SpeakerStr = "";
  97. string MicrophoneStr = "";
  98. if (IsRecordSpeaker)
  99. {
  100. SpeakerStr = "-f dshow -i audio=\"virtual-audio-capturer\" ";
  101. }
  102. if (IsRecordMicrophone)
  103. {
  104. MicrophoneName = GetMicrophoneName();
  105. if (!string.IsNullOrWhiteSpace(MicrophoneName))
  106. {
  107. MicrophoneStr = "-f dshow -i audio=\"" + MicrophoneName + "\" -filter_complex amix=inputs=2:duration=first:dropout_transition=2 ";
  108. }
  109. }
  110. switch (Extension.ToUpper())
  111. {
  112. case ".MP4":
  113. myProcess.StartInfo.Arguments = SpeakerStr + MicrophoneStr + " -f gdigrab -i desktop -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -acodec aac " + PathName;
  114. //myProcess.StartInfo.Arguments = SpeakerStr + MicrophoneStr + " -f dshow -i video=\"screen-capture-recorder\" -pix_fmt yuv420p -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -acodec aac " + PathName;
  115. //if (string.IsNullOrWhiteSpace(MicrophoneName))
  116. //{
  117. // 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 " + PathName; //ffmpeg的参数
  118. //}
  119. //else
  120. //{
  121. // myProcess.StartInfo.Arguments = "-f dshow -i audio=\"virtual-audio-capturer\" -f dshow -i audio=\"" +
  122. // 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的参数
  123. //}
  124. break;
  125. case ".AVI":
  126. case ".FLV":
  127. myProcess.StartInfo.Arguments = SpeakerStr + MicrophoneStr + " -f gdigrab -i desktop -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -acodec aac -f " + Extension.ToLower().Replace(".", "") + " " + PathName;
  128. //if (string.IsNullOrWhiteSpace(MicrophoneName))
  129. //{
  130. // 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的参数
  131. //}
  132. //else
  133. //{
  134. // myProcess.StartInfo.Arguments = "-f dshow -i audio=\"virtual-audio-capturer\" -f dshow -i audio=\"" +
  135. // 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的参数
  136. //}
  137. break;
  138. default:
  139. myProcess.StartInfo.Arguments = SpeakerStr + MicrophoneStr + " -f gdigrab -i desktop -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -acodec aac " + PathName;
  140. break;
  141. }
  142. if (OutputVideoLog)
  143. {
  144. LogHelper.WriteInfoLog("【录屏】:" + myProcess.StartInfo.Arguments);
  145. }
  146. myProcess.StartInfo.UseShellExecute = false; //不使用操作系统外壳程序启动
  147. myProcess.StartInfo.RedirectStandardError = true; //重定向标准错误输出
  148. myProcess.StartInfo.CreateNoWindow = true; //不显示程序窗口
  149. myProcess.StartInfo.RedirectStandardInput = true; //用于模拟该进程控制台的输入
  150. myProcess.ErrorDataReceived += new DataReceivedEventHandler(Output);
  151. myProcess.Start();
  152. myProcess.BeginErrorReadLine();
  153. }
  154. /// <summary>
  155. /// 录制音频
  156. /// </summary>
  157. /// <param name="Mp3Path">MP3音频位置</param>
  158. public bool StartRecordingAudio(string Mp3Path)
  159. {
  160. while (myProcess != null)
  161. {
  162. Thread.Sleep(100);
  163. }
  164. //路径
  165. string Path = FileToolsCommon.GetDirectoryName(Mp3Path);
  166. //文件保存路径
  167. string PathName = GetFilePathName(Mp3Path);
  168. Process[] KillProcessArray = Process.GetProcessesByName("ffmpeg");
  169. foreach (Process KillProcess in KillProcessArray)
  170. {
  171. KillProcess.Kill();
  172. }
  173. string MicrophoneName = null;
  174. #region 检测麦克风扬声器
  175. string audioSpeakerPath = FileToolsCommon.GetFileAbsolutePath("adoS.m");
  176. string audioMicrophonePath = FileToolsCommon.GetFileAbsolutePath("adoM.m");
  177. try
  178. {
  179. FileToolsCommon.DeleteFile(audioSpeakerPath);
  180. FileToolsCommon.DeleteFile(audioMicrophonePath);
  181. }
  182. catch (Exception)
  183. {
  184. }
  185. if (StartRecordSpeakerAudio(audioSpeakerPath))
  186. {
  187. IsRecordSpeaker = true;
  188. }
  189. else
  190. {
  191. //无法录制扬声器音频
  192. IsRecordSpeaker = false;
  193. }
  194. StopRecordAudio(2);
  195. Thread.Sleep(100);
  196. if (StartRecordAudio(audioMicrophonePath))
  197. {
  198. IsRecordMicrophone = true;
  199. MicrophoneName = GetMicrophoneName();
  200. }
  201. else
  202. {
  203. //无法录制麦克风
  204. IsRecordMicrophone = false;
  205. }
  206. StopRecordAudio(1);
  207. if (!IsRecordSpeaker && !IsRecordMicrophone)
  208. {
  209. return false;
  210. }
  211. #endregion
  212. myProcess = new Process();
  213. LogPath = CreateffmpegLog();
  214. myProcess.StartInfo.FileName = FileToolsCommon.GetFileAbsolutePath(@"/ffmpeg/bin/ffmpeg.exe"); //ffmpeg.exe的绝对路径
  215. if (IsRecordSpeaker && IsRecordMicrophone)
  216. {
  217. myProcess.StartInfo.Arguments = "-f dshow -i audio=\"virtual-audio-capturer\" -f dshow -i audio=\"" +
  218. MicrophoneName + "\" -filter_complex amix=inputs=2:duration=first:dropout_transition=2 " + PathName;
  219. }
  220. else if (IsRecordSpeaker)
  221. {
  222. myProcess.StartInfo.Arguments = "-f dshow -i audio=\"virtual-audio-capturer\" " + PathName;
  223. }
  224. else if (IsRecordMicrophone)
  225. {
  226. //录制麦克风
  227. if (!string.IsNullOrWhiteSpace(MicrophoneName))
  228. {
  229. myProcess.StartInfo.Arguments = "-f dshow -i audio=\"" +
  230. MicrophoneName + "\" -filter_complex amix=inputs=2:duration=first:dropout_transition=2 " + PathName;
  231. }
  232. }
  233. if (OutputVideoLog)
  234. LogHelper.WriteInfoLog("【录音】:" + myProcess.StartInfo.Arguments);
  235. myProcess.StartInfo.UseShellExecute = false; //不使用操作系统外壳程序启动
  236. myProcess.StartInfo.RedirectStandardError = true; //重定向标准错误输出
  237. myProcess.StartInfo.CreateNoWindow = true; //不显示程序窗口
  238. myProcess.StartInfo.RedirectStandardInput = true; //用于模拟该进程控制台的输入
  239. //外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN
  240. myProcess.ErrorDataReceived += new DataReceivedEventHandler(Output);
  241. myProcess.Start(); //启动线程
  242. myProcess.BeginErrorReadLine(); //开始异步读取
  243. return true;
  244. }
  245. /// <summary>
  246. /// 暂停录制
  247. /// </summary>
  248. public bool SuspendFFmpeg()
  249. {
  250. if (myProcess != null)
  251. {
  252. myProcess.StandardInput.WriteLine("q");//在这个进程的控制台中模拟输入q,用于暂停录制
  253. myProcess.Close();//关闭进程
  254. myProcess.Dispose();//释放资源
  255. }
  256. #region 进程是否已经释放
  257. bool IsRunning = true;
  258. while (IsRunning)
  259. {
  260. IsRunning = false;
  261. Process[] ProcessArray = Process.GetProcessesByName("ffmpeg");
  262. foreach (Process KillProcess in ProcessArray)
  263. {
  264. IsRunning = true;
  265. Thread.Sleep(100);
  266. }
  267. }
  268. #endregion
  269. myProcess = null;
  270. return true;
  271. //myProcess.Kill();
  272. }
  273. /// <summary>
  274. /// 停止录制并合成文件
  275. /// </summary>
  276. /// <param name="FilePath">文件存储路径 必须与开始时的路径完全一致</param>
  277. public bool StopFFmpeg(string FilePath)
  278. {
  279. //文件完整路径
  280. if (myProcess != null)
  281. {
  282. myProcess.StandardInput.WriteLine("q");//在这个进程的控制台中模拟输入q,用于暂停录制
  283. myProcess.Close();//关闭进程
  284. myProcess.Dispose();//释放资源
  285. }
  286. #region 进程是否已经释放
  287. bool IsRunning = true;
  288. while (IsRunning)
  289. {
  290. IsRunning = false;
  291. Process[] ProcessArray = Process.GetProcessesByName("ffmpeg");
  292. foreach (Process KillProcess in ProcessArray)
  293. {
  294. IsRunning = true;
  295. Thread.Sleep(100);
  296. }
  297. }
  298. #endregion
  299. myProcess = null;
  300. Thread t1 = new Thread(MergeVideoOrAudio);
  301. t1.Start(FilePath);
  302. return true;
  303. //文件合成
  304. }
  305. /// <summary>
  306. /// 图片音频合成视频
  307. /// </summary>
  308. /// <param name="ImageListPath">图片列表位置 命名为1.png 2.png</param>
  309. /// <param name="Mp3Path">MP3音频位置</param>
  310. /// <param name="VideoSavePath">视频保存位置</param>
  311. /// <param name="Frequency">每秒帧率</param>
  312. /// <param name="VideoWidth">视频宽度</param>
  313. /// <param name="VideoHeight">视频高度</param>
  314. public bool SynthesisVideo(string ImageListPath, string Mp3Path, string VideoSavePath, int Frequency, int VideoWidth, int VideoHeight)
  315. {
  316. //new Thread(new ThreadStart(new Action(() =>
  317. //{
  318. //}))).Start();
  319. while (myProcess != null)
  320. {
  321. Thread.Sleep(100);
  322. }
  323. string Extension = FileToolsCommon.GetIOExtension(VideoSavePath);//扩展名
  324. Process[] KillProcessArray = Process.GetProcessesByName("ffmpeg");
  325. //Debug.WriteLine(KillProcessArray.Length.ToString());
  326. foreach (Process KillProcess in KillProcessArray)
  327. {
  328. KillProcess.Kill();
  329. }
  330. myProcess = new Process();
  331. try
  332. {
  333. LogPath = CreateffmpegLog();
  334. string mp3Str = "";
  335. #region 判断音频是否存在
  336. if (!string.IsNullOrWhiteSpace(Mp3Path))
  337. {
  338. if (FileToolsCommon.IsExistFile(Mp3Path))
  339. {
  340. mp3Str = "-i " + Mp3Path;
  341. }
  342. }
  343. #endregion
  344. myProcess.StartInfo.FileName = FileToolsCommon.GetFileAbsolutePath(@"/ffmpeg/bin/ffmpeg.exe"); //ffmpeg.exe的绝对路径
  345. switch (Extension.ToUpper())
  346. {
  347. case ".MP4":
  348. myProcess.StartInfo.Arguments = @"-y -r " + Frequency + " -i " +
  349. ImageListPath + @"%d.png " +
  350. mp3Str + @" -s " + VideoWidth + "x" + VideoHeight + " -vcodec mpeg4 " +
  351. VideoSavePath;
  352. break;
  353. case ".AVI":
  354. myProcess.StartInfo.Arguments = @"-y -r " + Frequency + " -i " +
  355. ImageListPath + @"%d.png " +
  356. mp3Str + @" -s " + VideoWidth + "x" + VideoHeight + " -f AVI " +
  357. VideoSavePath;
  358. break;
  359. case ".FLV":
  360. myProcess.StartInfo.Arguments = @"-y -r " + Frequency + " -i " +
  361. ImageListPath + @"%d.png " +
  362. mp3Str + @" -s " + VideoWidth + "x" + VideoHeight + " -f FLV " +
  363. VideoSavePath;
  364. break;
  365. default:
  366. myProcess.StartInfo.Arguments = @"-y -r " + Frequency + " -i " +
  367. ImageListPath + @"%d.png " +
  368. mp3Str + @" -s " + VideoWidth + "x" + VideoHeight + " -vcodec mpeg4 " +
  369. VideoSavePath;
  370. break;
  371. }
  372. if (OutputVideoLog)
  373. LogHelper.WriteInfoLog("【图片音频合成视频】:" + myProcess.StartInfo.Arguments);
  374. myProcess.StartInfo.UseShellExecute = false; //不使用操作系统外壳程序启动
  375. myProcess.StartInfo.RedirectStandardError = true; //重定向标准错误输出
  376. myProcess.StartInfo.CreateNoWindow = true; //不显示程序窗口
  377. myProcess.StartInfo.RedirectStandardInput = true; //用于模拟该进程控制台的输入
  378. //外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN
  379. myProcess.ErrorDataReceived += new DataReceivedEventHandler(Output);
  380. myProcess.Start(); //启动线程
  381. myProcess.BeginErrorReadLine(); //开始异步读取
  382. myProcess.WaitForExit(); //阻塞等待进程结束
  383. myProcess.Close(); //关闭进程
  384. myProcess.Dispose(); //释放资源
  385. #region 进程是否已经释放
  386. bool IsRunning = true;
  387. while (IsRunning)
  388. {
  389. IsRunning = false;
  390. Process[] ProcessArray = Process.GetProcessesByName("ffmpeg");
  391. foreach (Process KillProcess in ProcessArray)
  392. {
  393. IsRunning = true;
  394. Thread.Sleep(100);
  395. }
  396. }
  397. #endregion
  398. myProcess = null;
  399. //生成视频后删除图片和音频保存列表
  400. //FileToolsCommon.DeleteDirectory(ImageListPath);
  401. //FileToolsCommon.DeleteDirectory(FileToolsCommon.GetDirectoryName(Mp3Path));
  402. Thread.Sleep(100);
  403. FileToolsCommon.DeleteDirectory(FileToolsCommon.GetDirectoryName(VideoSavePath) + "temp");
  404. return true;
  405. }
  406. catch (Exception ex)
  407. {
  408. LogHelper.WriteErrLog("【视频合成】(SynthesisVideo)视频生成失败," + ex.Message, ex);
  409. return false;
  410. }
  411. //Dispatcher.Invoke(() =>
  412. //{
  413. //});
  414. //// 允许不同线程间的调用
  415. //Control.CheckForIllegalCrossThreadCalls = false;
  416. }
  417. /// <summary>
  418. /// 视频音频合成
  419. /// </summary>
  420. /// <param name="FilePath">存储路径</param>
  421. public void MergeVideoOrAudio(object FilePathobj)
  422. {
  423. //new Thread(new ThreadStart(new Action(() =>
  424. //{
  425. //Dispatcher.Invoke(() =>
  426. //{
  427. //});
  428. //}))).Start();
  429. while (myProcess != null)
  430. {
  431. Thread.Sleep(100);
  432. }
  433. //路径
  434. string FilePath = (string)FilePathobj;
  435. string Path = FileToolsCommon.GetDirectoryName(FilePath);
  436. //扩展名
  437. string Extension = FileToolsCommon.GetIOExtension(FilePath);
  438. //Process[] KillProcessArray = Process.GetProcessesByName("ffmpeg");
  439. //foreach (var KillProcess in KillProcessArray)
  440. //{
  441. // KillProcess.Kill();
  442. //}
  443. #region 判断文件是否存在
  444. if (Extension.ToUpper() == ".MP3")
  445. {
  446. if (!FileToolsCommon.IsExistFile(Path + "temp/filelist.d"))
  447. {
  448. return;
  449. }
  450. }
  451. else
  452. {
  453. if (!FileToolsCommon.IsExistFile(Path + "temprs/filelist.d"))
  454. {
  455. return;
  456. }
  457. }
  458. #endregion
  459. myProcess = new Process();
  460. LogPath = CreateffmpegLog();
  461. myProcess.StartInfo.FileName = FileToolsCommon.GetFileAbsolutePath(@"/ffmpeg/bin/ffmpeg.exe"); //ffmpeg.exe的绝对路径
  462. if (Extension.ToUpper() == ".MP3")
  463. {
  464. myProcess.StartInfo.Arguments = "-f concat -safe 0 -i " + Path + "temp/filelist.d -c copy " + FilePath;
  465. }
  466. else
  467. {
  468. myProcess.StartInfo.Arguments = "-f concat -safe 0 -i " + Path + "temprs/filelist.d -c copy " + FilePath;
  469. }
  470. if (OutputVideoLog)
  471. LogHelper.WriteInfoLog("【音视频合成】:" + myProcess.StartInfo.Arguments);
  472. myProcess.StartInfo.UseShellExecute = false; //不使用操作系统外壳程序启动
  473. myProcess.StartInfo.RedirectStandardError = true; //重定向标准错误输出
  474. myProcess.StartInfo.CreateNoWindow = true; //不显示程序窗口
  475. myProcess.StartInfo.RedirectStandardInput = true; //用于模拟该进程控制台的输入
  476. //外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN
  477. myProcess.ErrorDataReceived += new DataReceivedEventHandler(Output);
  478. myProcess.Start(); //启动线程
  479. myProcess.BeginErrorReadLine(); //开始异步读取
  480. myProcess.WaitForExit(); //阻塞等待进程结束
  481. myProcess.Close(); //关闭进程
  482. myProcess.Dispose(); //释放资源
  483. #region 进程是否已经释放
  484. bool IsRunning = true;
  485. while (IsRunning)
  486. {
  487. IsRunning = false;
  488. Process[] ProcessArray = Process.GetProcessesByName("ffmpeg");
  489. foreach (Process KillProcess in ProcessArray)
  490. {
  491. IsRunning = true;
  492. Thread.Sleep(100);
  493. }
  494. }
  495. #endregion
  496. myProcess = null;
  497. if (Extension.ToUpper() == ".MP3")
  498. {
  499. FileToolsCommon.DeleteDirectory(Path + "temp/");
  500. }
  501. else
  502. {
  503. FileToolsCommon.DeleteDirectory(Path + "temprs/");
  504. }
  505. }
  506. /// <summary>
  507. /// 获取文件完整路径 音频
  508. /// </summary>
  509. /// <param name="FilePath">文件路径</param>
  510. /// <returns></returns>
  511. private string GetFilePathName(string FilePath)
  512. {
  513. //路径
  514. string Path = FileToolsCommon.GetDirectoryName(FilePath);
  515. //Path.GetFileName(FilePath);//获取文件名
  516. string Extension = FileToolsCommon.GetIOExtension(FilePath);//扩展名
  517. string tempFilePath = Path + "temp/";
  518. //创建临时目录
  519. FileToolsCommon.CreateDirectory(tempFilePath);
  520. //创建记录文件
  521. if (!FileToolsCommon.IsExistFile(tempFilePath + "filelist.d"))
  522. {
  523. FileToolsCommon.CreateFile(tempFilePath + "filelist.d");
  524. }
  525. int num = 1;
  526. string CompleteFilePath = tempFilePath + num + Extension;
  527. while (FileToolsCommon.IsExistFile(CompleteFilePath))
  528. {
  529. num++;
  530. CompleteFilePath = tempFilePath + num + Extension;
  531. }
  532. FileToolsCommon.AppendText(tempFilePath + "filelist.d", "file ./" + num + Extension + "\r\n");
  533. return CompleteFilePath;
  534. }
  535. /// <summary>
  536. /// 获取文件完整路径 录屏
  537. /// </summary>
  538. /// <param name="FilePath">文件路径</param>
  539. /// <returns></returns>
  540. private string GetRSFilePathName(string FilePath)
  541. {
  542. //路径
  543. string Path = FileToolsCommon.GetDirectoryName(FilePath);
  544. //Path.GetFileName(FilePath);//获取文件名
  545. string Extension = FileToolsCommon.GetIOExtension(FilePath);//扩展名
  546. string tempFilePath = Path + "temprs/";
  547. //创建临时目录
  548. FileToolsCommon.CreateDirectory(tempFilePath);
  549. //创建记录文件
  550. if (!FileToolsCommon.IsExistFile(tempFilePath + "filelist.d"))
  551. {
  552. FileToolsCommon.CreateFile(tempFilePath + "filelist.d");
  553. }
  554. int num = 1;
  555. string CompleteFilePath = tempFilePath + num + Extension;
  556. while (FileToolsCommon.IsExistFile(CompleteFilePath))
  557. {
  558. num++;
  559. CompleteFilePath = tempFilePath + num + Extension;
  560. }
  561. FileToolsCommon.AppendText(tempFilePath + "filelist.d", "file ./" + num + Extension + "\r\n");
  562. return CompleteFilePath;
  563. }
  564. /// <summary>
  565. /// 生成缩略图
  566. /// </summary>
  567. /// <param name="VideoPath">视频地址</param>
  568. /// <param name="ImagePath">图片地址</param>
  569. /// <param name="Width">图片大小</param>
  570. /// <param name="Height">图片大小</param>
  571. public bool GenerateThumbnails(string VideoPath, string ImagePath,int Width=0,int Height=0)
  572. {
  573. while (myProcess != null)
  574. {
  575. Thread.Sleep(100);
  576. }
  577. Process[] KillProcessArray = Process.GetProcessesByName("ffmpeg");
  578. foreach (Process KillProcess in KillProcessArray)
  579. {
  580. KillProcess.Kill();
  581. }
  582. string WHStr = "";
  583. if(Width>0)
  584. {
  585. WHStr = " -s "+ Width + "x"+ Height;
  586. }
  587. try
  588. {
  589. myProcess = new Process();
  590. LogPath = CreateffmpegLog();
  591. myProcess.StartInfo.FileName = FileToolsCommon.GetFileAbsolutePath(@"/ffmpeg/bin/ffmpeg.exe"); //ffmpeg.exe的绝对路径
  592. //myProcess.StartInfo.Arguments = "-i \"" + VideoPath + "\" -ss 1 -vframes 1 -r 1 -ac 1 -ab 2 -s " + thubWidth + "*" + thubHeight + " -f image2 \"" + ImagePath + "\"";
  593. myProcess.StartInfo.Arguments = "-i \"" + VideoPath + "\" -ss 1 -vframes 1 -r 1 -ac 1 -ab 2"+ WHStr + " -f image2 \"" + ImagePath + "\"";
  594. if (OutputVideoLog)
  595. LogHelper.WriteInfoLog("【生成缩略图】:" + myProcess.StartInfo.Arguments);
  596. myProcess.StartInfo.UseShellExecute = false; //不使用操作系统外壳程序启动
  597. myProcess.StartInfo.RedirectStandardError = true; //重定向标准错误输出
  598. myProcess.StartInfo.CreateNoWindow = true; //不显示程序窗口
  599. myProcess.StartInfo.RedirectStandardInput = true; //用于模拟该进程控制台的输入
  600. //外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN
  601. myProcess.ErrorDataReceived += new DataReceivedEventHandler(Output);
  602. myProcess.Start(); //启动线程
  603. myProcess.BeginErrorReadLine(); //开始异步读取
  604. myProcess.WaitForExit(); //阻塞等待进程结束
  605. myProcess.Close(); //关闭进程
  606. myProcess.Dispose(); //释放资源
  607. #region 进程是否已经释放
  608. bool IsRunning = true;
  609. while (IsRunning)
  610. {
  611. IsRunning = false;
  612. Process[] ProcessArray = Process.GetProcessesByName("ffmpeg");
  613. foreach (Process KillProcess in ProcessArray)
  614. {
  615. IsRunning = true;
  616. Thread.Sleep(100);
  617. }
  618. }
  619. #endregion
  620. myProcess = null;
  621. return true;
  622. }
  623. catch (Exception ex)
  624. {
  625. LogHelper.WriteErrLog("【生成缩略图】(GenerateThumbnails)缩略图生成失败," + ex.Message, ex);
  626. return false;
  627. }
  628. }
  629. /// <summary>
  630. /// 视频转码
  631. /// </summary>
  632. /// <param name="VideoPathName">源视频</param>
  633. /// <param name="VideoSavePathName">目标视频存储路径</param>
  634. /// <param name="Width">宽</param>
  635. /// <param name="Height">高</param>
  636. /// <returns></returns>
  637. public bool VideoTranscode(string VideoPathName, string VideoSavePathName, int Width, int Height)
  638. {
  639. while (myProcess != null)
  640. {
  641. Thread.Sleep(100);
  642. }
  643. Process[] KillProcessArray = Process.GetProcessesByName("ffmpeg");
  644. foreach (Process KillProcess in KillProcessArray)
  645. {
  646. KillProcess.Kill();
  647. }
  648. try
  649. {
  650. myProcess = new Process();
  651. LogPath = CreateffmpegLog();
  652. myProcess.StartInfo.FileName = FileToolsCommon.GetFileAbsolutePath(@"/ffmpeg/bin/ffmpeg.exe"); //ffmpeg.exe的绝对路径
  653. myProcess.StartInfo.Arguments = "-i " + VideoPathName + " -acodec copy -vcodec libx264 -s " + Width + "*" + Height + " " + VideoSavePathName;
  654. if (OutputVideoLog)
  655. LogHelper.WriteInfoLog("【视频转码】:" + myProcess.StartInfo.Arguments);
  656. myProcess.StartInfo.UseShellExecute = false; //不使用操作系统外壳程序启动
  657. myProcess.StartInfo.RedirectStandardError = true; //重定向标准错误输出
  658. myProcess.StartInfo.CreateNoWindow = true; //不显示程序窗口
  659. myProcess.StartInfo.RedirectStandardInput = true; //用于模拟该进程控制台的输入
  660. //外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN
  661. myProcess.ErrorDataReceived += new DataReceivedEventHandler(Output);
  662. myProcess.Start(); //启动线程
  663. myProcess.BeginErrorReadLine(); //开始异步读取
  664. myProcess.WaitForExit(); //阻塞等待进程结束
  665. myProcess.Close(); //关闭进程
  666. myProcess.Dispose(); //释放资源
  667. #region 进程是否已经释放
  668. bool IsRunning = true;
  669. while (IsRunning)
  670. {
  671. IsRunning = false;
  672. Process[] ProcessArray = Process.GetProcessesByName("ffmpeg");
  673. foreach (Process KillProcess in ProcessArray)
  674. {
  675. IsRunning = true;
  676. Thread.Sleep(100);
  677. }
  678. }
  679. #endregion
  680. myProcess = null;
  681. Thread.Sleep(200);
  682. FileToolsCommon.DeleteFile(VideoPathName);
  683. return true;
  684. }
  685. catch (Exception ex)
  686. {
  687. LogHelper.WriteErrLog("【视频转码】(VideoTranscode)视频转码失败," + ex.Message, ex);
  688. return false;
  689. }
  690. }
  691. /// <summary>
  692. /// 创建日志文件
  693. /// </summary>
  694. /// <returns></returns>
  695. private string CreateffmpegLog()
  696. {
  697. string LogFileName = DateTime.Now.ToString("yyyyMMdd");
  698. string LogFilePath = FileToolsCommon.GetFileAbsolutePath("/Log/FFMpegLog/");
  699. FileToolsCommon.CreateDirectory(LogFilePath);
  700. string LogName = LogFilePath + LogFileName + ".log";
  701. try
  702. {
  703. if (!FileToolsCommon.IsExistFile(LogName))
  704. {
  705. FileToolsCommon.CreateFile(LogName);
  706. FileToolsCommon.AppendText(LogName, "\r\n****************************************************************************************************" +
  707. "****************************************************************************************************\r\n");
  708. return LogName;
  709. }
  710. else
  711. {
  712. int num = 0;
  713. while (FileToolsCommon.GetFileSizeByMB(LogName) > 2)
  714. {
  715. num++;
  716. LogName = LogFilePath + LogFileName + "_" + num + ".log";
  717. FileToolsCommon.CreateFile(LogName);
  718. }
  719. FileToolsCommon.AppendText(LogName, "\r\n****************************************************************************************************" +
  720. "****************************************************************************************************\r\n");
  721. return LogName;
  722. }
  723. }
  724. catch (Exception)
  725. {
  726. return LogName;
  727. }
  728. }
  729. /// <summary>
  730. /// 输出结果
  731. /// </summary>
  732. /// <param name="sendProcess"></param>
  733. /// <param name="output"></param>
  734. private void Output(object sendProcess, DataReceivedEventArgs output)
  735. {
  736. if (!string.IsNullOrEmpty(output.Data))
  737. {
  738. FileToolsCommon.AppendText(LogPath, output.Data);
  739. }
  740. }
  741. #region 麦克风声卡检测
  742. #region 获取麦克风
  743. bool IsMicrophone = false;
  744. /// <summary>
  745. /// 使用FFmpeg获取的麦克风名
  746. /// </summary>
  747. string MicrophoneNameInfo = "";
  748. /// <summary>
  749. /// 获取麦克风名称
  750. /// </summary>
  751. /// <returns></returns>
  752. public string GetMicrophoneName()
  753. {
  754. return GetAudioInDevices();
  755. //string FullName = GetInDeviceFull();
  756. //if(string.IsNullOrWhiteSpace(MicrophoneNameInfo))
  757. //{
  758. // return FullName;
  759. //}
  760. ////byte[] bufferASCII = Encoding.Default.GetBytes(MicrophoneNameInfo);
  761. ////string str = Encoding.UTF8.GetString(bufferASCII);
  762. ////str = str.Replace("?", " ");
  763. ////int num = str.Length;
  764. ////int num1 = FullName.Length;
  765. //if (FullName.Contains("(") || FullName.Contains("("))
  766. //{
  767. // string EName = FullName.Substring(FullName.IndexOf("(")+1);
  768. // if(string.IsNullOrEmpty(EName))
  769. // {
  770. // EName = FullName.Substring(FullName.IndexOf("(") + 1);
  771. // EName = EName.Substring(0, EName.LastIndexOf(")"));
  772. // }
  773. // else
  774. // {
  775. // //EName = EName.Substring(0, EName.LastIndexOf(")"));
  776. // }
  777. // if(MicrophoneNameInfo.Contains(EName))
  778. // {
  779. // return FullName;
  780. // }
  781. // else
  782. // {
  783. // return GetInDeviceName();
  784. // }
  785. //}
  786. //else
  787. //{
  788. // return FullName;
  789. //}
  790. }
  791. /// <summary>
  792. /// 使用FFmpeg获取设备名称--待定
  793. /// </summary>
  794. public void GetMToFFmpeg()
  795. {
  796. return;
  797. new Thread(new ThreadStart(new Action(() =>
  798. {
  799. try
  800. {
  801. while (myProcess != null)
  802. {
  803. Thread.Sleep(100);
  804. }
  805. myProcess = new Process();
  806. LogPath = CreateffmpegLog();
  807. myProcess.StartInfo.FileName = FileToolsCommon.GetFileAbsolutePath(@"/ffmpeg/bin/ffmpeg.exe"); //ffmpeg.exe的绝对路径
  808. myProcess.StartInfo.Arguments = " -list_devices true -f dshow -i dummy";
  809. if (OutputVideoLog)
  810. LogHelper.WriteInfoLog("【音视频合成】:" + myProcess.StartInfo.Arguments);
  811. myProcess.StartInfo.UseShellExecute = false; //不使用操作系统外壳程序启动
  812. myProcess.StartInfo.RedirectStandardError = true; //重定向标准错误输出
  813. myProcess.StartInfo.CreateNoWindow = true; //不显示程序窗口
  814. myProcess.StartInfo.RedirectStandardInput = true; //用于模拟该进程控制台的输入
  815. //外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN
  816. myProcess.ErrorDataReceived += GetDevInfoData;
  817. myProcess.Start(); //启动线程
  818. myProcess.BeginErrorReadLine(); //开始异步读取
  819. myProcess.WaitForExit(); //阻塞等待进程结束
  820. myProcess.Close(); //关闭进程
  821. myProcess.Dispose(); //释放资源
  822. myProcess = null;
  823. }
  824. catch (Exception ex)
  825. {
  826. LogHelper.WriteErrLog("【获取设备信息】(GetMToFFmpeg)信息获取失败:" + ex.Message, ex);
  827. }
  828. }))).Start();
  829. }
  830. /// <summary>
  831. /// 使用FFmpeg获取设备名称--待定
  832. /// </summary>
  833. /// <param name="sender"></param>
  834. /// <param name="e"></param>
  835. private void GetDevInfoData(object sender, DataReceivedEventArgs e)
  836. {
  837. if (!string.IsNullOrEmpty(e.Data))
  838. {
  839. if (IsMicrophone)
  840. {
  841. try
  842. {
  843. MicrophoneNameInfo = e.Data;
  844. MicrophoneNameInfo = MicrophoneNameInfo.Substring(MicrophoneNameInfo.IndexOf("]") + 1);
  845. MicrophoneNameInfo = MicrophoneNameInfo.Replace("\"", "");
  846. MicrophoneNameInfo = MicrophoneNameInfo.Trim();
  847. #region 测试
  848. //byte[] bufferASCII = Encoding.Default.GetBytes(MicrophoneNameInfo);
  849. //MicrophoneNameInfo = Encoding.UTF8.GetString(bufferASCII); // 统一使用UTF-8
  850. ////System.Text.Encoding GB2312 = System.Text.Encoding.GetEncoding("GB2312");
  851. ////byte[] gb = GB2312.GetBytes(MicrophoneNameInfo);
  852. ////MicrophoneNameInfo = Encoding.UTF8.GetString(gb);
  853. #endregion
  854. IsMicrophone = false;
  855. FileToolsCommon.AppendText(LogPath, e.Data);
  856. //FileToolsCommon.AppendText(LogPath, "\r\n***************************************************\r\n");
  857. }
  858. catch (Exception ex)
  859. {
  860. LogHelper.WriteErrLog("【获取设备信息】(GetDevInfoData)信息获取失败:" + ex.Message, ex);
  861. }
  862. }
  863. else
  864. {
  865. if (e.Data.Contains("DirectShow audio devices"))
  866. {
  867. //FileToolsCommon.AppendText(LogPath, "\r\n***************************************************\r\n");
  868. IsMicrophone = true;
  869. }
  870. FileToolsCommon.AppendText(LogPath, e.Data);
  871. FileToolsCommon.AppendText(LogPath, "\r\n");
  872. }
  873. }
  874. }
  875. /// <summary>
  876. /// AForge获取麦克风
  877. /// </summary>
  878. /// <returns></returns>
  879. public static string GetAudioInDevices()
  880. {
  881. List<string> devicesList = new List<string>();
  882. try
  883. {
  884. var videoDevices = new FilterInfoCollection(FilterCategory.AudioInputDevice);
  885. foreach (FilterInfo device in videoDevices)
  886. {
  887. devicesList.Add(device.Name);
  888. }
  889. }
  890. catch (ApplicationException)
  891. {
  892. //Console.WriteLine("No local capture devices");
  893. }
  894. if (devicesList.Count > 1)
  895. {
  896. return devicesList[1];
  897. }
  898. else
  899. {
  900. return "";
  901. }
  902. }
  903. /// <summary>
  904. /// AForge获取麦克风列表
  905. /// </summary>
  906. /// <returns></returns>
  907. public static List<string> GetAudioInDevicesList()
  908. {
  909. List<string> devicesList = new List<string>();
  910. try
  911. {
  912. var videoDevices = new FilterInfoCollection(FilterCategory.AudioInputDevice);
  913. foreach (FilterInfo device in videoDevices)
  914. {
  915. devicesList.Add(device.Name);
  916. }
  917. }
  918. catch (ApplicationException)
  919. {
  920. Console.WriteLine("No local capture devices");
  921. }
  922. return devicesList;
  923. }
  924. /// <summary>
  925. /// 获取声音输入设备名称 不完整
  926. /// </summary>
  927. /// <returns></returns>
  928. public static string GetInDeviceName()
  929. {
  930. var devices = new List<WaveInCapabilities>();
  931. int waveInDevices = WaveIn.DeviceCount;
  932. for (int i = 0; i < waveInDevices; i++)
  933. {
  934. devices.Add(WaveIn.GetCapabilities(i));
  935. }
  936. List<string> devs = new List<string>();
  937. devs = devices.Select(item => item.ProductName).ToList();
  938. if (devs.Count > 0)
  939. {
  940. byte[] buffer = Encoding.UTF8.GetBytes(devs[0]);
  941. string MicrophoneName = Encoding.UTF8.GetString(buffer); // 统一使用UTF-8
  942. return MicrophoneName;
  943. }
  944. else
  945. {
  946. return "";
  947. }
  948. }
  949. /// <summary>
  950. /// 获取声音输入设备完整名称
  951. /// </summary>
  952. /// <returns></returns>
  953. public static string GetInDeviceFull()
  954. {
  955. List<string> devices = new List<string>();
  956. var enumberator = new MMDeviceEnumerator();
  957. var deviceCollection = enumberator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.All);
  958. for (int waveInDevice = 0; waveInDevice < WaveIn.DeviceCount; waveInDevice++)
  959. {
  960. WaveInCapabilities deviceInfo = WaveIn.GetCapabilities(waveInDevice);
  961. foreach (MMDevice device in deviceCollection)
  962. {
  963. try
  964. {
  965. if (device.FriendlyName.StartsWith(deviceInfo.ProductName))
  966. {
  967. devices.Add(device.FriendlyName);
  968. break;
  969. }
  970. }
  971. catch (Exception ex)
  972. {
  973. continue;
  974. }
  975. }
  976. }
  977. if (devices.Count > 0)
  978. {
  979. byte[] buffer = Encoding.UTF8.GetBytes(devices[0]);
  980. string MicrophoneName = Encoding.UTF8.GetString(buffer); // 统一使用UTF-8
  981. return MicrophoneName;
  982. }
  983. else
  984. {
  985. return "";
  986. }
  987. }
  988. /// <summary>
  989. /// 获取声音输入设备完整名称列表
  990. /// </summary>
  991. /// <returns></returns>
  992. public List<string> GetInDeviceListFull()
  993. {
  994. List<string> devices = new List<string>();
  995. var enumberator = new MMDeviceEnumerator();
  996. var deviceCollection = enumberator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.All);
  997. for (int waveInDevice = 0; waveInDevice < WaveIn.DeviceCount; waveInDevice++)
  998. {
  999. WaveInCapabilities deviceInfo = WaveIn.GetCapabilities(waveInDevice);
  1000. foreach (MMDevice device in deviceCollection)
  1001. {
  1002. try
  1003. {
  1004. if (device.FriendlyName.StartsWith(deviceInfo.ProductName))
  1005. {
  1006. devices.Add(device.FriendlyName);
  1007. break;
  1008. }
  1009. }
  1010. catch (Exception ex)
  1011. {
  1012. continue;
  1013. }
  1014. }
  1015. }
  1016. return devices;
  1017. }
  1018. /// <summary>
  1019. /// 获取麦克风---废弃
  1020. /// </summary>
  1021. private string GetMicrophone()
  1022. {
  1023. List<string> devs = new List<string>();
  1024. MMDeviceEnumerator enumberator = new MMDeviceEnumerator();
  1025. MMDeviceCollection deviceCollection = enumberator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.All);
  1026. for (int waveInDevice = 0; waveInDevice < WaveIn.DeviceCount; waveInDevice++)
  1027. {
  1028. WaveInCapabilities deviceInfo = WaveIn.GetCapabilities(waveInDevice);
  1029. foreach (MMDevice device in deviceCollection)
  1030. {
  1031. try
  1032. {
  1033. if (device.FriendlyName.StartsWith(deviceInfo.ProductName))
  1034. {
  1035. devs.Add(device.FriendlyName);
  1036. break;
  1037. }
  1038. }
  1039. catch (Exception)
  1040. {
  1041. }
  1042. }
  1043. }
  1044. if (devs.Count > 0)
  1045. {
  1046. return devs[0];
  1047. }
  1048. else
  1049. {
  1050. return "";
  1051. }
  1052. }
  1053. #endregion
  1054. #region 检测是否可用
  1055. /// <summary>
  1056. /// 录制麦克风的声音
  1057. /// </summary>
  1058. private WaveInEvent waveIn = null; //new WaveInEvent();
  1059. /// <summary>
  1060. /// 开始录制麦克风
  1061. /// </summary>
  1062. public bool StartRecordAudio(string audioFile)
  1063. {
  1064. try
  1065. {
  1066. waveIn = new WaveInEvent();
  1067. //生成音频文件的对象
  1068. WaveFileWriter writer = new WaveFileWriter(audioFile, waveIn.WaveFormat);
  1069. //开始录音,写数据
  1070. waveIn.DataAvailable += (s, a) =>
  1071. {
  1072. writer.Write(a.Buffer, 0, a.BytesRecorded);
  1073. };
  1074. //结束录音
  1075. waveIn.RecordingStopped += (s, a) =>
  1076. {
  1077. writer.Dispose();
  1078. writer = null;
  1079. waveIn.Dispose();
  1080. waveIn = null;
  1081. try
  1082. {
  1083. FileToolsCommon.DeleteFile(audioFile);
  1084. }
  1085. catch (Exception)
  1086. {
  1087. }
  1088. };
  1089. waveIn.StartRecording();
  1090. return true;
  1091. }
  1092. catch (Exception ex)
  1093. {
  1094. LogHelper.WriteErrLog("【麦克风】麦克风不可用:" + ex.Message, ex);
  1095. return false;
  1096. }
  1097. }
  1098. /// <summary>
  1099. /// 结束录制音频
  1100. /// </summary>
  1101. /// <param name="type">1麦克风 2扬声器</param>
  1102. public void StopRecordAudio(int type)
  1103. {
  1104. try
  1105. {
  1106. if (type == 1)
  1107. {
  1108. if (waveIn != null)
  1109. {
  1110. try
  1111. {
  1112. waveIn.StopRecording();
  1113. }
  1114. catch (Exception)
  1115. {
  1116. waveIn = null;
  1117. }
  1118. }
  1119. }
  1120. else if (type == 2)
  1121. {
  1122. if (capture != null)
  1123. {
  1124. try
  1125. {
  1126. capture.StopRecording();
  1127. }
  1128. catch (Exception)
  1129. {
  1130. capture = null;
  1131. }
  1132. }
  1133. }
  1134. }
  1135. catch (Exception ex)
  1136. {
  1137. LogHelper.WriteErrLog("【麦克风】麦克风不可用:" + ex.Message, ex);
  1138. }
  1139. }
  1140. /// <summary>
  1141. /// 录制扬声器的声音
  1142. /// </summary>
  1143. private WasapiLoopbackCapture capture = null; //new WasapiLoopbackCapture();
  1144. /// <summary>
  1145. /// 开始录制扬声器
  1146. /// </summary>
  1147. public bool StartRecordSpeakerAudio(string audioFile)
  1148. {
  1149. try
  1150. {
  1151. capture = new WasapiLoopbackCapture();
  1152. //生成音频文件的对象
  1153. WaveFileWriter writer = new WaveFileWriter(audioFile, capture.WaveFormat);
  1154. capture.DataAvailable += (s, a) =>
  1155. {
  1156. writer.Write(a.Buffer, 0, a.BytesRecorded);
  1157. };
  1158. //结束录音
  1159. capture.RecordingStopped += (s, a) =>
  1160. {
  1161. writer.Dispose();
  1162. writer = null;
  1163. capture.Dispose();
  1164. capture = null;
  1165. try
  1166. {
  1167. FileToolsCommon.DeleteFile(audioFile);
  1168. }
  1169. catch (Exception)
  1170. {
  1171. }
  1172. };
  1173. capture.StartRecording();
  1174. return true;
  1175. }
  1176. catch (Exception ex)
  1177. {
  1178. LogHelper.WriteErrLog("【麦克风】麦克风不可用:" + ex.Message, ex);
  1179. return false;
  1180. }
  1181. }
  1182. #endregion
  1183. #endregion
  1184. }
  1185. }