我正在尝试接收和传输一个Twilio语音通话和一个不和谐的语音频道之间的音频。我很难找到如何将从DSharpPlus (.NET的不和谐库)接收到的音频数据转换成Twilio所要求的格式。
如果我正在阅读正确的DSharpPlus文档,来自DSharpPlus的PCM数据是以PCM S16LE格式表示的。Twilio预计数据将采用MU/8000格式(不包括标题,我相信)。
我正试图使用NAudio来转换数据,但我通过电话听到的只是尖锐的痛苦噪音。我不能使用完整的NAudio库,因为这个项目应该在上工作,而且一些NAudio API仅适用于NAudio。
下面是我目前拥有的相关代码:
private async Task VoiceReceiveHandler(VoiceNextConnection connection, VoiceReceiveEventArgs args)
{
if (twilioSocketConnectionManager.TryGetSocketById(socketId, out var twilioSocket) && twilioSocket.Socket.State == WebSocketState.Open)
{
var media = ConvertPcmToMulawBase64Encoded(args.AudioFormat, args.PcmData.ToArray());
var json = JsonSerializer.Serialize<MediaMessage>
(
new MediaMessage("media", twilioSocket.StreamSid, new MediaPayload(media)),
jsonSerializerOptions
);
logger.LogInformation(json);
var bytes = Encoding.Default.GetBytes(json);
var arraySegment = new ArraySegment<byte>(bytes, 0, bytes.Length);
await twilioSocket.Socket.SendAsync(arraySegment, WebSocketMessageType.Text, WebSocketMessageFlags.EndOfMessage, CancellationToken.None);
}
}
private static string ConvertPcmToMulawBase64Encoded(AudioFormat audioFormat, byte[] pcmData)
{
var sourceFormat = new WaveFormat(audioFormat.SampleRate, 16, audioFormat.ChannelCount);
return Convert.ToBase64String(EncodeMuLaw(pcmData, 0, pcmData.Length));
}
public static byte[] EncodeMuLaw(byte[] data, int offset, int length)
{
var encoded = new byte[length / 2];
int outIndex = 0;
for(int n = 0; n < length; n+=2)
{
encoded[outIndex++] = MuLawEncoder.LinearToMuLawSample(BitConverter.ToInt16(data, offset + n));
}
return encoded;
}我还需要从MU-LAW转换到PCM S16LE,但首先要做的是.
当涉及到音频处理的时候,我完全被遗忘了,所以请对我轻松一点。
下面是源代码的其余部分:https://github.com/Swimburger/DiscordTwilioVoiceBot
本质上,我的问题是,如何使用.NET将PCM S16LE音频转换为MU-LAW/8000,同时支持.NET/Linux/Mac?
更新1:
人们建议使用ffmpeg代替NAudio,我认为这是正确的,但我仍然听到尖锐的噪音,而不是实际的音频。
private async Task VoiceReceiveHandler(VoiceNextConnection connection, VoiceReceiveEventArgs args)
{
var ffmpeg = Process.Start(new ProcessStartInfo
{
FileName = "ffmpeg",
Arguments = $@"-hide_banner -ac 2 -f s16le -ar 48000 -i pipe:0 -c:a pcm_mulaw -f mulaw -ar 8000 -ac 1 pipe:1",
RedirectStandardInput = true,
RedirectStandardOutput = true
});
//byte[] trimmedData = new byte[args.PcmData.Length - 44];
//Buffer.BlockCopy(args.PcmData.ToArray(), 44, trimmedData, 0, trimmedData.Length);
await ffmpeg.StandardInput.BaseStream.WriteAsync(args.PcmData);
ffmpeg.StandardInput.Close();
byte[] data;
using(var memoryStream = new MemoryStream())
{
ffmpeg.StandardOutput.BaseStream.CopyTo(memoryStream);
data = memoryStream.ToArray();
}
ffmpeg.Dispose();
//byte[] trimmedData = new byte[data.Length - 44];
//Buffer.BlockCopy(data, 44, trimmedData, 0, trimmedData.Length);
//return;
if (twilioSocketConnectionManager.TryGetSocketById(socketId, out var twilioSocket) && twilioSocket.Socket.State == WebSocketState.Open)
{
var json = JsonSerializer.Serialize<MediaMessage>
(
new MediaMessage("media", twilioSocket.StreamSid, new MediaPayload(Convert.ToBase64String(data))),
jsonSerializerOptions
);
logger.LogInformation(json);
var bytes = Encoding.Default.GetBytes(json);
var arraySegment = new ArraySegment<byte>(bytes, 0, bytes.Length);
await twilioSocket.Socket.SendAsync(arraySegment, WebSocketMessageType.Text, WebSocketMessageFlags.EndOfMessage, CancellationToken.None);
}
}这是在一个分叉上。
发布于 2022-01-13 12:20:13
我有一个类似的问题,将Twilio的MU-LAW转换为PCM 16 to,然后流到Azure认知服务转录服务。我是用Java而不是dotnet编写的,我没有找到一个好的库解决方案。
然而,转换可以通过一个查找表(注意,一个字节的mulaw由2个字节的pcm表示)进行逐时字节转换。这里有一个维基百科对算法的抽象描述,我发现这个dotnet回购的代码很容易被翻译成Java,并且运行良好。对于您的情况,您需要查看MulawDecoder.cs。
我为mulaw->pcm生成的Java代码是这里。
https://stackoverflow.com/questions/70599169
复制相似问题