|
@@ -22,6 +22,7 @@ namespace Common.system
|
22
|
22
|
/// </summary>
|
23
|
23
|
public class FFMpeg
|
24
|
24
|
{
|
|
25
|
+ #region 变量
|
25
|
26
|
public Process myProcess = null;
|
26
|
27
|
|
27
|
28
|
/// <summary>
|
|
@@ -42,6 +43,120 @@ namespace Common.system
|
42
|
43
|
/// 是否可以录制麦克风
|
43
|
44
|
/// </summary>
|
44
|
45
|
private bool IsRecordMicrophone = true;
|
|
46
|
+ #endregion
|
|
47
|
+
|
|
48
|
+ #region 直播录屏推流
|
|
49
|
+ /// <summary>
|
|
50
|
+ /// 录制屏幕并推流
|
|
51
|
+ /// </summary>
|
|
52
|
+ /// <param name="RTMPPath">RTMP流媒体服务器</param>
|
|
53
|
+ /// <param name="NodeKey">节点和Key</param>
|
|
54
|
+ /// <param name="size">大小</param>
|
|
55
|
+ /// <param name="ErrMessage">错误信息返回</param>
|
|
56
|
+ /// <returns></returns>
|
|
57
|
+ public bool StartRecordingVideo(string RTMPPath, string NodeKey, Size size, out string ErrMessage)
|
|
58
|
+ {
|
|
59
|
+ while (myProcess != null)
|
|
60
|
+ {
|
|
61
|
+ Thread.Sleep(100);
|
|
62
|
+ }
|
|
63
|
+ ErrMessage = null;
|
|
64
|
+ string RTMPPathName = "rtmp://" + RTMPPath + "/" + NodeKey;//rtmp://live.xhkjedu.com/live/test
|
|
65
|
+ Process[] KillProcessArray = Process.GetProcessesByName("ffmpeg");
|
|
66
|
+ foreach (Process KillProcess in KillProcessArray)
|
|
67
|
+ {
|
|
68
|
+ KillProcess.Kill();
|
|
69
|
+ }
|
|
70
|
+ myProcess = new Process();
|
|
71
|
+ LogPath = CreateffmpegLog();
|
|
72
|
+ string MicrophoneName = null;
|
|
73
|
+ #region 检测麦克风扬声器
|
|
74
|
+ string AudioPath = FileToolsCommon.GetFileAbsolutePath("/temp/audio/");
|
|
75
|
+ FileToolsCommon.CreateDirectory(AudioPath);
|
|
76
|
+ string audioSpeakerPath = AudioPath + "adoS" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".m";//FileToolsCommon.GetFileAbsolutePath("adoS.m");
|
|
77
|
+ string audioMicrophonePath = AudioPath + "adoM" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".m";//FileToolsCommon.GetFileAbsolutePath("adoM.m");
|
|
78
|
+ try
|
|
79
|
+ {
|
|
80
|
+ FileToolsCommon.DeleteFile(audioSpeakerPath);
|
|
81
|
+ FileToolsCommon.DeleteFile(audioMicrophonePath);
|
|
82
|
+ }
|
|
83
|
+ catch (Exception)
|
|
84
|
+ {
|
|
85
|
+
|
|
86
|
+ }
|
|
87
|
+ if (StartRecordSpeakerAudio(audioSpeakerPath))
|
|
88
|
+ {
|
|
89
|
+ IsRecordSpeaker = true;
|
|
90
|
+ }
|
|
91
|
+ else
|
|
92
|
+ {
|
|
93
|
+ //无法录制扬声器音频
|
|
94
|
+ IsRecordSpeaker = false;
|
|
95
|
+ }
|
|
96
|
+ StopRecordAudio(2);
|
|
97
|
+ Thread.Sleep(100);
|
|
98
|
+ if (StartRecordAudio(audioMicrophonePath))
|
|
99
|
+ {
|
|
100
|
+ IsRecordMicrophone = true;
|
|
101
|
+ }
|
|
102
|
+ else
|
|
103
|
+ {
|
|
104
|
+ //无法录制麦克风
|
|
105
|
+ IsRecordMicrophone = false;
|
|
106
|
+ }
|
|
107
|
+ StopRecordAudio(1);
|
|
108
|
+ #endregion
|
|
109
|
+ myProcess.StartInfo.FileName = FileToolsCommon.GetFileAbsolutePath(@"/ffmpeg/bin/ffmpeg.exe"); //ffmpeg.exe的绝对路径
|
|
110
|
+ string SpeakerStr = "";
|
|
111
|
+ string MicrophoneStr = "";
|
|
112
|
+ if (IsRecordSpeaker)
|
|
113
|
+ {
|
|
114
|
+ SpeakerStr = "-f dshow -i audio=\"virtual-audio-capturer\" ";
|
|
115
|
+ }
|
|
116
|
+ if (IsRecordMicrophone)
|
|
117
|
+ {
|
|
118
|
+ MicrophoneName = GetMicrophoneName();
|
|
119
|
+ if (!string.IsNullOrWhiteSpace(MicrophoneName))
|
|
120
|
+ {
|
|
121
|
+ MicrophoneStr = "-f dshow -i audio=\"" + MicrophoneName + "\" -filter_complex amix=inputs=2:duration=first:dropout_transition=2 ";
|
|
122
|
+ }
|
|
123
|
+ }
|
|
124
|
+
|
|
125
|
+ 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 flv " + RTMPPathName;
|
|
126
|
+
|
|
127
|
+ if (OutputVideoLog)
|
|
128
|
+ {
|
|
129
|
+ LogHelper.WriteInfoLog("【录屏】:" + myProcess.StartInfo.Arguments);
|
|
130
|
+ }
|
|
131
|
+ FileToolsCommon.AppendText(LogPath, "【录屏】:" + myProcess.StartInfo.Arguments + "\r\n");
|
|
132
|
+ myProcess.StartInfo.UseShellExecute = false; //不使用操作系统外壳程序启动
|
|
133
|
+ myProcess.StartInfo.RedirectStandardError = true; //重定向标准错误输出
|
|
134
|
+ myProcess.StartInfo.CreateNoWindow = true; //不显示程序窗口
|
|
135
|
+ myProcess.StartInfo.RedirectStandardInput = true; //用于模拟该进程控制台的输入
|
|
136
|
+ myProcess.ErrorDataReceived += new DataReceivedEventHandler(Output);
|
|
137
|
+ try
|
|
138
|
+ {
|
|
139
|
+ myProcess.Start();
|
|
140
|
+ myProcess.BeginErrorReadLine();
|
|
141
|
+ }
|
|
142
|
+ catch (Exception ex)
|
|
143
|
+ {
|
|
144
|
+ if (ex.Message.Contains("访问"))
|
|
145
|
+ {
|
|
146
|
+ ErrMessage = "访问被拒绝,请关闭杀毒软件或新任此软件后重试!";
|
|
147
|
+ }
|
|
148
|
+ else
|
|
149
|
+ {
|
|
150
|
+ ErrMessage = ex.Message + " 请关闭杀毒软件或信任此软件后重试!";
|
|
151
|
+ }
|
|
152
|
+ LogHelper.WriteErrLog("【录音】(StartRecordingAudio)" + ErrMessage, ex);
|
|
153
|
+ myProcess.Dispose();
|
|
154
|
+ myProcess = null;
|
|
155
|
+ return false;
|
|
156
|
+ }
|
|
157
|
+ return true;
|
|
158
|
+ }
|
|
159
|
+ #endregion
|
45
|
160
|
/// <summary>
|
46
|
161
|
/// 录制屏幕
|
47
|
162
|
/// </summary>
|