【问题标题】:Liquidsoap with live ALSA audio in Docker not working (Stuttering and buffer underruns)Docker 中带有实时 ALSA 音频的 Liquidsoap 无法正常工作(口吃和缓冲区欠载)
【发布时间】:2021-09-02 04:00:49
【问题描述】:

虽然使用 Liquidsoap 的 output.alsa(..) 在 Docker 中进行简单的音频播放工作正常,但我无法让实时音频正常工作。基本上我想将模拟音频输入路由到模拟音频输出,例如output.alsa(input.alsa())。以下三个示例可以正常工作:

示例 1:缓冲 I/O

# Successfully tested with Liquidsoap 1.4.4 & ALSA 1.1.3 (native)
# Low latency, no buffer underruns

set("frame.audio.size", 2048)
set("alsa.alsa_buffer", 8192)
set("alsa.buffer_length", 10)

input_analog = input.alsa(device="default", bufferize=true)
output.alsa(device="default", input_analog, bufferize=true)

示例 2:额外缓冲 I/O

# Successfully tested with Liquidsoap 1.4.4 + 1.1.3 (native)
# High latency, no buffer underruns

set("frame.audio.size", 2048)
set("alsa.alsa_buffer", 8192)
set("alsa.buffer_length", 10)

input_analog = input.alsa(device="default", bufferize=true)
input_analog = mksafe(buffer(input_analog))
output.alsa(device="default", input_analog, bufferize=true)

示例 3:无缓冲 I/O

# Successfully tested with Liquidsoap 2 & ALSA 1.2.4 (native)
# Almost no latency, no buffer underruns
# Doesn't work in Liquidsoap 1.4 because of some calculation bug

set("frame.audio.size", 7526)
set("frame.video.framerate", 0)

input_analog = input.alsa(device="default", bufferize=false)
output.alsa(device="default", input_analog, bufferize=false)

通过这些示例在 Docker 中,我得到了大量的音频中断和缓冲区欠载,无论我尝试哪种缓冲区或帧设置。 Docker Container 的 CPU 使用率通常

我正在像这样启动容器(之前也尝试过为容器提供额外 CPU 和内存的特定设置):

docker run -it \
    --network="host" \
    --mount type=tmpfs,destination=/tmp \
    -v /dev/snd:/dev/snd \
    -v "/etc/asound.conf":"/etc/asound.conf" \
    --group-add audio \
    --privileged \
    savonet/liquidsoap:main \
    ...

default ALSA 设备的定义很简单:

#/etc/asound.conf
defaults.pcm.card 2
defaults.ctl.card 2

需要什么秘方吗?你有一个例子吗?

也许这根本不是 Liquidsoap 的问题。希望结合一些隐藏的 Docker 标志来做一些特殊的 ALSA 设备配置就足够了。

【问题讨论】:

    标签: docker alsa liquidsoap


    【解决方案1】:

    如果我首先在主机系统上播放音频,然后在启动 docker 之前停止播放,我发现所有示例都可以正常工作。

    重新启动 docker 而不先在主机上播放音频,会导致所描述的缓冲区欠载。

    --编辑

    另一个观察结果:在启动 liquidsoap 之前在 docker-container(播放文件)中播放声音文件总是会导致缓冲区欠载。

    【讨论】:

    • 非常感谢您的回复,英戈!我不确定我是否正确理解了您的答案:您正在主机系统上播放音频,然后停止 playplack,然后才在播放音频时启动 Docker?你测试了多长时间从模拟输入播放音频?对我来说,有一个设置让我让它工作了大约 20 分钟,但随后又以大量缓冲区不足告终。虽然 Docker 中的简单音频播放工作正常。
    • 在阅读了您对aplay file 的观察后,我假设您可能还有另一个先决条件(例如,您能否确保您的机器上没有运行 PulseAudio?),因为对我来说,从 Docker 内部进行的简单回放与某些设置。 aplay 也没有问题。我的问题实际上不是关于从 Docker 内部播放,而是更多关于从 Docker 内部的模拟输入播放实时音频。如果您能提供更多说明和可能的想法,我们会很高兴。谢谢:)
    • 嗨,大卫。 1)确切地说。我在主机系统上播放音频(aplay 或其他),然后停止播放,然后启动 docker。 docker 运行时主机系统上没有播放。很确定我让它运行了 20 多分钟,但会再次测试。 2)抱歉,我的编辑有点误导:从 docker 中播放文件工作正常(没有缓冲区欠载),只有在 aplay 完成后运行liquidsoap 会导致缓冲区欠载,即使我在启动 docker 之前在主机上播放了音频。所以我希望它能够工作,但不知何故,在 docker 中的 aplay 使liquidsoap 导致欠载。
    • 你是对的,一段时间后缓冲区不足开始发生。就我而言,是在 1.5 小时后。
    • 感谢英戈的澄清。您也可以尝试自定义 frame.audio.size 的值。此值特定于每个音频接口。所以你的可能实际上是不同的。在这里,我在“检测正确的帧大小”部分详细介绍了如何获得正确的帧大小:gitlab.servus.at/aura/engine-core/-/blob/master/docs/…