i'm using a raspberry pi with Raspberry Pi OS Lite installed. I have installed the node-red environment and am using node-red-contrib-sox-utils. I tried to start streaming audio from an external USB sound card using sox-record node and at the same time play it back in the speakers. In general everything works fine, but from time to time i get the error: sox WARN alsa: under-run and i hear crackling in the speakers. Besides, there is some delay between the input (microphone) and output (speakers). When I set the sample-rate in sox-record to 16000, the delay is about 1s, but when I change it to 48000, there is practically no delay what i want. It probably has to do with some ALSA / SOX buffer. Is it possible to somehow set it up so that at the sample-rate 16000 there was not such a long delay?
If i set the number of channels to 1 in sox-record, then after starting the flow in the debug output it receives the information that the number of channels is 2
would it be possible to use node sox-convert to convert the stream from the microphone (obtained with node sox-record) to the format, for example mp3 on the fly and then play it in the speakers so that there is the shortest possible delay between input and output?
Hmmm I just tested the latest version on my Mac the other day and fed the recording right to the output and it worked fine. Give me a bit to find the version
i have Channels:2, but I chose one channel in sex-record
The flow works and i hear my voice in the speakers when i speak into the microphone, while at 16000 there is a long delay (over 1s) between what i say and what i hear in the speakers. Interestingly, when i change to 48000 then this delay is very short. I would like to achieve the shortest possible delay at 16000. This is probably related to the alsa or sox buffer but i don't know where it is configured,
but no matter if I set 16000 or 48000, from time to time the debug displays: error: sox WARN alsa: under-run which results in a short click in the speakers.
In this very special use case where I think you might be better of using an exec node to achieve this directly with Unix pipes.
This is nothing to worry about and you can safely ignore it.
Yes this has to do with the default buffer size. If you use an exec node you could try define a smaller buffer size. The reason that the delay is shorter with a higher Bitrate is that you will have much less audio length in one buffer of the same size. But this also equals to more buffers a second and a much higher load unfortunately.
The explanation above, use a custom command and try defining a smaller buffer size but you might run into limits imposed by the underlying alsa architecture.
This is the native number of channels and format of the chosen input device sox shows you, this is what gets converted to the settings in the node. So the output data will be in the format that you set.
No not possible unfortunately as sox can’t do streaming conversions and the play node can only handle pcm streams. Encoding like that would only add more latency anyways.
This happens as the node.js process will add varying latency when handling the buffers and so the timing of how they arrive at the play node can shift from how the record send them leading to a to big pause between two buffers. Again only way to solve this would be to use a all in one command with pipes in an exec node.
Thanks for the advice and answers, i also thought about using exec node when creating a command, setting buffers etc, but i don't know how to do it yet. Can you help me where to start? maybe you can provide some example for the test? I figured buffers could be set in some alsa or sox configuration file...
If i remember correctly there is a buffer argument you can add to a sox command but you would have to look it up in the documentation.
You are running into the reason why most hardware audio interfaces supply a hardware solution for listening in on yourself as the delay /latency when running through software quickly adds up.
An exec command would look something like this i think (of course you need to edit it to your input output device, here for example it plays from the default configured recording device to the built in Headphone port of the raspberry):
but now i am wondering about one more thing. I wanted to send the stream using a UDP_OUT node to another raspberry pi on the network. On the second raspberry pi i wanted to use the UDP_IN node and listen on the port. This worked fine with node-red-contrib-sox-utils nodes, but how do you do that with an exec node now?
For streaming audio over a network you should really look at solutions like snapcast or gstreamer.
Those specialized solutions will be much better for this as nodered will not be the best tool for something like low latency audio streaming.