前言
视频录制我测试了三种不同的方式
- FFMPEG(调用EXE方式)
- Accord
- AForge
AForge包括
- AForge
- AForge.Video
- AForge.Video.FFMPEG
- AForge.Video.DirectShow
Accord包括
- Accord
- Accord.Video
- Accord.Video.FFMPEG
- Accord.Video.DirectShow
官方文档
Accord
http://accord-framework.net/docs/html/R_Project_Accord_NET.htm
https://github.com/accord-net/framework
NAudio
https://github.com/naudio/NAudio
视频录制
AForge和Accord
FFMPEG音视频均可录制 后两者只能录制视频
AForge 录制的视频颜色有偏差,最终选择了Accord
安装
1 | Install-Package Accord.Video.DirectShow -Version 3.8.0 |
其中
Accord.Video.FFMPEG
负责文件的写入。Accord.Video
获取桌面的帧,这个库在Accord.Video.FFMPEG
的依赖中,会自动安装。Accord.Video.DirectShow
可以获取摄像头的帧,如果不录制摄像头,可以不用安装这个
音频录制
音频录制可以使用 NAudio
和Accord.DirectSound
,
本来想都用Accord
来录制桌面和麦克风及扬声器,但是后来决定使用NAudio
,
原因如下:
Accord.DirectSound
只支持麦克风录制,不支持扬声器录制。- 使用
Accord
最新的稳定版本3.8.0
,在同时录制桌面和麦克风的时候一直报错,Github这个仓库也好几年没更新,上面也没有示例,很多和我提出一样的Issues
,也没有解决,目前还不知道是库的问题,还是调用的问题。
所以音频录制使用了NAudio库
安装
1 | Install-Package NAudio -Version 1.9.0 |
音视频合并
音视频合成使用了NReco.VideoConverter库,这个库本质也是用FFMpeg进行音视频合并的。
1 | Install-Package NReco -Version 2.0.3.0 |
音频处理
使用NAudio
安装
1 | Install-Package NAudio -Version 1.9.0 |
麦克风列表
1 | using NAudio.Wave; |
打印如下
-1: Microsoft Sound Mapper
0: 麦克风 (Realtek(R) Audio)
注意上面是从-1开始遍历的,我们获取麦克风设备的时候可以从0遍历。
方式2
1 | using NAudio.CoreAudioApi; |
扬声器列表
获取默认的扬声器及其声音大小
1 | using NAudio.CoreAudioApi; |
结果
PHL 271V8 (NVIDIA High Definition Audio) 声音大小:100
扬声器/听筒 (Realtek(R) Audio) 声音大小:29
默认的麦克风和扬声器
1 | var defaultCaptureDevice = WasapiCapture.GetDefaultCaptureDevice(); |
获取麦克风实时音量
xaml
1 | <ProgressBar |
代码
1 | // 定义 |
停止
1 | // 停止时调用 |
获取麦克风列表
1 | for (int n = -1; n < WaveIn.DeviceCount; n++) |
打印如下
-1: Microsoft 声音映射器
0: 麦克风 (Realtek(R) Audio)
注意上面是从-1开始遍历的,我们获取麦克风设备的时候可以从0遍历。
设置麦克风
设置对应的索引
1 | waveIn.DeviceNumber = 0; |
官方文档
https://github.com/naudio/NAudio/blob/master/Docs/RecordingLevelMeter.md
获取扬声器实时音量
1 | // 定义 |
注意
获取扬声器声音大小不受系统声音设置大小影响,所以要想获取真实用户听到的声音大小要用
采集的声音大小
*扬声器设置的声音大小
设置扬声器的音量
1 | private void SetCurrentSpeakerVolume(int volume) |
录制麦克风和扬声器
录制麦克风
1 | using System; |
注意
这里在初始化类的时候就直接调用录制了,原因在于,如果同时录制音视频的时候,同时开启的时候,由于硬件原因导致启动的时间有先后从而会导致声画不同步。
后文中的视频录制也是同样的原因。
录制扬声器
1 | using System; |
使用Accord
Accord.DirectSound
安装依赖
1 | Install-Package Accord.Audio -Version 3.8.0 |
麦克风列表
1 | using Accord.DirectSound; |
结果
主声音捕获驱动程序
麦克风 (Realtek(R) Audio)
扬声器列表
1 | /// <summary> |
结果
主声音驱动程序
扬声器/听筒 (Realtek(R) Audio)
PHL 271V8 (NVIDIA High Definition Audio)
Accord.Video.DirectShow
麦克风列表
这种方式的好处在于能获取到虚拟的音频设备。
1 | using Accord.Video.DirectShow; |
结果
virtual-audio-capturer @device:sw:{33D9A762-90C8-11D0-BD43-00A0C911CE86}{8E14549B-DB61-4309-AFA1-3578E927E935}
麦克风 (Realtek(R) Audio) @device:cm:{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave:{41E427BE-4D43-4FA3-A0AA-CE09C9B127F5}
麦克风录制
Accord.DirectSound
1 | private static readonly object WriterLock = new object(); |
音频状态获取
改变系统音量
1 | [ ] |
改变软件音量
改变软件音量 但不改变系统音量
1 | [ ] |
设置默认音频设备
目前还没有用代码设置默认音频设备的方法
打开系统声音设置,让用户操作
1 | Process.Start("mmsys.cpl"); |
摄像头
摄像头列表
获取摄像头列表
1 | <ComboBox |
c#
1 | using Accord.Video; |
过滤常见的虚拟设备
1 | var devs = new FilterInfoCollection(FilterCategory.VideoInputDevice); //获取摄像头列表 |
注意
new VideoCaptureDevice(CameraName)
中CameraName
传入的是MonikerString
显示的时候使用
Name
摄像头画面
1 | if (CmbCameraList.SelectedIndex >= 0) |
我的方案
安装相关依赖
1 | Install-Package Accord.Video.FFMPEG -Version 3.7.0 |
重新安装所有依赖
1 | Update-Package –reinstall |
添加系统依赖
1 | <Reference Include="System.Drawing" /> |
其中
- Accord 视频处理
- NAudio 音频处理
- NReco 音视频合并
音视频分开录制 音频如果麦克风和扬声器都录制的话,也要分开录制,最后再合并所有的流。
视频录制
桌面录制
工具类
整体
1 | /* |
绘制光标
1 | [ ] |
绘制圆点
1 | // 帧返回时绘制上圆点 |
调用方式
1 | // 当前窗体指针 |
视频写入
1 | using Accord.Video.FFMPEG; |
注意以下几点
- Open时传入的宽高要和写入时的宽高保持一致。
- 宽高必须是2的整数倍。
- Open视频文件时,请加上全局锁,否则多线程并发有异常抛出。
- Close视频文件时,请使用Open的全局锁,否则会在Open 时出现
AccessViolationException
异常。
桌面流读取
1 | using Accord.Video; |
组件录制
1 | /// <summary> |
摄像头录制
录制
1 | using Accord.Video; |
音视频合并
1 | using NReco.VideoConverter; |
参数说明
amix=inputs=2
: 表示混音文件个数 , 有 2 个文件进行混音 ;duration=longest
: 设置混音时间对齐策略 ,longest
表示最长的音频文件持续时间 ,shortest
表示最短输入的持续时间 ,first
表示第一个文件的持续时间 ;dropout_transition=2
: 表示输入流结束时 , 音量从满音量到 0 音量渐弱 2 秒消失 ;
生成缩略图
1 | /// <summary> |
获取视频时长
1 | /// <summary> |
音视频录制工具类
1 | /* |
调用
1 | IsRecording = !IsRecording; |
打开系统声音设置
1 | Process.Start("mmsys.cpl"); |
调用本地播放
1 | Process pro = new Process |
音视频参数计算
音频
采样率和比特率(码率)之间的公式如下:
比特率 = 采样率 × 样本深度 × 声道数
AudioBitRate = SampleRate × bits × channels
其中,采样率表示每秒钟采集的样本数,单位为Hz(赫兹);样本深度表示每个采样值所占的位数,通常为16或24位;声道数表示音频信号的通道数,通常为单声道或立体声。
例如,对于一段立体声音乐,采样率为44100Hz,样本深度为16位,声道数为2,则它的比特率为:
比特率 = 44100 × 16 × 2 = 1411200 bit/s = 1.41 Mbps
采样率为44100Hz,样本深度为16位,声道数为1,则它的比特率为:
比特率 = 44100 × 16 × 1 = 705600 bit/s
因为
1 byte = 8 bits
所以上面的示例1s产生的byte为
1411200 / 8 = 176400
音频计算中使用到的参数
1 | //帧率 |
音频的比特率
1 | 比特率 = 采样率 * 位深 * 声道数 |
音频帧大小
1 | 音频帧大小 = 比特率 * 1秒 / 8 / 声道数 / 帧率 |
其中比特率 * 1秒 / 8
为1秒的byte数。