summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxegineering <me@xegineering.eu>2024-12-08 17:36:28 +0100
committerxegineering <me@xegineering.eu>2024-12-08 18:22:14 +0100
commit49f47e76a85b3477835a0adec05649507d94b2e8 (patch)
tree8a1306820743aea32e706b9d106ead958f6e755e
parent06c4f8b0120f5598f9d179b8c0fea33df35659a8 (diff)
downloadsoundbox-go-49f47e76a85b3477835a0adec05649507d94b2e8.tar
soundbox-go-49f47e76a85b3477835a0adec05649507d94b2e8.tar.zst
soundbox-go-49f47e76a85b3477835a0adec05649507d94b2e8.zip
pipewire: Fix huge latency by dropping silence
The current architecture uses the following processing: - capture raw audio from PipeWire as unsigned 16 bit integers - convert with a `ffmpeg` process to OGG / FLAC - stream the `ffmpeg` output to multiple soundboxes via TCP Only the first part is different for URL sources. Since using PipeWire significant latency (up to 15 seconds) were measured. It turned out that this happens exactly when zero bytes (silence) are fed into the `ffmpeg` process. This commit avoids this by dropping those empty samples. It has to be made sure that only samples are dropped where both channels are zero. Otherwise audible noise is the result.
-rw-r--r--soundbox/pipewire.go16
1 files changed, 15 insertions, 1 deletions
diff --git a/soundbox/pipewire.go b/soundbox/pipewire.go
index fbae73b..fcb5968 100644
--- a/soundbox/pipewire.go
+++ b/soundbox/pipewire.go
@@ -18,6 +18,20 @@ import (
var pipewireAudio = make(chan []byte, 5)
+func s16leDropSilence(input []byte) []byte {
+ output := make([]byte, 0)
+
+ for i := 0; i < (len(input)-1); i+=2 {
+ if input[i] == byte(0) && input[i+1] == byte(0) {
+ continue
+ }
+ output = append(output, input[i])
+ output = append(output, input[i+1])
+ }
+
+ return output
+}
+
func StreamPipewireContext(ctx context.Context, targets []net.HardwareAddr) error {
cmd := exec.CommandContext(
ctx,
@@ -51,7 +65,7 @@ func StreamPipewireContext(ctx context.Context, targets []net.HardwareAddr) erro
go func() {
for buffer := range pipewireAudio {
- tempReader := bytes.NewReader(buffer)
+ tempReader := bytes.NewReader(s16leDropSilence(buffer))
_, err := io.Copy(stdin, tempReader)
if err != nil {
log.Println("Failed to copy from PipeWire to ffmpeg.")