using
System;
using
System.Collections.Generic;
using
System.Diagnostics;
using
System.IO;
using
System.Linq;
using
System.Text;
using
System.Threading.Tasks;
using
Microsoft.DirectX;
using
Microsoft.DirectX.DirectSound;
using
System.Runtime.InteropServices;
namespace
ClassTool
{
public
class
RecordHelper
{
#region
模拟控制台信号需要使用的api
[DllImport(
"
kernel32.dll
"
)]
static
extern
bool
GenerateConsoleCtrlEvent(
int
dwCtrlEvent,
int
dwProcessGroupId);
[DllImport(
"
kernel32.dll
"
)]
static
extern
bool
SetConsoleCtrlHandler(IntPtr handlerRoutine,
bool
add);
[DllImport(
"
kernel32.dll
"
)]
static
extern
bool
AttachConsole(
int
dwProcessId);
[DllImport(
"
kernel32.dll
"
)]
static
extern
bool
FreeConsole();
#endregion
//
ffmpeg进程
static
Process p =
new
Process();
//
ffmpeg.exe实体文件路径
static
string
ffmpegPath = AppDomain.CurrentDomain.BaseDirectory +
"
ffmpeg\\ffmpeg.exe
"
;
///
///
获取声音输入设备列表
///
///
声音输入设备列表
public
static
CaptureDevicesCollection GetAudioList()
{
CaptureDevicesCollection collection
=
new
CaptureDevicesCollection();
return
collection;
}
///
///
功能: 开始录制
///
public
static
void
Start(
string
audioDevice,
string
outFilePath)
{
if
(File.Exists(outFilePath))
{
File.Delete(outFilePath);
}
/*
转码,视频录制设备:gdigrab;录制对象:桌面;
* 音频录制方式:dshow;
* 视频编码格式:h.264;
*/
ProcessStartInfo startInfo
=
new
ProcessStartInfo(ffmpegPath);
startInfo.WindowStyle
=
ProcessWindowStyle.Normal;
startInfo.Arguments
=
"
-f gdigrab -framerate 15 -i desktop -f dshow -i audio=\"
"
+ audioDevice +
"
\" -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -acodec libmp3lame \"
"
+ outFilePath +
"
\"
"
;
p.StartInfo
=
startInfo;
p.Start();
}
///
///
功能: 停止录制
///
public
static
void
Stop()
{
AttachConsole(p.Id);
SetConsoleCtrlHandler(IntPtr.Zero,
true
);
GenerateConsoleCtrlEvent(
0
,
0
);
FreeConsole();
}
}
}
开始那几个api接口是用来模拟ctrl+c命令的。本来以为在停止录制的时候直接kill掉进程就好,结果导致生成的视频文件直接损坏了。手动使用ffmpeg.exe的时候发现ctrl+c可以直接结束录制并且不会损坏视频文件,于是采用这种方法,在点击停止按钮时模拟ctrl+c来退出ffmpeg。
ffmpeg的命令参数里,gdigrab是ffmpeg内置的屏幕录制设备,但是这个设备不能同时采集音频,于是又用到了后面的dshow。这里有个问题很奇怪,用ffmpeg获取音频设备列表时,设备的名称如果超过31个字符的话会被截断,而若是将完整的设备名传到参数里则无法进行音频采集,只能将截断的设备名称传进去,不知道为什么……