用Naudio录制音频,以下代码是把录音数据写入到一个音频文件中,然后打开播放
public class RecordController
{
WaveIn mWavIn;
WaveFileWriter mWavWriter;
public RecordController()
{
}
/// <summary>
/// 开始录音
/// </summary>
/// <param name="filePath">录音文件路径</param>
public int StartRecord(string filePath)
{
//录音文件路径
mWavIn = new WaveIn();
// 设置录音参数
mWavIn.WaveFormat = new WaveFormat(16000, 16, 1);
// 添加DataAvailable事件处理程序
mWavIn.DataAvailable += MWavIn_DataAvailable;
// 创建WaveFileWriter对象
mWavWriter = new WaveFileWriter(filePath, mWavIn.WaveFormat);
if (WaveInEvent.DeviceCount > 0)
{
//遍历录音设备
for (int i = 0; i < WaveInEvent.DeviceCount; i++)
{
var capabilities = WaveInEvent.GetCapabilities(i);
Console.WriteLine($"设备 {i}: {capabilities.ProductName} - {capabilities.Channels} 个声道");
}
//mWavIn.DeviceNumber 选择录音设备
// 开始录音
mWavIn.StartRecording();
return 1;
}
else
{
return 0;
}
}
/// <summary>
/// 停止录音
/// </summary>
public void StopRecord()
{
// 停止录音
mWavIn?.StopRecording();
// 释放WaveIn对象
mWavIn?.Dispose();
mWavIn = null;
// 关闭WaveFileWriter对象
mWavWriter?.Close();
mWavWriter = null;
}
/// <summary>
/// DataAvailable事件处理程序
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MWavIn_DataAvailable(object sender, WaveInEventArgs e)
{
// 写入录音数据
mWavWriter.Write(e.Buffer, 0, e.BytesRecorded);
}
//播放录音
public void PlayAudio(MemoryStream stream)
{
WaveStream waveStream = new RawSourceWaveStream(stream, new WaveFormat(16000, 16, 1));
// 创建一个输出设备
IWavePlayer waveOut = new WaveOut();
// 播放音频
waveOut.Init(waveStream);
waveOut.Play();
}
}
如果是要把录音数据实时上传到后台可在MWavIn_DataAvailable方法中写入以下代码
byte[] bt = e.Buffer;
StreamASR streamASR = new StreamASR();
streamASR.action = "类型";
streamASR.audio_data = bt;
string str = JsonConvert.SerializeObject(streamASR);
//把str数据上传
如果要实时播放录音数据不限制格式,可使用ffplay来实现如:
Stream stream;
//把这段代码放置初始化中
ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = "ffplay",
Arguments = " -f s16le -ar 16000 -ac 1 -i -",
UseShellExecute = false,
RedirectStandardInput = true,
CreateNoWindow = true
};
Process ffplayProcess = Process.Start(startInfo);
stream = ffplayProcess.StandardInput.BaseStream;
//把获取到的数据实时写入到通道中
stream.Write(e.Buffer, 0, e.BytesRecorded);
stream.flush();
//结束播放后关闭
stream?.close();
如果要实时播放amr格式的音频需要写入amr格式的头部字段
Stream stream;
//实时播放amr音频格式
ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = "ffplay",
Arguments = "-fflags nobuffer -nodisp -probesize 32 -analyzeduration 0 -f amr -i -",//showmode 0 会导致声音有时播放不了
UseShellExecute = false,
RedirectStandardInput = true,
CreateNoWindow = true
};
Process ffplayProcess = Process.Start(startInfo);
stream = ffplayProcess.StandardInput.BaseStream;
//写入amr头部数据
string[] str = { "23", "21", "41", "4d", "52", "0a" };
byte[] bts = new byte[6];
for (int i = 0; i < str.Length; i++)
{
bts[i] = Convert.ToByte(str[i], 16);
}
stream.Write(bts, 0, bts.Length);
//输入一段无效的音频数据,防止播放延时严重
string[] str2 = { "3c", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00" };
byte[] bts2 = new byte[32];
for (int i = 0; i < str2.Length; i++)
{
bts2[i] = Convert.ToByte(str2[i], 16);
}
stream.Write(bts2, 0, bts2.Length);
stream.Write(bts2, 0, bts2.Length);
stream.flush();//处理播放声音延迟