using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.Threading; using VisioForge.Shared.NAudio.CoreAudioApi; using VisioForge.Shared.NAudio.Wave; namespace Common.system { /// /// ffmpeg帮助类 /// 创建人:赵耀 /// 创建时间::2020年8月22日 /// 需要安装\ffmpeg\bin\Setup Screen Capturer Recorder v0.12.10.exe /// 本地调试需要配置环境变量 将ffmpeg.exe位置配置到环境变量的path中 /// public class FFMpeg { public Process myProcess = null; /// /// ffmpeg输出日志文件地址 每个文件2MB左右 /// private string LogPath = ""; /// /// 是否可以录制扬声器 /// private bool IsRecordSpeaker = true; /// /// 是否可以录制麦克风 /// private bool IsRecordMicrophone = true; /// /// 录制屏幕 /// /// 文件存储路径 public void StartRecordingVideo(string FilePath) { while (myProcess != null) { Thread.Sleep(100); } //路径 string Path = FileToolsCommon.GetDirectoryName(FilePath); string Extension = FileToolsCommon.GetIOExtension(FilePath);//扩展名 //文件保存路径 string PathName = GetRSFilePathName(FilePath); Process[] KillProcessArray = Process.GetProcessesByName("ffmpeg"); foreach (Process KillProcess in KillProcessArray) { KillProcess.Kill(); } myProcess = new Process(); LogPath = CreateffmpegLog(); string MicrophoneName = null; #region 检测麦克风扬声器 string audioSpeakerPath = FileToolsCommon.GetFileAbsolutePath("adoS.m"); string audioMicrophonePath = FileToolsCommon.GetFileAbsolutePath("adoM.m"); try { FileToolsCommon.DeleteFile(audioSpeakerPath); FileToolsCommon.DeleteFile(audioMicrophonePath); } catch (Exception) { } if (StartRecordSpeakerAudio(audioSpeakerPath)) { IsRecordSpeaker = true; } else { //无法录制扬声器音频 IsRecordSpeaker = false; } StopRecordAudio(2); Thread.Sleep(100); if (StartRecordAudio(audioMicrophonePath)) { IsRecordMicrophone = true; } else { //无法录制麦克风 IsRecordMicrophone = false; } StopRecordAudio(1); #endregion myProcess.StartInfo.FileName = FileToolsCommon.GetFileAbsolutePath(@"/ffmpeg/bin/ffmpeg.exe"); //ffmpeg.exe的绝对路径 string SpeakerStr = ""; string MicrophoneStr = ""; if (IsRecordSpeaker) { SpeakerStr = "-f dshow -i audio=\"virtual-audio-capturer\" "; } if (IsRecordMicrophone) { MicrophoneName = GetInDeviceFull(); if (!string.IsNullOrWhiteSpace(MicrophoneName)) { MicrophoneStr = "-f dshow -i audio=\"" + MicrophoneName + "\" -filter_complex amix=inputs=2:duration=first:dropout_transition=2 "; } } switch (Extension.ToUpper()) { case ".MP4": myProcess.StartInfo.Arguments = SpeakerStr + MicrophoneStr + " -f gdigrab -i desktop -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -acodec aac " + PathName; //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; //if (string.IsNullOrWhiteSpace(MicrophoneName)) //{ // 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的参数 //} //else //{ // myProcess.StartInfo.Arguments = "-f dshow -i audio=\"virtual-audio-capturer\" -f dshow -i audio=\"" + // 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的参数 //} break; case ".AVI": case ".FLV": myProcess.StartInfo.Arguments = SpeakerStr + MicrophoneStr + " -f gdigrab -i desktop -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -acodec aac -f " + Extension.ToLower().Replace(".", "") + " " + PathName; //if (string.IsNullOrWhiteSpace(MicrophoneName)) //{ // 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的参数 //} //else //{ // myProcess.StartInfo.Arguments = "-f dshow -i audio=\"virtual-audio-capturer\" -f dshow -i audio=\"" + // 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的参数 //} break; default: myProcess.StartInfo.Arguments = SpeakerStr + MicrophoneStr + " -f gdigrab -i desktop -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -acodec aac " + PathName; break; } LogHelper.WriteInfoLog("【录屏】:"+myProcess.StartInfo.Arguments); myProcess.StartInfo.UseShellExecute = false; //不使用操作系统外壳程序启动 myProcess.StartInfo.RedirectStandardError = true; //重定向标准错误输出 myProcess.StartInfo.CreateNoWindow = true; //不显示程序窗口 myProcess.StartInfo.RedirectStandardInput = true; //用于模拟该进程控制台的输入 myProcess.ErrorDataReceived += new DataReceivedEventHandler(Output); myProcess.Start(); myProcess.BeginErrorReadLine(); } /// /// 录制音频 /// /// MP3音频位置 public bool StartRecordingAudio(string Mp3Path) { while (myProcess != null) { Thread.Sleep(100); } //路径 string Path = FileToolsCommon.GetDirectoryName(Mp3Path); //文件保存路径 string PathName = GetFilePathName(Mp3Path); Process[] KillProcessArray = Process.GetProcessesByName("ffmpeg"); foreach (Process KillProcess in KillProcessArray) { KillProcess.Kill(); } string MicrophoneName = null; #region 检测麦克风扬声器 string audioSpeakerPath = FileToolsCommon.GetFileAbsolutePath("adoS.m"); string audioMicrophonePath = FileToolsCommon.GetFileAbsolutePath("adoM.m"); try { FileToolsCommon.DeleteFile(audioSpeakerPath); FileToolsCommon.DeleteFile(audioMicrophonePath); } catch (Exception) { } if (StartRecordSpeakerAudio(audioSpeakerPath)) { IsRecordSpeaker = true; } else { //无法录制扬声器音频 IsRecordSpeaker = false; } StopRecordAudio(2); Thread.Sleep(100); if (StartRecordAudio(audioMicrophonePath)) { IsRecordMicrophone = true; MicrophoneName = GetInDeviceFull(); } else { //无法录制麦克风 IsRecordMicrophone = false; } StopRecordAudio(1); if (!IsRecordSpeaker && !IsRecordMicrophone) { return false; } #endregion myProcess = new Process(); LogPath = CreateffmpegLog(); myProcess.StartInfo.FileName = FileToolsCommon.GetFileAbsolutePath(@"/ffmpeg/bin/ffmpeg.exe"); //ffmpeg.exe的绝对路径 if (IsRecordSpeaker && IsRecordMicrophone) { myProcess.StartInfo.Arguments = "-f dshow -i audio=\"virtual-audio-capturer\" -f dshow -i audio=\"" + MicrophoneName + "\" -filter_complex amix=inputs=2:duration=first:dropout_transition=2 " + PathName; } else if (IsRecordSpeaker) { myProcess.StartInfo.Arguments = "-f dshow -i audio=\"virtual-audio-capturer\" " + PathName; } else if (IsRecordMicrophone) { //录制麦克风 if (!string.IsNullOrWhiteSpace(MicrophoneName)) { myProcess.StartInfo.Arguments = "-f dshow -i audio=\"" + MicrophoneName + "\" -filter_complex amix=inputs=2:duration=first:dropout_transition=2 " + PathName; } } LogHelper.WriteInfoLog("【录音】:" + myProcess.StartInfo.Arguments); myProcess.StartInfo.UseShellExecute = false; //不使用操作系统外壳程序启动 myProcess.StartInfo.RedirectStandardError = true; //重定向标准错误输出 myProcess.StartInfo.CreateNoWindow = true; //不显示程序窗口 myProcess.StartInfo.RedirectStandardInput = true; //用于模拟该进程控制台的输入 //外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN myProcess.ErrorDataReceived += new DataReceivedEventHandler(Output); myProcess.Start(); //启动线程 myProcess.BeginErrorReadLine(); //开始异步读取 return true; } /// /// 暂停录制 /// public bool SuspendFFmpeg() { if (myProcess != null) { myProcess.StandardInput.WriteLine("q");//在这个进程的控制台中模拟输入q,用于暂停录制 myProcess.Close();//关闭进程 myProcess.Dispose();//释放资源 } #region 进程是否已经释放 bool IsRunning = true; while (IsRunning) { IsRunning = false; Process[] ProcessArray = Process.GetProcessesByName("ffmpeg"); foreach (Process KillProcess in ProcessArray) { IsRunning = true; Thread.Sleep(100); } } #endregion myProcess = null; return true; //myProcess.Kill(); } /// /// 停止录制并合成文件 /// /// 文件存储路径 必须与开始时的路径完全一致 public bool StopFFmpeg(string FilePath) { //文件完整路径 if (myProcess != null) { myProcess.StandardInput.WriteLine("q");//在这个进程的控制台中模拟输入q,用于暂停录制 myProcess.Close();//关闭进程 myProcess.Dispose();//释放资源 } #region 进程是否已经释放 bool IsRunning = true; while (IsRunning) { IsRunning = false; Process[] ProcessArray = Process.GetProcessesByName("ffmpeg"); foreach (Process KillProcess in ProcessArray) { IsRunning = true; Thread.Sleep(100); } } #endregion myProcess = null; Thread t1 = new Thread(MergeVideoOrAudio); t1.Start(FilePath); return true; //文件合成 } /// /// 图片音频合成视频 /// /// 图片列表位置 命名为1.png 2.png /// MP3音频位置 /// 视频保存位置 /// 每秒帧率 /// 视频宽度 /// 视频高度 public bool SynthesisVideo(string ImageListPath, string Mp3Path, string VideoSavePath, int Frequency, int VideoWidth, int VideoHeight) { //new Thread(new ThreadStart(new Action(() => //{ //}))).Start(); while (myProcess != null) { Thread.Sleep(100); } string Extension = FileToolsCommon.GetIOExtension(VideoSavePath);//扩展名 Process[] KillProcessArray = Process.GetProcessesByName("ffmpeg"); //Debug.WriteLine(KillProcessArray.Length.ToString()); foreach (Process KillProcess in KillProcessArray) { KillProcess.Kill(); } myProcess = new Process(); try { LogPath = CreateffmpegLog(); string mp3Str = ""; #region 判断音频是否存在 if (!string.IsNullOrWhiteSpace(Mp3Path)) { if (FileToolsCommon.IsExistFile(Mp3Path)) { mp3Str = "-i " + Mp3Path; } } #endregion myProcess.StartInfo.FileName = FileToolsCommon.GetFileAbsolutePath(@"/ffmpeg/bin/ffmpeg.exe"); //ffmpeg.exe的绝对路径 switch (Extension.ToUpper()) { case ".MP4": myProcess.StartInfo.Arguments = @"-y -r " + Frequency + " -i " + ImageListPath + @"%d.png " + mp3Str + @" -s " + VideoWidth + "x" + VideoHeight + " -vcodec mpeg4 " + VideoSavePath; break; case ".AVI": myProcess.StartInfo.Arguments = @"-y -r " + Frequency + " -i " + ImageListPath + @"%d.png " + mp3Str + @" -s " + VideoWidth + "x" + VideoHeight + " -f AVI " + VideoSavePath; break; case ".FLV": myProcess.StartInfo.Arguments = @"-y -r " + Frequency + " -i " + ImageListPath + @"%d.png " + mp3Str + @" -s " + VideoWidth + "x" + VideoHeight + " -f FLV " + VideoSavePath; break; default: myProcess.StartInfo.Arguments = @"-y -r " + Frequency + " -i " + ImageListPath + @"%d.png " + mp3Str + @" -s " + VideoWidth + "x" + VideoHeight + " -vcodec mpeg4 " + VideoSavePath; break; } myProcess.StartInfo.UseShellExecute = false; //不使用操作系统外壳程序启动 myProcess.StartInfo.RedirectStandardError = true; //重定向标准错误输出 myProcess.StartInfo.CreateNoWindow = true; //不显示程序窗口 myProcess.StartInfo.RedirectStandardInput = true; //用于模拟该进程控制台的输入 //外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN myProcess.ErrorDataReceived += new DataReceivedEventHandler(Output); myProcess.Start(); //启动线程 myProcess.BeginErrorReadLine(); //开始异步读取 myProcess.WaitForExit(); //阻塞等待进程结束 myProcess.Close(); //关闭进程 myProcess.Dispose(); //释放资源 #region 进程是否已经释放 bool IsRunning = true; while (IsRunning) { IsRunning = false; Process[] ProcessArray = Process.GetProcessesByName("ffmpeg"); foreach (Process KillProcess in ProcessArray) { IsRunning = true; Thread.Sleep(100); } } #endregion myProcess = null; //生成视频后删除图片和音频保存列表 //FileToolsCommon.DeleteDirectory(ImageListPath); //FileToolsCommon.DeleteDirectory(FileToolsCommon.GetDirectoryName(Mp3Path)); Thread.Sleep(100); FileToolsCommon.DeleteDirectory(FileToolsCommon.GetDirectoryName(VideoSavePath) + "temp"); return true; } catch (Exception ex) { LogHelper.WriteErrLog("【视频合成】(SynthesisVideo)视频生成失败," + ex.Message, ex); return false; } //Dispatcher.Invoke(() => //{ //}); //// 允许不同线程间的调用 //Control.CheckForIllegalCrossThreadCalls = false; } /// /// 视频音频合成 /// /// 存储路径 public void MergeVideoOrAudio(object FilePathobj) { //new Thread(new ThreadStart(new Action(() => //{ //Dispatcher.Invoke(() => //{ //}); //}))).Start(); while (myProcess != null) { Thread.Sleep(100); } //路径 string FilePath = (string)FilePathobj; string Path = FileToolsCommon.GetDirectoryName(FilePath); //扩展名 string Extension = FileToolsCommon.GetIOExtension(FilePath); //Process[] KillProcessArray = Process.GetProcessesByName("ffmpeg"); //foreach (var KillProcess in KillProcessArray) //{ // KillProcess.Kill(); //} #region 判断文件是否存在 if (Extension.ToUpper() == ".MP3") { if (!FileToolsCommon.IsExistFile(Path + "temp/filelist.d")) { return; } } else { if (!FileToolsCommon.IsExistFile(Path + "temprs/filelist.d")) { return; } } #endregion myProcess = new Process(); LogPath = CreateffmpegLog(); myProcess.StartInfo.FileName = FileToolsCommon.GetFileAbsolutePath(@"/ffmpeg/bin/ffmpeg.exe"); //ffmpeg.exe的绝对路径 if (Extension.ToUpper() == ".MP3") { myProcess.StartInfo.Arguments = "-f concat -safe 0 -i " + Path + "temp/filelist.d -c copy " + FilePath; } else { myProcess.StartInfo.Arguments = "-f concat -safe 0 -i " + Path + "temprs/filelist.d -c copy " + FilePath; } myProcess.StartInfo.UseShellExecute = false; //不使用操作系统外壳程序启动 myProcess.StartInfo.RedirectStandardError = true; //重定向标准错误输出 myProcess.StartInfo.CreateNoWindow = true; //不显示程序窗口 myProcess.StartInfo.RedirectStandardInput = true; //用于模拟该进程控制台的输入 //外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN myProcess.ErrorDataReceived += new DataReceivedEventHandler(Output); myProcess.Start(); //启动线程 myProcess.BeginErrorReadLine(); //开始异步读取 myProcess.WaitForExit(); //阻塞等待进程结束 myProcess.Close(); //关闭进程 myProcess.Dispose(); //释放资源 #region 进程是否已经释放 bool IsRunning = true; while (IsRunning) { IsRunning = false; Process[] ProcessArray = Process.GetProcessesByName("ffmpeg"); foreach (Process KillProcess in ProcessArray) { IsRunning = true; Thread.Sleep(100); } } #endregion myProcess = null; if (Extension.ToUpper() == ".MP3") { FileToolsCommon.DeleteDirectory(Path + "temp/"); } else { FileToolsCommon.DeleteDirectory(Path + "temprs/"); } } /// /// 获取文件完整路径 音频 /// /// 文件路径 /// private string GetFilePathName(string FilePath) { //路径 string Path = FileToolsCommon.GetDirectoryName(FilePath); //Path.GetFileName(FilePath);//获取文件名 string Extension = FileToolsCommon.GetIOExtension(FilePath);//扩展名 string tempFilePath = Path + "temp/"; //创建临时目录 FileToolsCommon.CreateDirectory(tempFilePath); //创建记录文件 if (!FileToolsCommon.IsExistFile(tempFilePath + "filelist.d")) { FileToolsCommon.CreateFile(tempFilePath + "filelist.d"); } int num = 1; string CompleteFilePath = tempFilePath + num + Extension; while (FileToolsCommon.IsExistFile(CompleteFilePath)) { num++; CompleteFilePath = tempFilePath + num + Extension; } FileToolsCommon.AppendText(tempFilePath + "filelist.d", "file ./" + num + Extension + "\r\n"); return CompleteFilePath; } /// /// 获取文件完整路径 录屏 /// /// 文件路径 /// private string GetRSFilePathName(string FilePath) { //路径 string Path = FileToolsCommon.GetDirectoryName(FilePath); //Path.GetFileName(FilePath);//获取文件名 string Extension = FileToolsCommon.GetIOExtension(FilePath);//扩展名 string tempFilePath = Path + "temprs/"; //创建临时目录 FileToolsCommon.CreateDirectory(tempFilePath); //创建记录文件 if (!FileToolsCommon.IsExistFile(tempFilePath + "filelist.d")) { FileToolsCommon.CreateFile(tempFilePath + "filelist.d"); } int num = 1; string CompleteFilePath = tempFilePath + num + Extension; while (FileToolsCommon.IsExistFile(CompleteFilePath)) { num++; CompleteFilePath = tempFilePath + num + Extension; } FileToolsCommon.AppendText(tempFilePath + "filelist.d", "file ./" + num + Extension + "\r\n"); return CompleteFilePath; } /// /// 生成缩略图 /// /// 视频地址 /// 图片地址 /// 图片大小 /// 图片大小 public bool GenerateThumbnails(string VideoPath, string ImagePath,int Width=0,int Height=0) { while (myProcess != null) { Thread.Sleep(100); } Process[] KillProcessArray = Process.GetProcessesByName("ffmpeg"); foreach (Process KillProcess in KillProcessArray) { KillProcess.Kill(); } string WHStr = ""; if(Width>0) { WHStr = " -s "+ Width + "x"+ Height; } try { myProcess = new Process(); LogPath = CreateffmpegLog(); myProcess.StartInfo.FileName = FileToolsCommon.GetFileAbsolutePath(@"/ffmpeg/bin/ffmpeg.exe"); //ffmpeg.exe的绝对路径 //myProcess.StartInfo.Arguments = "-i \"" + VideoPath + "\" -ss 1 -vframes 1 -r 1 -ac 1 -ab 2 -s " + thubWidth + "*" + thubHeight + " -f image2 \"" + ImagePath + "\""; myProcess.StartInfo.Arguments = "-i \"" + VideoPath + "\" -ss 1 -vframes 1 -r 1 -ac 1 -ab 2"+ WHStr + " -f image2 \"" + ImagePath + "\""; myProcess.StartInfo.UseShellExecute = false; //不使用操作系统外壳程序启动 myProcess.StartInfo.RedirectStandardError = true; //重定向标准错误输出 myProcess.StartInfo.CreateNoWindow = true; //不显示程序窗口 myProcess.StartInfo.RedirectStandardInput = true; //用于模拟该进程控制台的输入 //外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN myProcess.ErrorDataReceived += new DataReceivedEventHandler(Output); myProcess.Start(); //启动线程 myProcess.BeginErrorReadLine(); //开始异步读取 myProcess.WaitForExit(); //阻塞等待进程结束 myProcess.Close(); //关闭进程 myProcess.Dispose(); //释放资源 #region 进程是否已经释放 bool IsRunning = true; while (IsRunning) { IsRunning = false; Process[] ProcessArray = Process.GetProcessesByName("ffmpeg"); foreach (Process KillProcess in ProcessArray) { IsRunning = true; Thread.Sleep(100); } } #endregion myProcess = null; return true; } catch (Exception ex) { LogHelper.WriteErrLog("【生成缩略图】(GenerateThumbnails)缩略图生成失败," + ex.Message, ex); return false; } } /// /// 视频转码 /// /// 源视频 /// 目标视频存储路径 /// 宽 /// 高 /// public bool VideoTranscode(string VideoPathName, string VideoSavePathName, int Width, int Height) { while (myProcess != null) { Thread.Sleep(100); } Process[] KillProcessArray = Process.GetProcessesByName("ffmpeg"); foreach (Process KillProcess in KillProcessArray) { KillProcess.Kill(); } try { myProcess = new Process(); LogPath = CreateffmpegLog(); myProcess.StartInfo.FileName = FileToolsCommon.GetFileAbsolutePath(@"/ffmpeg/bin/ffmpeg.exe"); //ffmpeg.exe的绝对路径 myProcess.StartInfo.Arguments = "-i " + VideoPathName + " -acodec copy -vcodec libx264 -s " + Width + "*" + Height + " " + VideoSavePathName; myProcess.StartInfo.UseShellExecute = false; //不使用操作系统外壳程序启动 myProcess.StartInfo.RedirectStandardError = true; //重定向标准错误输出 myProcess.StartInfo.CreateNoWindow = true; //不显示程序窗口 myProcess.StartInfo.RedirectStandardInput = true; //用于模拟该进程控制台的输入 //外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN myProcess.ErrorDataReceived += new DataReceivedEventHandler(Output); myProcess.Start(); //启动线程 myProcess.BeginErrorReadLine(); //开始异步读取 myProcess.WaitForExit(); //阻塞等待进程结束 myProcess.Close(); //关闭进程 myProcess.Dispose(); //释放资源 #region 进程是否已经释放 bool IsRunning = true; while (IsRunning) { IsRunning = false; Process[] ProcessArray = Process.GetProcessesByName("ffmpeg"); foreach (Process KillProcess in ProcessArray) { IsRunning = true; Thread.Sleep(100); } } #endregion myProcess = null; Thread.Sleep(200); FileToolsCommon.DeleteFile(VideoPathName); return true; } catch (Exception ex) { LogHelper.WriteErrLog("【视频转码】(VideoTranscode)视频转码失败," + ex.Message, ex); return false; } } /// /// 创建日志文件 /// /// private string CreateffmpegLog() { string LogFileName = DateTime.Now.ToString("yyyyMMdd"); string LogFilePath = FileToolsCommon.GetFileAbsolutePath("/Log/FFMpegLog/"); FileToolsCommon.CreateDirectory(LogFilePath); string LogName = LogFilePath + LogFileName + ".log"; try { if (!FileToolsCommon.IsExistFile(LogName)) { FileToolsCommon.CreateFile(LogName); FileToolsCommon.AppendText(LogName, "\r\n****************************************************************************************************" + "****************************************************************************************************\r\n"); return LogName; } else { int num = 0; while (FileToolsCommon.GetFileSizeByMB(LogName) > 2) { num++; LogName = LogFilePath + LogFileName + "_" + num + ".log"; FileToolsCommon.CreateFile(LogName); } FileToolsCommon.AppendText(LogName, "\r\n****************************************************************************************************" + "****************************************************************************************************\r\n"); return LogName; } } catch (Exception) { return LogName; } } /// /// 输出结果 /// /// /// private void Output(object sendProcess, DataReceivedEventArgs output) { if (!string.IsNullOrEmpty(output.Data)) { FileToolsCommon.AppendText(LogPath, output.Data); } } //private void P_ErrorDataReceived(object sender, DataReceivedEventArgs e) //{ // //+= new DataReceivedEventHandler((s, message) => { Console.WriteLine(message.Data); }) // using (StreamWriter fs = new StreamWriter("E:\\项目\\测试\\Wpf测试\\bin\\Debug\\ffmpeg\\log.txt", true)) // { // fs.WriteLine(e.Data); // Debug.WriteLine(output.Data.ToString()); // } //} /// /// 获取麦克风 /// private string GetMicrophone() { List devs = new List(); MMDeviceEnumerator enumberator = new MMDeviceEnumerator(); MMDeviceCollection deviceCollection = enumberator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.All); for (int waveInDevice = 0; waveInDevice < WaveIn.DeviceCount; waveInDevice++) { WaveInCapabilities deviceInfo = WaveIn.GetCapabilities(waveInDevice); foreach (MMDevice device in deviceCollection) { try { if (device.FriendlyName.StartsWith(deviceInfo.ProductName)) { devs.Add(device.FriendlyName); break; } } catch (Exception) { } } } if (devs.Count > 0) { return devs[0]; } else { return ""; } } /// /// 获取声音输入设备完整名称 /// /// public static string GetInDeviceFull() { List devices = new List(); var enumberator = new MMDeviceEnumerator(); var deviceCollection = enumberator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.All); for (int waveInDevice = 0; waveInDevice < WaveIn.DeviceCount; waveInDevice++) { WaveInCapabilities deviceInfo = WaveIn.GetCapabilities(waveInDevice); foreach (MMDevice device in deviceCollection) { try { if (device.FriendlyName.StartsWith(deviceInfo.ProductName)) { devices.Add(device.FriendlyName); break; } } catch (Exception ex) { continue; } } } if (devices.Count > 0) { byte[] buffer = Encoding.UTF8.GetBytes(devices[0]); string MicrophoneName = Encoding.UTF8.GetString(buffer); // 统一使用UTF-8 return MicrophoneName; } else { return ""; } } /// /// 获取声音输入设备完整名称 /// /// public List GetInDeviceListFull() { List devices = new List(); var enumberator = new MMDeviceEnumerator(); var deviceCollection = enumberator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.All); for (int waveInDevice = 0; waveInDevice < WaveIn.DeviceCount; waveInDevice++) { WaveInCapabilities deviceInfo = WaveIn.GetCapabilities(waveInDevice); foreach (MMDevice device in deviceCollection) { try { if (device.FriendlyName.StartsWith(deviceInfo.ProductName)) { devices.Add(device.FriendlyName); break; } } catch (Exception ex) { continue; } } } return devices; } /// /// 录制麦克风的声音 /// private WaveInEvent waveIn = null; //new WaveInEvent(); /// /// 开始录制麦克风 /// public bool StartRecordAudio(string audioFile) { try { waveIn = new WaveInEvent(); //生成音频文件的对象 WaveFileWriter writer = new WaveFileWriter(audioFile, waveIn.WaveFormat); //开始录音,写数据 waveIn.DataAvailable += (s, a) => { writer.Write(a.Buffer, 0, a.BytesRecorded); }; //结束录音 waveIn.RecordingStopped += (s, a) => { writer.Dispose(); writer = null; waveIn.Dispose(); waveIn = null; try { FileToolsCommon.DeleteFile(audioFile); } catch (Exception) { } }; waveIn.StartRecording(); return true; } catch (Exception ex) { LogHelper.WriteErrLog("【麦克风】麦克风不可用:" + ex.Message, ex); return false; } } /// /// 结束录制音频 /// /// 1麦克风 2扬声器 public void StopRecordAudio(int type) { try { if (type == 1) { if (waveIn != null) { try { waveIn.StopRecording(); } catch (Exception) { waveIn = null; } } } else if (type == 2) { if (capture != null) { try { capture.StopRecording(); } catch (Exception) { capture = null; } } } } catch (Exception ex) { LogHelper.WriteErrLog("【麦克风】麦克风不可用:" + ex.Message, ex); } } /// /// 录制扬声器的声音 /// private WasapiLoopbackCapture capture = null; //new WasapiLoopbackCapture(); /// /// 开始录制扬声器 /// public bool StartRecordSpeakerAudio(string audioFile) { try { capture = new WasapiLoopbackCapture(); //生成音频文件的对象 WaveFileWriter writer = new WaveFileWriter(audioFile, capture.WaveFormat); capture.DataAvailable += (s, a) => { writer.Write(a.Buffer, 0, a.BytesRecorded); }; //结束录音 capture.RecordingStopped += (s, a) => { writer.Dispose(); writer = null; capture.Dispose(); capture = null; try { FileToolsCommon.DeleteFile(audioFile); } catch (Exception) { } }; capture.StartRecording(); return true; } catch (Exception ex) { LogHelper.WriteErrLog("【麦克风】麦克风不可用:" + ex.Message, ex); return false; } } } }