目录
概述
AudioRecorder 快速入门
输出格式详解
录制到流
停止录制与统计信息
模拟录制模式
完整示例:录音并回放
录制过程中的错误处理
平台注意事项
进阶用法
概述
AudioRecorder 是 SimpleAudioPlayer 提供的录音组件,与 AudioPlayer 同属 SimpleAudio 命名空间。它使用本机音频 API 从麦克风或其他输入设备捕获音频数据,支持多种输出格式。
using SimpleAudioPlayer;// 创建录音机
using var recorder = new AudioRecorder();// 开始录制到文件
recorder.Start(@"C:\Recordings\test.wav");// 停止录制
recorder.Stop();核心功能:
支持 WAV、AAC (ADTS)、M4A、Raw PCM 四种输出格式
输出到文件或任意
Stream录制统计信息(帧数、丢帧数)
模拟录制模式(测试用,不依赖麦克风硬件)
跨平台兼容
AudioRecorder 快速入门
录制到 WAV 文件
WAV 是最简单、兼容性最好的格式,不需要编码器,所有平台都支持:
using SimpleAudioPlayer;using var recorder = new AudioRecorder();Console.WriteLine("开始录音... 按 Enter 停止");
recorder.Start(@"C:\Recordings\my_audio.wav");
Console.ReadLine();
recorder.Stop();Console.WriteLine("录音已保存到 C:\\Recordings\\my_audio.wav");录制参数: Start(filename) 使用默认参数(44.1kHz, 16-bit, mono)。
录制到 AAC 文件
AAC 格式需要编码器,文件体积更小:
using SimpleAudioPlayer;using var recorder = new AudioRecorder();recorder.Start(@"C:\Recordings\my_audio.aac");
Console.WriteLine("正在录制 AAC...");
Thread.Sleep(5000); // 录制 5 秒
recorder.Stop();Console.WriteLine("录音完成");输出格式详解
设置输出格式
// 设置格式后再开始录制
recorder.OutputFormat = RecordingFileFormat.Wav; // WAV
recorder.OutputFormat = RecordingFileFormat.Aac; // AAC (ADTS)
recorder.OutputFormat = RecordingFileFormat.M4A; // M4A (AAC in MP4)
recorder.OutputFormat = RecordingFileFormat.Pcm; // Raw PCM格式对比
格式 | 文件扩展名 | 有损/无损 | 编码器需求 | 兼容性 | 文件大小 | 适用场景 |
|---|---|---|---|---|---|---|
WAV | .wav | 无损 (PCM) | 无 | 极高 | 大 | 录音编辑、存档 |
AAC (ADTS) | .aac | 有损 | FFmpeg | 高 | 小 | 语音笔记、播客 |
M4A | .m4a | 有损 | FFmpeg | 高 | 小 | 移动设备分享 |
Raw PCM | .raw | 无损 (PCM) | 无 | 低(无头) | 大 | 自定义处理 |
设置采样率和声道
// 录制前配置参数
recorder.SampleRate = 48000; // 48kHz
recorder.Channels = 2; // 立体声
recorder.BitDepth = 16; // 16-bitrecorder.OutputFormat = RecordingFileFormat.Wav;
recorder.Start(@"C:\Recordings\high_quality.wav");推荐的录音配置:
场景 | 采样率 | 声道 | 位深 | 格式 |
|---|---|---|---|---|
语音笔记 | 16000 | Mono | 16 | WAV 或 AAC |
播客录制 | 44100 | Mono | 16 | WAV |
音乐录制 | 48000 | Stereo | 24 | WAV |
移动分享 | 44100 | Stereo | 16 | M4A |
语音识别 | 16000 | Mono | 16 | WAV |
自定义后处理 | 48000 | Stereo | 24 | Raw PCM |
录制到流
除了保存到文件,还可以录制到任意 Stream 对象:
using SimpleAudioPlayer;using var outputStream = new MemoryStream();
using var recorder = new AudioRecorder();// 录制到流(需要指定格式)
recorder.OutputFormat = RecordingFileFormat.Wav;
recorder.Start(outputStream, RecordingFileFormat.Wav);Console.WriteLine("正在录音到内存流... 按 Enter 停止");
Console.ReadLine();recorder.Stop();// 此时 outputStream 包含完整的 WAV 文件数据
Console.WriteLine($"录制了 {outputStream.Length} 字节");// 可以保存或进一步处理
await File.WriteAllBytesAsync(@"C:\Recordings\from_stream.wav", outputStream.ToArray());流的优势:
录制到
MemoryStream直接用于播放或上传录制到
FileStream实现自定义文件名逻辑录制到
NetworkStream实时传输音频录制到
CryptoStream加密保存
上传到服务器的示例
using SimpleAudioPlayer;// 在内存中录制
using var audioStream = new MemoryStream();
using var recorder = new AudioRecorder();recorder.OutputFormat = RecordingFileFormat.Aac;
recorder.Start(audioStream, RecordingFileFormat.Aac);Console.WriteLine("录音中... 按 Enter 停止并上传");
Console.ReadLine();recorder.Stop();// 上传到服务器
audioStream.Position = 0;
using var httpClient = new HttpClient();
using var content = new StreamContent(audioStream);
content.Headers.ContentType = new MediaTypeHeaderValue("audio/aac");var response = await httpClient.PostAsync("https://api.example.com/upload", content);
Console.WriteLine($"上传结果: {response.StatusCode}");停止录制与统计信息
Stop() 返回一个 MaResult 对象,包含录制统计信息:
using SimpleAudioPlayer;using var recorder = new AudioRecorder();recorder.Start(@"C:\Recordings\stats.wav");
Thread.Sleep(3000);
var result = recorder.Stop();Console.WriteLine($"录制统计:");
Console.WriteLine($" 采样率: {result.SampleRate} Hz");
Console.WriteLine($" 声道数: {result.Channels}");
Console.WriteLine($" 位深: {result.BitsPerSample}");
Console.WriteLine($" 总帧数: {result.TotalFrames}");
Console.WriteLine($" 丢帧数: {result.FramesDropped}");
Console.WriteLine($" 时长: {result.Duration}");if (result.FramesDropped > 0)
{double dropRate = (double)result.FramesDropped / result.TotalFrames * 100;Console.WriteLine($" ⚠ 注意: 丢帧率 {dropRate:F2}%,可能存在录音质量问题");
}MaResult 属性
属性 | 类型 | 说明 |
|---|---|---|
|
| 录制采样率 (Hz) |
|
| 声道数 |
|
| 位深 |
|
| 采集的 PCM 帧总数 |
|
| 丢帧数(因缓冲区溢出丢失的帧) |
|
| 录制时长 |
|
| 输出文件路径(如果录制到文件) |
模拟录制模式
模拟录制模式不需要麦克风硬件,在测试环境中非常有用。它生成静音 PCM 数据,让你可以在没有音频输入设备的机器上测试录制流程。
using SimpleAudioPlayer;// 启用模拟录制模式(必须在 Start 之前设置)
AudioRecorder.SimulateRecording = true;using var recorder = new AudioRecorder();recorder.OutputFormat = RecordingFileFormat.Wav;
recorder.Start(@"C:\Recordings\test_simulated.wav");Thread.Sleep(3000);var result = recorder.Stop();
Console.WriteLine($"模拟录制完成,时长: {result.Duration}");// 测试完成后关闭模拟模式
AudioRecorder.SimulateRecording = false;模拟录制适用场景:
CI/CD 流水线中测试录音功能
没有麦克风的开发环境
录制功能的单元测试
UI 自动化测试
在测试中使用
[Fact]
public void TestRecordingAndPlayback()
{// 启用模拟模式AudioRecorder.SimulateRecording = true;var recorder = new AudioRecorder();var player = new AudioPlayer();using var audioStream = new MemoryStream();// 模拟录制 2 秒recorder.OutputFormat = RecordingFileFormat.Wav;recorder.Start(audioStream, RecordingFileFormat.Wav);Thread.Sleep(2000);recorder.Stop();// 验证录制结果var result = recorder.Stop();Assert.True(result.TotalFrames > 0);Assert.Equal(0, result.FramesDropped);// 回放录制的音频audioStream.Position = 0;var handle = new StreamHandle(audioStream);player.Load(handle);player.Play();AudioRecorder.SimulateRecording = false;
}完整示例:录音并回放
以下程序录制一段音频、保存到文件、然后立即回放:
using SimpleAudioPlayer;Console.WriteLine("SimpleAudioPlayer 录音与回放示例");
Console.WriteLine("====================================");
Console.WriteLine();// 选择输出格式
Console.WriteLine("选择输出格式:");
Console.WriteLine(" 1. WAV (无损)");
Console.WriteLine(" 2. AAC (有损,体积小)");
Console.WriteLine(" 3. M4A (AAC in MP4)");
Console.Write("请选择 (1-3) [默认 1]: ");var formatChoice = Console.ReadKey(true);
AudioOutputFormat format = RecordingFileFormat.Wav;
string extension = ".wav";switch (formatChoice.KeyChar)
{case '2':format = RecordingFileFormat.Aac;extension = ".aac";Console.WriteLine("AAC 格式");break;case '3':format = RecordingFileFormat.M4A;extension = ".m4a";Console.WriteLine("M4A 格式");break;default:Console.WriteLine("WAV 格式");break;
}// 选择录音配置
Console.WriteLine();
Console.WriteLine("选择录音质量:");
Console.WriteLine(" 1. 语音 (16kHz, Mono, 16-bit)");
Console.WriteLine(" 2. 标准 (44.1kHz, Mono, 16-bit)");
Console.WriteLine(" 3. 高保真 (48kHz, Stereo, 24-bit)");
Console.Write("请选择 (1-3) [默认 2]: ");var qualityChoice = Console.ReadKey(true);
int sampleRate = 44100;
int channels = 1;
int bitDepth = 16;switch (qualityChoice.KeyChar)
{case '1':sampleRate = 16000;Console.WriteLine("语音质量");break;case '3':sampleRate = 48000;channels = 2;bitDepth = 24;Console.WriteLine("高保真质量");break;default:Console.WriteLine("标准质量");break;
}// 生成输出文件名
string outputDir = @"C:\Recordings";
Directory.CreateDirectory(outputDir);
string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
string outputPath = Path.Combine(outputDir, $"recording_{timestamp}{extension}");Console.WriteLine();
Console.WriteLine($"输出文件: {outputPath}");
Console.WriteLine($"格式: {format}, 采样率: {sampleRate}Hz, 声道: {(channels == 1 ? "Mono" : "Stereo")}, 位深: {bitDepth}");
Console.WriteLine();
Console.WriteLine("准备就绪!按 Enter 开始录音...");
Console.ReadLine();// 创建录音机并配置
using var recorder = new AudioRecorder();
recorder.SampleRate = sampleRate;
recorder.Channels = channels;
recorder.BitDepth = bitDepth;
recorder.OutputFormat = format;// 开始录音
Console.WriteLine("正在录音... 按 Enter 停止");
recorder.Start(outputPath);// 显示录音时长
var startTime = DateTime.Now;
var cts = new CancellationTokenSource();_ = Task.Run(async () =>
{while (!cts.IsCancellationRequested){var elapsed = DateTime.Now - startTime;Console.Write($"\r录音中... {elapsed:mm\\:ss\\.ff}");await Task.Delay(100);}
});Console.ReadLine();
cts.Cancel();// 停止录音
var result = recorder.Stop();
Console.WriteLine();
Console.WriteLine("=== 录音统计 ===");
Console.WriteLine($" 时长: {result.Duration}");
Console.WriteLine($" 总帧数: {result.TotalFrames:N0}");
Console.WriteLine($" 丢帧数: {result.FramesDropped:N0}");
Console.WriteLine($" 文件大小: {new FileInfo(outputPath).Length / 1024.0:F1} KB");
Console.WriteLine();// 询问是否回放
Console.Write("是否立即回放?(Y/N) [默认 Y]: ");
var playKey = Console.ReadKey(true);
Console.WriteLine();if (playKey.KeyChar != 'n' && playKey.KeyChar != 'N')
{Console.WriteLine("正在回放录音...");using var player = new AudioPlayer();player.PlaybackStateChanged += (s, e) =>{if (e.NewState == PlaybackState.Completed){Console.WriteLine("回放完成");}};player.PlayCompleted += (s, e) =>{Console.WriteLine("播放完毕");};try{player.Load(outputPath);Console.WriteLine($"音频时长: {player.Duration}");player.Play();Console.WriteLine("按 Enter 停止回放");Console.ReadLine();player.Stop();}catch (Exception ex){Console.WriteLine($"回放失败: {ex.Message}");}
}Console.WriteLine("程序结束。");录制过程中的错误处理
常见异常及处理
using SimpleAudioPlayer;using var recorder = new AudioRecorder();try
{recorder.Start(@"C:\Recordings\test.wav");// ... 录制逻辑recorder.Stop();
}
catch (InvalidOperationException ex)
{// 已在录制中 / 未初始化Console.WriteLine($"录制状态错误: {ex.Message}");
}
catch (UnauthorizedAccessException ex)
{// 没有麦克风权限Console.WriteLine($"权限不足: {ex.Message}");Console.WriteLine("请在系统设置中授予麦克风权限。");
}
catch (NotSupportedException ex)
{// 不支持当前配置(如不支持的采样率)Console.WriteLine($"不支持的配置: {ex.Message}");
}
catch (Exception ex)
{Console.WriteLine($"录制失败: {ex.Message}");
}权限检查
不同平台对麦克风权限的处理不同:
// 尝试录制一小段来检测权限
public static async Task<bool> CheckMicrophonePermissionAsync()
{try{AudioRecorder.SimulateRecording = false;using var recorder = new AudioRecorder();using var stream = new MemoryStream();recorder.OutputFormat = RecordingFileFormat.Wav;recorder.Start(stream, RecordingFileFormat.Wav);await Task.Delay(500);recorder.Stop();return stream.Length > 44; // 有效的 WAV 文件至少有 44 字节头}catch{return false;}
}丢帧处理
丢帧通常表示缓冲区太小或 CPU 负载过高:
using var recorder = new AudioRecorder();// 增大缓冲区可以降低丢帧率
// (具体 API 取决于版本实现)
recorder.Start(@"C:\Recordings\test.wav");
Thread.Sleep(5000);
var result = recorder.Stop();if (result.FramesDropped > 0)
{double dropRate = (double)result.FramesDropped / result.TotalFrames * 100;if (dropRate > 5){Console.WriteLine($"警告:丢帧率 {dropRate:F1}%,建议降低采样率或升级硬件。");}
}平台注意事项
Windows
使用 WASAPI 捕获设备
默认使用默认输入设备(可在系统设置中更改)
需要麦克风权限(Windows 10/11 隐私设置)
独占模式下可能影响其他应用的录音能力
配置默认输入设备:
// Windows 上选择特定输入设备(如果 API 支持)
// recorder.InputDeviceId = "device_id"; // 取决于具体版本实现Linux
使用 ALSA 或 PulseAudio 进行捕获
PulseAudio 默认提供混音和采样率转换
需要
pulseaudio-utils或alsa-utils可能需要将用户加入
audio组
# Linux 上可能需要的配置
sudo usermod -a -G audio $USERmacOS
使用 CoreAudio 进行音频捕获
需要在
Info.plist中声明麦克风权限macOS 10.14+ 要求麦克风权限,系统会弹出授权对话框
权限可在「系统偏好设置 → 安全性与隐私 → 麦克风」中管理
Info.plist 配置:
<key>NSMicrophoneUsageDescription</key>
<string>此应用需要访问麦克风以录制音频。</string>Android
Android 6.0+ (API 23+) 需要运行时权限
Android 10+ (API 29+) 使用 AAudio 提供低延迟录制
部分设备可能不支持某些采样率
Android 权限请求:
// Xamarin.Android / .NET MAUI 中的权限请求
var status = await Permissions.RequestAsync<Permissions.Microphone>();
if (status != PermissionStatus.Granted)
{Console.WriteLine("未获得麦克风权限");return;
}进阶用法
分段录制
using SimpleAudioPlayer;using var recorder = new AudioRecorder();
recorder.OutputFormat = RecordingFileFormat.Wav;for (int i = 1; i <= 3; i++)
{string fileName = $"C:\\Recordings\\segment_{i}.wav";Console.WriteLine($"录制第 {i} 段...");recorder.Start(fileName);Thread.Sleep(3000);recorder.Stop();Console.WriteLine($"第 {i} 段已保存: {fileName}");
}检测是否正在录制
if (recorder.IsRecording)
{Console.WriteLine("正在录制中...");var result = recorder.Stop();
}Raw PCM 后处理
录制为 Raw PCM 后可以自定义处理:
recorder.OutputFormat = RecordingFileFormat.Pcm;
recorder.Start(@"C:\Recordings\raw_output.pcm");Thread.Sleep(3000);var result = recorder.Stop();Console.WriteLine($"Raw PCM 数据: {result.TotalFrames} 帧");
Console.WriteLine($"参数: {result.SampleRate}Hz, {result.Channels}ch, {result.BitsPerSample}bit");// Raw PCM 需要知道参数才能正确播放或转换
// 可使用外部工具(如 ffmpeg)转换为 WAV
// ffmpeg -f s16le -ar 44100 -ac 1 -i raw_output.pcm output.wav通过本文的学习,你应该能够使用 AudioRecorder 完成各种录音任务。下一章将对比 SimpleAudioPlayer 与其他音频库的优劣,帮助你在项目中做出最佳选择。