Eti*_*oux 6 c# audio audio-streaming naudio wasapi
我遇到了来自 NAudio 库的 BufferedWaveProvider 的问题。我正在录制 2 个音频设备(一个麦克风和一个扬声器),将它们合并为 1 个流并将其发送到编码器(用于视频)。
为此,我执行以下操作:
WasapiCapture
.WasapiLookbackCapture
. (我也使用 aSilenceProvider
所以我记录的内容没有空白)。MediaFoundationResampler
来调整其格式,使其与扬声器中的音频相同。BufferedWaveProvider
.MixingSampleProvider
我ISampleProvider
从每个录制线程传递的地方。所以我通过MediaFoundationResampler
麦克风和BufferedWaveProvider
扬声器。MixingSampleProvider
,它应该BufferedWaveProvider
在填充时异步清空(s)。请参阅下面的流程图,它说明了我上面的描述。
during
进行 Discord、Skype 或 Teams 音频对话时,我都会立即(在 5 秒内)崩溃,BufferedWaveProvider.AppSamples
因为缓冲区已满。在调试模式下查看它,我可以看到:
从我在 NAudio 的作者博客、文档和 StackOverflow 上阅读的内容来看,我认为我正在做最佳实践(但我可能是错的),即从一个线程写入缓冲区,并从另一个线程并行读取它. 当然有一种风险,它比我阅读它的速度更快,这基本上就是现在正在发生的事情。但我不明白为什么。
我需要一些帮助来理解我在这里遗漏了什么,请。以下几点让我感到困惑:
为什么这个问题只发生在 Discord/Skype/Teams 会议上?我正在使用的视频游戏也在使用麦克风,所以我无法想象它像another app is preventing the microphone/speakers to works correctly
.
我同步两个录音机的启动。这样做,我使用一个信号来要求记录器启动,当它们都开始生成数据(通过DataAvailable
事件)时,我发送一个信号告诉他们用他们将在下一个接收到的内容填充缓冲区事件。这可能并不完美,因为两个音频设备DataAvailable
在不同的时间发送它们,但我们谈论的最大差异为 60 毫秒(在我的机器上),而不是 5 秒。所以我不明白为什么它会被填满。
为了回顾我在 #2 中所说的内容,我的遥测显示缓冲区正在以这种方式填充(值是虚拟的):
Microphone buffered duration: 0ms | Speakers: 0ms
Microphone buffered duration: 60ms | Speakers: 60ms
Microphone buffered duration: 0ms | Speakers: 0ms <= That's because I read the data from the mixing sample provider
Microphone buffered duration: 60ms | Speakers: 0ms <= Events may not be in sync, that's ok.
Microphone buffered duration: 120ms | Speakers: 60ms <= Alright, next loop, I'll extract 60ms on each buffer.
Microphone buffered duration: 390ms | Speakers: 0ms <= Wait, how?
Microphone buffered duration: 390ms | Speakers: 60ms
[...]
Microphone buffered duration: 5000ms | Speakers: 0ms <= Oh no :(
Run Code Online (Sandbox Code Playgroud)
所以看起来麦克风的缓冲区越来越快......但为什么呢?可能是因为重采样器减慢了麦克风缓冲区的读取速度?如果是这样,它也应该减慢扬声器缓冲区的读取速度,因为我正在通过 a 读取它MixingSampleProvider
,不是吗?
如果可以的话,这是我的代码的简化摘录:
Microphone buffered duration: 0ms | Speakers: 0ms
Microphone buffered duration: 60ms | Speakers: 60ms
Microphone buffered duration: 0ms | Speakers: 0ms <= That's because I read the data from the mixing sample provider
Microphone buffered duration: 60ms | Speakers: 0ms <= Events may not be in sync, that's ok.
Microphone buffered duration: 120ms | Speakers: 60ms <= Alright, next loop, I'll extract 60ms on each buffer.
Microphone buffered duration: 390ms | Speakers: 0ms <= Wait, how?
Microphone buffered duration: 390ms | Speakers: 60ms
[...]
Microphone buffered duration: 5000ms | Speakers: 0ms <= Oh no :(
Run Code Online (Sandbox Code Playgroud)
有没有人知道我做错了什么和/或为什么只有在 Discord/Skype/Teams 上通过语音聊天而不是通过在线多人游戏时才会出现这种情况?
提前致谢!
我可能已经发现了这个问题,但我不是 100% 确定如何处理它。似乎我停止从麦克风接收数据,因此扬声器缓冲区已满。(好像昨天,正好相反)。
这听起来出于某种原因,也许(我说也许是因为问题可能是其他问题)BufferedWaveProvider
在某些情况下阅读后并没有清除。
让我想到的是以下几点:
MixingSampleProvider
我记录了我们在每个缓冲区中的缓冲持续时间。BEFORE READING MICROPHONE: 20ms
BEFORE READING SPEAKER: 10ms
AFTER READING MICROPHONE: 0ms
AFTER READING SPEAKER: 0ms
// I don't explain why both buffer are empty considering my algorithm was supposed to read only 10ms, but the output MP4 seems fine and in sync, so it's fine? ...
Run Code Online (Sandbox Code Playgroud)
BEFORE READING MICROPHONE: 20ms
BEFORE READING SPEAKER: 10ms
AFTER READING MICROPHONE: 0ms
AFTER READING SPEAKER: 0ms
BEFORE READING MICROPHONE: 10ms
BEFORE READING SPEAKER: 20ms
AFTER READING MICROPHONE: 0ms
AFTER READING SPEAKER: 20ms
BEFORE READING MICROPHONE: 20ms
BEFORE READING SPEAKER: 30ms
AFTER READING MICROPHONE: 0ms
AFTER READING SPEAKER: 30ms
BEFORE READING MICROPHONE: 10ms
BEFORE READING SPEAKER: 50ms
AFTER READING MICROPHONE: 0ms
AFTER READING SPEAKER: 50ms
BEFORE READING MICROPHONE: 20ms
BEFORE READING SPEAKER: 70ms
AFTER READING MICROPHONE: 0ms
AFTER READING SPEAKER: 70ms
BEFORE READING MICROPHONE: 20ms
BEFORE READING SPEAKER: 80ms
AFTER READING MICROPHONE: 0ms
AFTER READING SPEAKER: 80ms
BEFORE READING MICROPHONE: 10ms
BEFORE READING SPEAKER: 100ms
AFTER READING MICROPHONE: 0ms
AFTER READING SPEAKER: 100ms
BEFORE READING MICROPHONE: 20ms
BEFORE READING SPEAKER: 110ms
AFTER READING MICROPHONE: 0ms
AFTER READING SPEAKER: 110ms
BEFORE READING MICROPHONE: 10ms
BEFORE READING SPEAKER: 130ms
AFTER READING MICROPHONE: 0ms
AFTER READING SPEAKER: 130ms
[...]
BEFORE READING MICROPHONE: 20ms
BEFORE READING SPEAKER: 4970ms
AFTER READING MICROPHONE: 0ms
AFTER READING SPEAKER: 4970ms
BEFORE READING MICROPHONE: 10ms
BEFORE READING SPEAKER: 4980ms
AFTER READING MICROPHONE: 0ms
AFTER READING SPEAKER: 4980ms
BEFORE READING MICROPHONE: 20ms
BEFORE READING SPEAKER: 5000ms
AFTER READING MICROPHONE: 0ms
AFTER READING SPEAKER: 5000ms
<!-- Crash -->
Run Code Online (Sandbox Code Playgroud)
当缓冲区开始不再同步时,我可以通过清除缓冲区来做一个肮脏的修复,但我真的很想了解为什么会发生这种情况,以及是否有更好的方法来解决它。
谢谢
好的,我想我把问题隔离了。这可能是 NAudio 库中的一个错误。这是我所做的:
经过更多调查和 GitHub 上的帖子:https ://github.com/naudio/NAudio/issues/742
我发现我应该监听该MixingSampleProvider.MixerInputEnded
事件,并在事件发生时将 SampleProvider 重新添加到 MixingSampleProvider 中。
发生这种情况的原因是我在捕获音频时处理音频,并且有时我处理它的速度可能比录制它的速度快,因此 MixingSampleProvider 认为它没有更多内容可读取并停止。所以我应该告诉它,不,一切还没有结束,它应该期待更多。
归档时间: |
|
查看次数: |
240 次 |
最近记录: |