WPF桌面端开发7-使用FFMpeg进行推流

复制FFMpeg到目标目录

项目->属性->生成事件->生成前事件命令行

添加如下

复制目录

1
xcopy /Y /i /e $(ProjectDir)\ffmpeg $(TargetDir)\ffmpeg

复制文件

1
xcopy  /Y /d $(ProjectDir)\ffmpeg\* $(TargetDir)\ffmpeg\

获取音频输入设备

使用NuGet添加 NAudio

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
using NAudio.CoreAudioApi;
using System.Collections.Generic;

namespace ZJClassTool.Utils
{
public class ZJAudioModel : ZJNotifyModel
{
private string _name;

public string name
{
get { return _name; }
set
{
_name = value; OnPropertyChanged("name");
}
}

public string id { get; set; }
private bool _selected = true;

public bool selected
{
get { return _selected; }
set { _selected = value; OnPropertyChanged("selected"); }
}

public static List<ZJAudioModel> getAudioDevice()
{
List<ZJAudioModel> audioList = new List<ZJAudioModel>();
var enumerator = new NAudio.CoreAudioApi.MMDeviceEnumerator();

//允许你在某些状态下枚举渲染设备
var endpoints = enumerator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.Active);
foreach (var endpoint in endpoints)
{
ZJAudioModel audioModel = new ZJAudioModel();
audioModel.name = endpoint.FriendlyName;
audioModel.id = endpoint.ID;
audioList.Add(audioModel);
}
return audioList;
}
}
}

使用FFmpeg推流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
using System;
using System.Diagnostics;
using System.IO;

namespace ZJClassTool.Utils
{
internal class ZJRtmpPush
{
// ffmpeg进程
public static Process p = new Process();

// ffmpeg.exe实体文件路径
private static string ffmpegPath = AppDomain.CurrentDomain.BaseDirectory + "ffmpeg\\ffmpeg.exe";

/// <summary>
/// 功能: 开始录制
/// </summary>
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.Hidden;

var parastr = string.Format("-f gdigrab -framerate 15 -i desktop -f dshow -i audio=\"{0}\" -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -acodec libmp3lame \"{1}\"", audioDevice, outFilePath);
startInfo.Arguments = parastr;
p.StartInfo = startInfo;

p.Start();
}

/// <summary>
/// 功能: 开始推流
/// </summary>
public static void StartPush(string audioDevice, string pushUrl)
{
/*转码,视频录制设备:gdigrab;录制对象:桌面;
* 音频录制方式:dshow;
* 视频编码格式:h.264;*/
ProcessStartInfo startInfo = new ProcessStartInfo(ffmpegPath);
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
var parastr = string.Format("-f gdigrab -framerate 15 -i desktop -f dshow -i audio=\"{0}\" -filter:v scale=w=trunc(oh*a/2)*2:h=720 -vcodec libx264 -preset:v ultrafast -acodec libmp3lame -maxrate 1000k -pix_fmt yuv422p -f flv \"{1}\"", audioDevice, pushUrl);
startInfo.Arguments = parastr;
p.StartInfo = startInfo;
// Console.WriteLine("parastr:" + parastr);
p.Start();
}

/// <summary>
/// 功能: 停止录制
/// </summary>
public static void Stop()
{
p.Kill();
p.StartInfo.Arguments = "";
}
}
}

实际上执行的推流命令

1
ffmpeg -f gdigrab -framerate 15 -i desktop -f dshow -i audio="Internal Microphone (Cirrus Logic CS8409 (AB 51))" -filter:v scale=w=trunc(oh*a/2)*2:h=720 -vcodec libx264 -preset:v ultrafast -acodec libmp3lame -maxrate 1000k -pix_fmt yuv422p -f flv "rtmp://live.psvmc.cn/test/01"

具体参数根据自己实际情况调整即可