星火微课系统客户端
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

FFMpeg.cs 26KB

il y a 1 an
il y a 1 an
il y a 1 an
il y a 4 ans
il y a 4 ans
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  1. namespace XHWK.WKTool.system
  2. {
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using System.Drawing;
  7. using System.Linq;
  8. using System.Text;
  9. using System.Threading;
  10. using AForge.Video.DirectShow;
  11. using Common.system;
  12. using VisioForge.Shared.NAudio.CoreAudioApi;
  13. using VisioForge.Shared.NAudio.Wave;
  14. /// <summary>
  15. /// ffmpeg帮助类 创建人:赵耀 创建时间::2020年8月22日 需要安装\SSCR\Setup Screen Capturer Recorder v0.12.10.exe
  16. /// 本地调试需要配置环境变量 将ffmpeg.exe位置配置到环境变量的path中
  17. /// </summary>
  18. // ReSharper disable once InconsistentNaming
  19. public class FFMpeg
  20. {
  21. #region 变量
  22. public Process myProcess;
  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. private readonly string _ffmpegPath = FileToolsCommon.GetFileAbsolutePath(@"/ffmpeg.exe");
  40. #endregion 变量
  41. /// <summary>
  42. /// 录制屏幕
  43. /// </summary>
  44. /// <param name="filePath">文件存储路径</param>
  45. /// <param name="size">大小</param>
  46. /// <param name="recordingSound">录制音频</param>
  47. /// <param name="recordingMicrophone">录制麦克风</param>
  48. /// <param name="errMessage">错误信息</param>
  49. /// <param name="microphoneName">麦克风名</param>
  50. /// <returns></returns>
  51. public bool StartRecordingVideo
  52. (
  53. string filePath,
  54. Size size,
  55. bool recordingSound,
  56. bool recordingMicrophone,
  57. out string errMessage,
  58. string microphoneName = null
  59. )
  60. {
  61. while (myProcess != null)
  62. {
  63. Thread.Sleep(100);
  64. }
  65. errMessage = null;
  66. //路径
  67. FileToolsCommon.GetDirectoryName(filePath);
  68. string extension = FileToolsCommon.GetIoExtension(filePath); //扩展名
  69. //文件保存路径
  70. string pathName = GetRsFilePathName(filePath);
  71. Process[] killProcessArray = Process.GetProcessesByName("ffmpeg");
  72. foreach (Process killProcess in killProcessArray)
  73. {
  74. killProcess.Kill();
  75. }
  76. myProcess = new Process();
  77. _logPath = CreateffmpegLog();
  78. if (string.IsNullOrWhiteSpace(microphoneName))
  79. {
  80. microphoneName = GetMicrophoneName();
  81. }
  82. #region 检测麦克风扬声器
  83. string audioPath = FileToolsCommon.GetFileAbsolutePath("/temp/audio/");
  84. FileToolsCommon.CreateDirectory(audioPath);
  85. string audioSpeakerPath = audioPath + "adoS" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".m"; //FileToolsCommon.GetFileAbsolutePath("adoS.m");
  86. string audioMicrophonePath = audioPath + "adoM" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".m"; //FileToolsCommon.GetFileAbsolutePath("adoM.m");
  87. try
  88. {
  89. FileToolsCommon.DeleteFile(audioSpeakerPath);
  90. FileToolsCommon.DeleteFile(audioMicrophonePath);
  91. }
  92. catch (Exception)
  93. {
  94. // ignored
  95. }
  96. //是否录制音频
  97. if (recordingSound)
  98. {
  99. if (StartRecordSpeakerAudio(audioSpeakerPath))
  100. {
  101. _isRecordSpeaker = true;
  102. }
  103. else
  104. {
  105. //无法录制扬声器音频
  106. _isRecordSpeaker = false;
  107. }
  108. StopRecordAudio(2);
  109. Thread.Sleep(100);
  110. }
  111. //是否录制麦克风
  112. if (recordingMicrophone)
  113. {
  114. if (StartRecordAudio(audioMicrophonePath))
  115. {
  116. _isRecordMicrophone = true;
  117. }
  118. else
  119. {
  120. //无法录制麦克风
  121. _isRecordMicrophone = false;
  122. }
  123. StopRecordAudio(1);
  124. }
  125. #endregion 检测麦克风扬声器
  126. myProcess.StartInfo.FileName = _ffmpegPath; //ffmpeg.exe的绝对路径
  127. string speakerStr = "";
  128. string microphoneStr = "";
  129. if (_isRecordSpeaker && recordingSound)
  130. {
  131. speakerStr = "-f dshow -i audio=\"virtual-audio-capturer\" ";
  132. }
  133. if (_isRecordMicrophone && recordingMicrophone)
  134. {
  135. if (!string.IsNullOrWhiteSpace(microphoneName))
  136. {
  137. microphoneStr = "-f dshow -i audio=\"" + microphoneName + "\" -filter_complex amix=inputs=2:duration=first:dropout_transition=2 ";
  138. }
  139. }
  140. switch (extension.ToUpper())
  141. {
  142. case ".MP4":
  143. myProcess.StartInfo.Arguments = speakerStr + microphoneStr + " -f gdigrab -framerate 6 -offset_x 0 -offset_y 0 -video_size " + size.Width + "x" + size.Height + " -i desktop -pix_fmt yuv420p -vf scale=trunc(iw/2)*2:trunc(ih/2)*2 -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -acodec aac " + pathName;
  144. break;
  145. case ".AVI":
  146. case ".FLV":
  147. myProcess.StartInfo.Arguments = speakerStr + microphoneStr + " -f gdigrab -framerate 6 -offset_x 0 -offset_y 0 -video_size " + size.Width + "x" + size.Height + " -i desktop -pix_fmt yuv420p -vf scale=trunc(iw/2)*2:trunc(ih/2)*2 -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -acodec aac -f " + extension.ToLower().Replace(".", "") + " " + pathName;
  148. break;
  149. default:
  150. myProcess.StartInfo.Arguments = speakerStr + microphoneStr + " -f gdigrab -framerate 6 -offset_x 0 -offset_y 0 -video_size " + size.Width + "x" + size.Height + " -i desktop -pix_fmt yuv420p -vf scale=trunc(iw/2)*2:trunc(ih/2)*2 -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -acodec aac " + pathName;
  151. break;
  152. }
  153. if (OutputVideoLog)
  154. {
  155. LogHelper.Loginfo.Info("【录屏】:" + myProcess.StartInfo.Arguments);
  156. }
  157. FileToolsCommon.AppendText(_logPath, "【录屏】:" + myProcess.StartInfo.Arguments + "\r\n");
  158. myProcess.StartInfo.UseShellExecute = false; //不使用操作系统外壳程序启动
  159. myProcess.StartInfo.RedirectStandardError = true; //重定向标准错误输出
  160. myProcess.StartInfo.CreateNoWindow = true; //不显示程序窗口
  161. myProcess.StartInfo.RedirectStandardInput = true; //用于模拟该进程控制台的输入
  162. myProcess.ErrorDataReceived += Output;
  163. try
  164. {
  165. myProcess.Start();
  166. myProcess.BeginErrorReadLine();
  167. }
  168. catch (Exception ex)
  169. {
  170. if (ex.Message.Contains("访问"))
  171. {
  172. errMessage = "访问被拒绝,请关闭杀毒软件或新任此软件后重试!";
  173. }
  174. else
  175. {
  176. errMessage = ex.Message + " 请关闭杀毒软件或信任此软件后重试!";
  177. }
  178. LogHelper.Logerror.Error("【录音】(StartRecordingAudio)" + errMessage, ex);
  179. myProcess.Dispose();
  180. myProcess = null;
  181. return false;
  182. }
  183. return true;
  184. }
  185. /// <summary>
  186. /// 视频剪辑
  187. /// </summary>
  188. /// <param name="videoFilePath">视频路径</param>
  189. /// <param name="startTime">开始时间 格式 HH:mm:ss</param>
  190. /// <param name="endTime">结束时间 格式 HH:mm:ss</param>
  191. /// <param name="saveFilePath">保存文件路径</param>
  192. public void ClipVideo
  193. (
  194. string videoFilePath,
  195. string startTime,
  196. string endTime,
  197. string saveFilePath
  198. )
  199. {
  200. while (myProcess != null)
  201. {
  202. Thread.Sleep(100);
  203. }
  204. Process[] killProcessArray = Process.GetProcessesByName("ffmpeg");
  205. foreach (var killProcess in killProcessArray)
  206. {
  207. killProcess.Kill();
  208. }
  209. myProcess = new Process();
  210. _logPath = CreateffmpegLog();
  211. this.myProcess.StartInfo.FileName = _ffmpegPath; //ffmpeg.exe的绝对路径
  212. //ffmpeg -ss 开始时间 -to 结束时间 -accurate_seek -i mp4输入路径 -c:v libx264 -c:a aac -strict experimental -vf scale = 宽:高 -b 500k 输出路径.mp4
  213. myProcess.StartInfo.Arguments = "-i " + videoFilePath + " -vcodec copy -acodec copy -ss " + startTime + " -to " + endTime + " " + saveFilePath; //-filter:a "volume=0.5"
  214. myProcess.StartInfo.UseShellExecute = false; //不使用操作系统外壳程序启动
  215. myProcess.StartInfo.RedirectStandardError = true; //重定向标准错误输出
  216. myProcess.StartInfo.CreateNoWindow = true; //不显示程序窗口
  217. myProcess.StartInfo.RedirectStandardInput = true; //用于模拟该进程控制台的输入
  218. //外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN
  219. myProcess.ErrorDataReceived += Output;
  220. myProcess.Start(); //启动线程
  221. myProcess.BeginErrorReadLine(); //开始异步读取
  222. myProcess.WaitForExit(); //阻塞等待进程结束
  223. myProcess.Close(); //关闭进程
  224. myProcess.Dispose(); //释放资源
  225. #region 进程是否已经释放
  226. bool isRunning = true;
  227. while (isRunning)
  228. {
  229. isRunning = false;
  230. Process[] processArray = Process.GetProcessesByName("ffmpeg");
  231. if (processArray.Length > 0)
  232. {
  233. isRunning = true;
  234. Thread.Sleep(100);
  235. }
  236. }
  237. #endregion 进程是否已经释放
  238. myProcess = null;
  239. }
  240. /// <summary>
  241. /// 获取文件完整路径 录屏
  242. /// </summary>
  243. /// <param name="filePath">文件路径</param>
  244. /// <returns></returns>
  245. private string GetRsFilePathName(string filePath)
  246. {
  247. //路径
  248. string path = FileToolsCommon.GetDirectoryName(filePath);
  249. //Path.GetFileName(FilePath);//获取文件名
  250. string extension = FileToolsCommon.GetIoExtension(filePath); //扩展名
  251. string tempFilePath = path + "_temppath/";
  252. //创建临时目录
  253. FileToolsCommon.CreateDirectory(tempFilePath);
  254. //创建记录文件
  255. if (!FileToolsCommon.IsExistFile(tempFilePath + "filelist.d"))
  256. {
  257. FileToolsCommon.CreateFile(tempFilePath + "filelist.d");
  258. }
  259. int num = 1;
  260. string completeFilePath = tempFilePath + num + extension;
  261. while (FileToolsCommon.IsExistFile(completeFilePath))
  262. {
  263. num++;
  264. completeFilePath = tempFilePath + num + extension;
  265. }
  266. FileToolsCommon.AppendText(tempFilePath + "filelist.d", "file ./" + num + extension + "\r\n");
  267. return completeFilePath;
  268. }
  269. /// <summary>
  270. /// 创建日志文件
  271. /// </summary>
  272. /// <returns></returns>
  273. private string CreateffmpegLog()
  274. {
  275. string logFileName = DateTime.Now.ToString("yyyyMMdd");
  276. string logFilePath = FileToolsCommon.GetFileAbsolutePath("/Log/FFMpegLog/");
  277. FileToolsCommon.CreateDirectory(logFilePath);
  278. string logName = logFilePath + logFileName + ".log";
  279. try
  280. {
  281. if (!FileToolsCommon.IsExistFile(logName))
  282. {
  283. FileToolsCommon.CreateFile(logName);
  284. FileToolsCommon.AppendText(logName, "\r\n****************************************************************************************************" + "****************************************************************************************************\r\n");
  285. return logName;
  286. }
  287. else
  288. {
  289. int num = 0;
  290. while (FileToolsCommon.GetFileSizeByMb(logName) > 2)
  291. {
  292. num++;
  293. logName = logFilePath + logFileName + "_" + num + ".log";
  294. FileToolsCommon.CreateFile(logName);
  295. }
  296. FileToolsCommon.AppendText(logName, "\r\n****************************************************************************************************" + "****************************************************************************************************\r\n");
  297. return logName;
  298. }
  299. }
  300. catch (Exception)
  301. {
  302. return logName;
  303. }
  304. }
  305. /// <summary>
  306. /// 输出结果
  307. /// </summary>
  308. /// <param name="sendProcess"></param>
  309. /// <param name="output"></param>
  310. private void Output(object sendProcess, DataReceivedEventArgs output)
  311. {
  312. if (!string.IsNullOrEmpty(output.Data))
  313. {
  314. FileToolsCommon.AppendText(_logPath, "【" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff") + "】:");
  315. FileToolsCommon.AppendText(_logPath, output.Data + "\r\n");
  316. }
  317. }
  318. #region 麦克风声卡检测
  319. #region 获取麦克风
  320. /// <summary>
  321. /// 获取麦克风名称
  322. /// </summary>
  323. /// <returns></returns>
  324. public string GetMicrophoneName()
  325. {
  326. return GetAudioInDevices();
  327. }
  328. /// <summary>
  329. /// AForge获取麦克风
  330. /// </summary>
  331. /// <returns></returns>
  332. public static string GetAudioInDevices()
  333. {
  334. List<string> devicesList = new List<string>();
  335. try
  336. {
  337. // ReSharper disable once CollectionNeverUpdated.Local
  338. FilterInfoCollection videoDevices = new FilterInfoCollection(FilterCategory.AudioInputDevice);
  339. foreach (FilterInfo device in videoDevices)
  340. {
  341. devicesList.Add(device.Name);
  342. }
  343. }
  344. catch (ApplicationException)
  345. {
  346. //Console.WriteLine("No local capture devices");
  347. }
  348. if (devicesList.Count > 1)
  349. {
  350. return devicesList[1];
  351. }
  352. return "";
  353. }
  354. /// <summary>
  355. /// AForge获取麦克风列表
  356. /// </summary>
  357. /// <returns></returns>
  358. public static List<string> GetAudioInDevicesList()
  359. {
  360. List<string> devicesList = new List<string>();
  361. try
  362. {
  363. // ReSharper disable once CollectionNeverUpdated.Local
  364. FilterInfoCollection videoDevices = new FilterInfoCollection(FilterCategory.AudioInputDevice);
  365. foreach (FilterInfo device in videoDevices)
  366. {
  367. if (device.Name == "virtual-audio-capturer")
  368. {
  369. continue;
  370. }
  371. devicesList.Add(device.Name);
  372. }
  373. }
  374. catch (ApplicationException)
  375. {
  376. //Console.WriteLine("No local capture devices");
  377. }
  378. return devicesList;
  379. }
  380. /// <summary>
  381. /// 获取声音输入设备名称 不完整
  382. /// </summary>
  383. /// <returns></returns>
  384. public static string GetInDeviceName()
  385. {
  386. List<WaveInCapabilities> devices = new List<WaveInCapabilities>();
  387. int waveInDevices = WaveIn.DeviceCount;
  388. for (int i = 0; i < waveInDevices; i++)
  389. {
  390. devices.Add(WaveIn.GetCapabilities(i));
  391. }
  392. var devs = devices.Select(item => item.ProductName).ToList();
  393. if (devs.Count > 0)
  394. {
  395. byte[] buffer = Encoding.UTF8.GetBytes(devs[0]);
  396. string microphoneName = Encoding.UTF8.GetString(buffer); // 统一使用UTF-8
  397. return microphoneName;
  398. }
  399. else
  400. {
  401. return "";
  402. }
  403. }
  404. /// <summary>
  405. /// 获取声音输入设备完整名称
  406. /// </summary>
  407. /// <returns></returns>
  408. public static string GetInDeviceFull()
  409. {
  410. List<string> devices = new List<string>();
  411. MMDeviceEnumerator enumberator = new MMDeviceEnumerator();
  412. MMDeviceCollection deviceCollection = enumberator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.All);
  413. for (int waveInDevice = 0; waveInDevice < WaveIn.DeviceCount; waveInDevice++)
  414. {
  415. WaveInCapabilities deviceInfo = WaveIn.GetCapabilities(waveInDevice);
  416. foreach (MMDevice device in deviceCollection)
  417. {
  418. try
  419. {
  420. if (device.FriendlyName.StartsWith(deviceInfo.ProductName))
  421. {
  422. devices.Add(device.FriendlyName);
  423. break;
  424. }
  425. }
  426. catch (Exception)
  427. {
  428. // ignored
  429. }
  430. }
  431. }
  432. if (devices.Count > 0)
  433. {
  434. byte[] buffer = Encoding.UTF8.GetBytes(devices[0]);
  435. string microphoneName = Encoding.UTF8.GetString(buffer); // 统一使用UTF-8
  436. return microphoneName;
  437. }
  438. else
  439. {
  440. return "";
  441. }
  442. }
  443. /// <summary>
  444. /// 获取声音输入设备完整名称列表
  445. /// </summary>
  446. /// <returns></returns>
  447. public List<string> GetInDeviceListFull()
  448. {
  449. List<string> devices = new List<string>();
  450. MMDeviceEnumerator enumberator = new MMDeviceEnumerator();
  451. MMDeviceCollection deviceCollection = enumberator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.All);
  452. for (int waveInDevice = 0; waveInDevice < WaveIn.DeviceCount; waveInDevice++)
  453. {
  454. WaveInCapabilities deviceInfo = WaveIn.GetCapabilities(waveInDevice);
  455. foreach (MMDevice device in deviceCollection)
  456. {
  457. try
  458. {
  459. if (device.FriendlyName.StartsWith(deviceInfo.ProductName))
  460. {
  461. devices.Add(device.FriendlyName);
  462. break;
  463. }
  464. }
  465. catch (Exception)
  466. {
  467. // ignored
  468. }
  469. }
  470. }
  471. return devices;
  472. }
  473. #endregion 获取麦克风
  474. #region 录音
  475. /// <summary>
  476. /// 开始录制麦克风
  477. /// </summary>
  478. public bool StartAudio(string audioFile, string deviceName = "")
  479. {
  480. try
  481. {
  482. int deviceIndex = 0;
  483. _waveIn = new WaveInEvent();
  484. List<string> inDeviceList = GetInDeviceListFull();
  485. if (inDeviceList.Exists(x => deviceName.Contains(x)))
  486. {
  487. deviceIndex = inDeviceList.FindIndex(x => deviceName.Contains(x));
  488. }
  489. _waveIn.DeviceNumber = deviceIndex;
  490. //waveIn.DeviceNumber = 1;
  491. //生成音频文件的对象
  492. WaveFileWriter writer = new WaveFileWriter(audioFile, _waveIn.WaveFormat);
  493. //开始录音,写数据
  494. _waveIn.DataAvailable += (s, a) =>
  495. {
  496. writer.Write
  497. (
  498. a.Buffer,
  499. 0,
  500. a.BytesRecorded
  501. );
  502. };
  503. return true;
  504. }
  505. catch (Exception ex)
  506. {
  507. LogHelper.Logerror.Error("【麦克风】麦克风不可用:" + ex.Message, ex);
  508. return false;
  509. }
  510. }
  511. #endregion 录音
  512. #region 检测是否可用
  513. /// <summary>
  514. /// 录制麦克风的声音
  515. /// </summary>
  516. private WaveInEvent _waveIn; //new WaveInEvent();
  517. /// <summary>
  518. /// 开始录制麦克风
  519. /// </summary>
  520. public bool StartRecordAudio
  521. (
  522. string audioFile,
  523. string deviceName = "",
  524. bool isStopDelFile = true
  525. )
  526. {
  527. try
  528. {
  529. int deviceIndex = 0;
  530. _waveIn = new WaveInEvent();
  531. List<string> inDeviceList = GetInDeviceListFull();
  532. if (inDeviceList.Exists(x => deviceName.Contains(x)))
  533. {
  534. deviceIndex = inDeviceList.FindIndex(x => deviceName.Contains(x));
  535. }
  536. _waveIn.DeviceNumber = deviceIndex;
  537. //waveIn.DeviceNumber = 1;
  538. //生成音频文件的对象
  539. WaveFileWriter writer = new WaveFileWriter(audioFile, _waveIn.WaveFormat);
  540. //开始录音,写数据
  541. _waveIn.DataAvailable += (s, a) =>
  542. {
  543. writer.Write
  544. (
  545. a.Buffer,
  546. 0,
  547. a.BytesRecorded
  548. );
  549. short s1 = BitConverter.ToInt16(a.Buffer, 0); //这样采样比较少,反正是int16型的
  550. int s2 = Math.Abs(s1 / 50);
  551. Console.WriteLine(@"声音大小:" + s2);
  552. };
  553. //结束录音
  554. _waveIn.RecordingStopped += (s, a) =>
  555. {
  556. writer.Dispose();
  557. writer = null;
  558. _waveIn.Dispose();
  559. _waveIn = null;
  560. try
  561. {
  562. if (isStopDelFile)
  563. {
  564. FileToolsCommon.DeleteFile(audioFile);
  565. }
  566. }
  567. catch (Exception)
  568. {
  569. // ignored
  570. }
  571. };
  572. _waveIn.StartRecording();
  573. return true;
  574. }
  575. catch (Exception ex)
  576. {
  577. LogHelper.Logerror.Error("【麦克风】麦克风不可用:" + ex.Message, ex);
  578. return false;
  579. }
  580. }
  581. /// <summary>
  582. /// 结束录制音频
  583. /// </summary>
  584. /// <param name="type">1麦克风 2扬声器</param>
  585. public void StopRecordAudio(int type)
  586. {
  587. try
  588. {
  589. if (type == 1)
  590. {
  591. if (_waveIn != null)
  592. {
  593. try
  594. {
  595. _waveIn.StopRecording();
  596. }
  597. catch (Exception)
  598. {
  599. _waveIn = null;
  600. }
  601. }
  602. }
  603. else if (type == 2)
  604. {
  605. if (_capture != null)
  606. {
  607. try
  608. {
  609. _capture.StopRecording();
  610. }
  611. catch (Exception)
  612. {
  613. _capture = null;
  614. }
  615. }
  616. }
  617. }
  618. catch (Exception ex)
  619. {
  620. LogHelper.Logerror.Error("【麦克风】麦克风不可用:" + ex.Message, ex);
  621. }
  622. }
  623. /// <summary>
  624. /// 录制扬声器的声音
  625. /// </summary>
  626. private WasapiLoopbackCapture _capture; //new WasapiLoopbackCapture();
  627. /// <summary>
  628. /// 开始录制扬声器
  629. /// </summary>
  630. public bool StartRecordSpeakerAudio(string audioFile)
  631. {
  632. try
  633. {
  634. _capture = new WasapiLoopbackCapture();
  635. //生成音频文件的对象
  636. WaveFileWriter writer = new WaveFileWriter(audioFile, _capture.WaveFormat);
  637. _capture.DataAvailable += (s, a) =>
  638. {
  639. writer.Write
  640. (
  641. a.Buffer,
  642. 0,
  643. a.BytesRecorded
  644. );
  645. };
  646. //结束录音
  647. _capture.RecordingStopped += (s, a) =>
  648. {
  649. writer.Dispose();
  650. writer = null;
  651. _capture.Dispose();
  652. _capture = null;
  653. try
  654. {
  655. FileToolsCommon.DeleteFile(audioFile);
  656. }
  657. catch (Exception)
  658. {
  659. // ignored
  660. }
  661. };
  662. _capture.StartRecording();
  663. return true;
  664. }
  665. catch (Exception ex)
  666. {
  667. LogHelper.Logerror.Error("【扬声器】扬声器不可用:" + ex.Message, ex);
  668. return false;
  669. }
  670. }
  671. #endregion 检测是否可用
  672. #endregion 麦克风声卡检测
  673. }
  674. }