在纯 ALSA 中复制音频,以便在本地设备上播放并通过 trx 进行流式传输

在纯 ALSA 中复制音频,以便在本地设备上播放并通过 trx 进行流式传输

我正在尝试使用 Raspberry Pi 在我的房子里实现多房间音频设置。如何让 VLC 在本地耳机端口上同时播放,同时通过 trx 将其流式传输到其他设备?

背景:

我发现了一个名为 trx 的奇妙软件包,它允许在 LAN 上使用 Opus 编解码器进行低延迟流传输:http://www.pogo.org.uk/~mark/trx/streaming-desktop-audio.html

我已成功安装 trx 并使用以下内容:

sudo modprobe snd-aloop

传输端~/.asoundrc

# TX device catches played audio from a player (e.g. VLC)
# point vlc to this device:
#    cvlc --alsa-audio-device="tx" <file_or_stream>
pcm.tx {
    type plug
    slave.pcm {
        type dmix
        ipc_key 2867
        slave {
            pcm "hw:Loopback,0,0"
            rate 48000
            format S16_LE
            channels 2
            period_size 256
            buffer_size 8192
        }
    }
}

# Hubcap ensures 48000Hz sample rate (Opus compatible)
pcm.hubcap {
    type plug
    slave {
        pcm "hw:Loopback,1,0"
        rate 48000
        format S16_LE
    }
}

传输侧:

tx -d hubcap -m 64 -h 239.0.0.99 &

cvlc --alsa-audio-device="tx" {source_file_path_or_url}

接收方:

rx -m 64 -h 239.0.0.99

偶尔会出现缓冲区不足的情况,通过将 tx 进程的良好度更改为 -10 可以轻松修复。

renice -n -10 {process_id}

问题:

我希望能够将音频从 VLC 播放到网络上侦听多播 239.0.0.99 的设备,以及从传输设备的耳机/线路输出插座播放音频。

我不知道如何在 ~/.asoundrc 中设置插头、路由和多重,以便有一个 ALSA 设备 cvlc 可以播放,其中音频被馈送到本地 hw:1 (耳机插座)和plug:tx (通过 tx 传输音频的输入)。

ALSA asound 配置文档非常糟糕。我尝试向 .asoundrc 添加以下内容,但没有成功:

pcm.headphones_dmix {
        type dmix
        slave {
                pcm "hw:Headphones"
        }
}

pcm.localandtx {
    type plug
    slave {
        format S16_LE
        pcm {
            type multi
            slaves.tx.pcm "tx"
            slaves.tx.channels 2
            slaves.local.pcm "headphones_dmix"
            slaves.local.channels 2
            bindings.0.slave tx
            bindings.0.channel 0
            bindings.1.slave tx
            bindings.1.channel 1
            bindings.2.slave local
            bindings.2.channel 0
            bindings.3.slave local
            bindings.3.channel 1
        }
    }
    route_policy duplicate
    ttable {
        0.0 1
        1.1 1
        0.2 1
        1.3 1
    }
    hint {
        show on
        description "Play both locally and via TX."
    }
}

与上述:

vlc 会很高兴地用本地耳机播放 --alsa-audio-device="hw:Headphones"

vlc 将很乐意在运行 rx 的设备上播放--alsa-audio-device="tx"

但是,vlc 无法与--alsa-audio-device="localandtx".我想让两者都玩。 (我知道通过 trx 发送音频时会产生额外的延迟)。

vlc 错误是:

ALSA lib pcm_direct.c:2031:(snd1_pcm_direct_parse_open_conf) Unique IPC key is not defined
[015a4ac8] alsa audio output error: cannot open ALSA device "localandtx": Invalid argument
[015a4ac8] main audio output error: Audio output failed
[015a4ac8] main audio output error: The audio device "localandtx" could not be used: Invalid argument.
[015a4ac8] main audio output error: module not functional
[71b7a980] main decoder error: failed to create audio output

