如何使用 Uno Platform 在多个平台上录制音频
How do I record audio on multiple platforms with Uno Platform
我正在尝试录制音频并在之后进行处理。据我所知,没有统一的 API 我可以用来跨不同平台访问麦克风。我的目标是 WASM、UWP 和 Android.
我的方法是使用特定于平台的代码来录制音频。
对于 UWP,我可以使用 MediaCapture class,如下所述:link。
我已经实现了这部分并且它工作得很好。
对于Android,它也应该是直截了当的。我可以使用 Android.Media.MediaRecorder,如下所示:link。之后不知道怎么获取录制的音频文件
至于 WASM 我完全迷失在这里。我想我可以使用一些 javascript 库来录制声音或 vmsg 库,如此处 link 所述。但是我不知道如何将记录的数据放入C#代码中进行进一步处理。
是否有一些 material 我应该阅读以更好地理解主题。我是否忽略了一些重要的细节?或者有没有一种简单的方法可以在 xamarin.android 和 wasm 中录制音频?
更新:
我已经使用 Android.Media.MediaRecorder 在 Android 上成功实现了音频捕获,我可以在完成录制后轻松访问该文件。
我终于可以在所有三个平台(UWP、Android、WASM)上进行录制了。
这里的目标是获取具有 48 kHz 采样率、1 个通道和每个样本 16 位的原始 PCM 音频数据。
UWP:
全局变量:
MediaCapture audioCapture = new MediaCapture();
IRandomAccessStream buffer = new InMemoryRandomAccessStream();
正在录制音频:
public async Task RecordAudio(int recordingLength, uint sampleRate, uint channels, uint bitsPerSample)
{
//initialization
await audioCapture.InitializeAsync(new MediaCaptureInitializationSettings { StreamingCaptureMode = StreamingCaptureMode.Audio });
//encoding setup
MediaEncodingProfile profile = MediaEncodingProfile.CreateWav(AudioEncodingQuality.Auto);
profile.Audio = AudioEncodingProperties.CreatePcm(sampleRate, channels, bitsPerSample);
//start recording
await audioCapture.StartRecordToStreamAsync(profile, buffer);
await Task.Delay(recordingLength * 1000);
//stop recording
await audioCapture.StopRecordAsync();
}
获取字节数组形式的 PCM 数据:
public async Task<byte[]> GetPCMData()
{
byte[] data = new byte[buffer.Size];
DataReader dataReader = new DataReader(buffer.GetInputStreamAt(0));
await dataReader.LoadAsync((uint)buffer.Size);
dataReader.ReadBytes(data);
return data;
}
ANDROID:
请记住先检查麦克风权限。
全局变量:
byte[] buffer;
AudioRecord recorder;
int bufferLimit;
正在录制音频:
public async Task RecordAudio(int recordingLength, uint sampleRate, uint channels, uint bitsPerSample)
{
//initialization
// seconds * (number of bytes bytes per 1 sample) * sampleRate
bufferLimit = recordingLength * bitsPerSample/8 * sampleRate;
//encoding setup
ChannelIn channels = Parameters.Channels == 1 ? ChannelIn.Mono : ChannelIn.Stereo;
if (bitsPerSample != 16)
throw new Exception("Unsupported bits per sample value");
recorder = new AudioRecord(
AudioSource.Mic,
(int)sampleRate,
channels,
Android.Media.Encoding.Pcm16bit,
bufferLimit
);
//start recording
buffer = new byte[bufferLimit];
int totalBytesRead = 0;
recorder.StartRecording();
//record until specified amount of bytes was read
while(totalBytesRead < bufferLimit)
{
int bytesRead = recorder.Read(buffer, 0, bufferLimit);
if (bytesRead < 0)
{
throw new Exception(String.Format("Exception code: {0}", bytesRead));
}
else
{
totalBytesRead += bytesRead;
}
}
//stop recording
recorder.Stop();
recorder.Dispose();
}
获取字节数组形式的 PCM 数据:
public async Task<byte[]> GetPCMData()
{
return buffer;
}
WASM:
我使用RecordRTCjavascript库获取音频数据:
function record(recordingLength, sampleRate, channels) {
navigator.mediaDevices.getUserMedia({
audio: true
}).then(async function (stream) {
//initialization
let recorder = RecordRTC(stream, {
type: 'audio',
mimeType: 'audio/wav',
recorderType: StereoAudioRecorder,
sampleRate: sampleRate,
desiredSampRate: sampleRate,
numberOfAudioChannels: channels
});
//start recording
recorder.startRecording();
const sleep = m => new Promise(r => setTimeout(r, m));
await sleep(recordingLength * 1000);
recorder.stopRecording(function () {
//blob of PCM audio data that can be further processed
let blob = recorder.getBlob();
}
});
});
}
在 WASM 中,我使用 blob 作为 base64 字符串从 javascript 调用 C# 代码,以在 C# 中进一步处理 PCM 音频数据的 blob(如何从 javascript 可以在 Uno 平台找到 docs).
我知道,这不是最干净的解决方案,但它是一个有效的解决方案。
我正在尝试录制音频并在之后进行处理。据我所知,没有统一的 API 我可以用来跨不同平台访问麦克风。我的目标是 WASM、UWP 和 Android.
我的方法是使用特定于平台的代码来录制音频。
对于 UWP,我可以使用 MediaCapture class,如下所述:link。 我已经实现了这部分并且它工作得很好。
对于Android,它也应该是直截了当的。我可以使用 Android.Media.MediaRecorder,如下所示:link。之后不知道怎么获取录制的音频文件
至于 WASM 我完全迷失在这里。我想我可以使用一些 javascript 库来录制声音或 vmsg 库,如此处 link 所述。但是我不知道如何将记录的数据放入C#代码中进行进一步处理。
是否有一些 material 我应该阅读以更好地理解主题。我是否忽略了一些重要的细节?或者有没有一种简单的方法可以在 xamarin.android 和 wasm 中录制音频?
更新: 我已经使用 Android.Media.MediaRecorder 在 Android 上成功实现了音频捕获,我可以在完成录制后轻松访问该文件。
我终于可以在所有三个平台(UWP、Android、WASM)上进行录制了。 这里的目标是获取具有 48 kHz 采样率、1 个通道和每个样本 16 位的原始 PCM 音频数据。
UWP:
全局变量:
MediaCapture audioCapture = new MediaCapture();
IRandomAccessStream buffer = new InMemoryRandomAccessStream();
正在录制音频:
public async Task RecordAudio(int recordingLength, uint sampleRate, uint channels, uint bitsPerSample)
{
//initialization
await audioCapture.InitializeAsync(new MediaCaptureInitializationSettings { StreamingCaptureMode = StreamingCaptureMode.Audio });
//encoding setup
MediaEncodingProfile profile = MediaEncodingProfile.CreateWav(AudioEncodingQuality.Auto);
profile.Audio = AudioEncodingProperties.CreatePcm(sampleRate, channels, bitsPerSample);
//start recording
await audioCapture.StartRecordToStreamAsync(profile, buffer);
await Task.Delay(recordingLength * 1000);
//stop recording
await audioCapture.StopRecordAsync();
}
获取字节数组形式的 PCM 数据:
public async Task<byte[]> GetPCMData()
{
byte[] data = new byte[buffer.Size];
DataReader dataReader = new DataReader(buffer.GetInputStreamAt(0));
await dataReader.LoadAsync((uint)buffer.Size);
dataReader.ReadBytes(data);
return data;
}
ANDROID: 请记住先检查麦克风权限。 全局变量:
byte[] buffer;
AudioRecord recorder;
int bufferLimit;
正在录制音频:
public async Task RecordAudio(int recordingLength, uint sampleRate, uint channels, uint bitsPerSample)
{
//initialization
// seconds * (number of bytes bytes per 1 sample) * sampleRate
bufferLimit = recordingLength * bitsPerSample/8 * sampleRate;
//encoding setup
ChannelIn channels = Parameters.Channels == 1 ? ChannelIn.Mono : ChannelIn.Stereo;
if (bitsPerSample != 16)
throw new Exception("Unsupported bits per sample value");
recorder = new AudioRecord(
AudioSource.Mic,
(int)sampleRate,
channels,
Android.Media.Encoding.Pcm16bit,
bufferLimit
);
//start recording
buffer = new byte[bufferLimit];
int totalBytesRead = 0;
recorder.StartRecording();
//record until specified amount of bytes was read
while(totalBytesRead < bufferLimit)
{
int bytesRead = recorder.Read(buffer, 0, bufferLimit);
if (bytesRead < 0)
{
throw new Exception(String.Format("Exception code: {0}", bytesRead));
}
else
{
totalBytesRead += bytesRead;
}
}
//stop recording
recorder.Stop();
recorder.Dispose();
}
获取字节数组形式的 PCM 数据:
public async Task<byte[]> GetPCMData()
{
return buffer;
}
WASM:
我使用RecordRTCjavascript库获取音频数据:
function record(recordingLength, sampleRate, channels) {
navigator.mediaDevices.getUserMedia({
audio: true
}).then(async function (stream) {
//initialization
let recorder = RecordRTC(stream, {
type: 'audio',
mimeType: 'audio/wav',
recorderType: StereoAudioRecorder,
sampleRate: sampleRate,
desiredSampRate: sampleRate,
numberOfAudioChannels: channels
});
//start recording
recorder.startRecording();
const sleep = m => new Promise(r => setTimeout(r, m));
await sleep(recordingLength * 1000);
recorder.stopRecording(function () {
//blob of PCM audio data that can be further processed
let blob = recorder.getBlob();
}
});
});
}
在 WASM 中,我使用 blob 作为 base64 字符串从 javascript 调用 C# 代码,以在 C# 中进一步处理 PCM 音频数据的 blob(如何从 javascript 可以在 Uno 平台找到 docs).
我知道,这不是最干净的解决方案,但它是一个有效的解决方案。