audify
audify copied to clipboard
RtAudio input stops after ~7 seconds, when output is not opened
I'm having trouble with the basic audio input example. The audio input callback stops being called after about 7 seconds. Some notes:
- This occurs with both WASAPI and DirectShow audio APIs.
- It doesn't matter which audio device I use.
- The exact time duration before failure varies from run to run, slightly, as does the number of times the input callback is called.
- DirectShow devices fail 1-2 seconds sooner than WASAPI devices, even if the same physical device is used.
- Changing the frame size option will change the number of times the callback is called, but will not change the time duration or number of bytes received. That is, if I double the frame size, the callback is called about half the number of times, but the total time duration and byte count is about the same.
- Changing the sample format option of course changes the number of bytes I receive, but the number of times the callback is called is not changed, and neither is the total time duration.
- I'm not using an audio output. Input only.
- The error callback is never called.
- None of the RtAudioStreamFlags have any impact on this problem.
- Windows 10 x64. Node.js 18.3.0. Audify 1.7.1.
Any thoughts as to the cause of this and how it can be solved?
The problem also occurs on Node.js v16.15.1.
I've found that this problem doesn't occur as long as I have an output running too. It seems rtAudio.write() must be called regularly for the input to work.
Using null for the output options doesn't work, because calls to .write() cause a crash.
I have almost the same exact same issue on Linux with PulseAudio. Based on your workaround I implemented a very dumb way of dealing with it after some experimentation.
// Start the stream
rtAudio.start();
setTimeout(() => {
try {
rtAudio.write(null);
} catch {
console.log("RTAudio fixed, enjoy your stream.");
}
})
Calling it once without setTimeout does not work. Putting it in setTimeout and the default 0ms timeout will make it work. I did not have to call it anymore after this.
I found out that it's not really related with the write method, you can actually call isStreamOpen or isStreamRunning methods to keep it running. It almost feels like a reference counter or something that goes to zero if you don't reference it. I'm pretty sure it's about the C++ implementation of the binding.
Actually, even this worked for me:
// Not even calling the foo function, just declaring it.
const foo = () => {
recorder.isStreamOpen() // keeps the recorder stream running.
}
It's a Schrödinger's stream: if nobody is measuring if it's open or not, it declines to collapse its superposition into a concrete state of existence 🤣