是否有任何有用的(健全的)工具来调试 ALSA asound 配置文件?

我如何确定 localandtx 中的哪个 .asoundrc 参数是“无效的”?

如何在不使用 PulseAudio 的情况下在 ALSA 中实现到 hw:Headphones 和 tx 的音频路由?

答案1

我终于解决了 Raspberry Pi 多房间音频难题!

解决方案是引入 PulseAudio。由于 Raspberry Pi 的 ALSA bcm2835 驱动程序限制,ALSA 无法单独完成此操作。由于我不太明白的原因,驱动程序无法使用 mmap 将数据从一个流复制到另一个流。即使专门启用 mmap 并使用 mmap 模拟 (mmap_emul),情况也是如此 - 请参阅:https://blog.dowhile0.org/2013/04/27/mmap-support-for-raspberry-pi-bcm2835-alsa-driver/

Raspberry Pi 音频流本地复制和通过 trx 复制的完整解决方案:

  1. 传输端-安装包:

     sudo su
     sudo apt install alsa-utils opus-tools lame vlc cmake libasound2-dev libortp-dev libopus-dev pulseaudio
     mkdir ~/Installers
     cd ~/Installers
     git clone http://www.pogo.org.uk/~mark/trx.git
     make
     sudo make install
    
  2. 传输端 - 将用户添加到音频组:

     sudo usermod -a -G audio your_username
    
  3. 传输端-激活alsa环回模块:

     modprobe snd-aloop
     echo "snd-aloop" | sudo tee -a /etc/modules
    
  4. 传输端 - 设置 ALSA 设备以支持 trx:

    如果您只想为一个用户执行此操作,您应该编辑 ~/.asoundrc,或者编辑 /etc/asound.conf 为所有用户执行此操作。

     # nano /etc/asound.conf 
    

    或者

     # nano ~/asoundrc:
    

    文件内容:

     # /etc/asound.conf OR ~/asoundrc:
    
     # tx_dmix ensures audio sent to tx gets resampled properly
     pcm.tx_dmix {
             type dmix
             ipc_key 2867
             ipc_perm 0666 # allow other users
             slave {
                 pcm "hw:Loopback,0,0"
                 rate 48000
                 format S16_LE
                 channels 2
                 period_size 256
                 buffer_size 8192
             }
     }
    
     # tx is the entry point for anything that wants to play down the TX link
     pcm.tx {
             type plug
             slave.pcm "tx_dmix"
             hint.description "Audio input for TX transmission."
     }
    
     # Hubcap is used by TX to resample audio into Opus-friendly sample rate
     pcm.hubcap {
             type plug
             slave {
                     pcm "hw:Loopback,1,0"
                     rate 48000
                     format S16_LE
             }
             hint.description "Internal loopback capture and resampler for TX. Only TX should use."
     }
    
     # Headphones (3.5mm jack) playback
     pcm.headphones_hw {
         type hw
         card Headphones
         sync_ptr_ioctl 1
     }
    
     pcm.headphones {
         type plug
         slave.pcm "headphones_hw"
     }
    
     pcm.!default {
         type plug
         slave.pcm "headphones"
     }
    
  5. 传输端 - 设置 PulseAudio 连接

     # nano /etc/pulse/default.pa
    

    或者

     # nano ~/.pulse/default.pa:
    

    文件内容:

     # PulseAudio config - duplicates audio for local playback and network playback
    
     .include /etc/pulse/default.pa
    
     # Set up Pulse sinks to connect to our ALSA devices we configured in .asoundrc
     load-module module-alsa-sink device="tx" sink_name=tx
     load-module module-alsa-sink device="headphones" sink_name=headphones
    
     # Create stream duplicator
     load-module module-null-sink sink_name=localandtx
     load-module module-loopback source=localandtx.monitor sink=tx
     load-module module-loopback source=localandtx.monitor sink=headphones
     set-default-sink localandtx
    

    创建此文件后重新启动脉冲

     pulseaudio -k
    
  6. 传输端 - 创建 tx 初始化脚本:

     nano ~/run_tx.sh
    

    文件内容

     #!/bin/bash
     # Fires up the TX transmission 
     # Usage:
     #     sudo run_tx.sh [ip] [latency in ms]
     #     sudo run_tx.sh 239.0.0.99 64
    
     # Defaults
     DEFAULT_TX_IP="239.0.0.99"
     DEFAULT_LATENCY_BUFFER_MS="64"
    
     # Resolve from args
     CHOSEN_TX_IP=${$1:-$DEFAULT_TX_IP}
     CHOSEN_LATENCY_BUFFER_MS=${$2:-$DEFAULT_LATENCY_BUFFER_MS}
    
     echo "Launching TX on ${CHOSEN_TX_IP} with ${CHOSEN_LATENCY_BUFFER_MS} ms buffer."
    
     # Start TX, using hubcap ALSA device
     tx -d hubcap -m $(($CHOSEN_LATENCY_BUFFER_MS)) -h $CHOSEN_TX_IP &
    
     # Boost priority of all TX threads (necessary to prevent buffer underruns)
     TX_PIDS=$(ps -L -C tx -o lwp=)
     for TX_PID in TX_PIDS
     do
       sudo renice -10 $(($TX_PID))
     done
    
  7. 传输端 - 运行 tx 发送器:

     chmod +x ~/run_tx.sh        
     sudo ~/run_tx.sh 
    
  8. 接收端 - 安装软件包(仅运行 ALSA,不需要 PulseAudio):

     sudo su
     sudo apt install alsa-utils opus-tools lame vlc cmake libasound2-dev libortp-dev libopus-dev
     mkdir ~/Installers
     cd ~/Installers
     git clone http://www.pogo.org.uk/~mark/trx.git
     make
     sudo make install
    
  9. 接收方 - 创建 rx 初始化脚本:

     nano ~/run_rx.sh
    

    文件内容

     #!/bin/bash
     # Fires up the RX Reception side
     # Usage:
     #     sudo run_rx.sh [ip] [latency in ms]
     #     sudo run_rx.sh 239.0.0.99 64
    
     # Defaults
     DEFAULT_RX_IP="239.0.0.99"
     DEFAULT_LATENCY_BUFFER_MS="64"
    
     # Resolve from args
     CHOSEN_RX_IP=${$1:-$DEFAULT_RX_IP}
     CHOSEN_LATENCY_BUFFER_MS=${$2:-$DEFAULT_LATENCY_BUFFER_MS}
    
     echo "Launching RX receiver, listening on ${CHOSEN_RX_IP} with ${CHOSEN_LATENCY_BUFFER_MS} ms buffer."
    
     # Start RX, using default ALSA device
     rx -m $(($CHOSEN_LATENCY_BUFFER_MS)) -h $CHOSEN_RX_IP &
    
     # Boost priority of all RX threads (necessary to prevent buffer underruns)
     RX_PIDS=$(ps -L -C rx -o lwp=)
     for RX_PID in RX_PIDS
     do
       sudo renice -10 $(($RX_PID))
     done
    
  10. 接收端 - 运行 rx 监听器:

    chmod +x ~/run_rx.sh        
    sudo ~/run_rx.sh 
    
  11. 将 tx 端的某些内容播放到 PulseAudio 默认接收器 (localandtx) 中。它将通过接收设备的默认音频输出从接收端播放。

要指定在 rx 中播放的不同音频设备,请将该-d "alsa_device_name"选项添加到该rx -m $(($CHOSEN_LATENCY_BUFFER_MS)) -h $CHOSEN_RX_IP &行,例如rx -m $(($CHOSEN_LATENCY_BUFFER_MS)) -h $CHOSEN_RX_IP -d Headphones &

相关内容