Raspberry-Pi

在純 ALSA 中複製音頻以在本地設備上播放並通過 trx 流式傳輸

  • February 7, 2021

我正在嘗試使用 Raspberry Pis 在我家中實現多房間音頻設置。如何讓 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 程序的 niceness 更改為 -10 可以輕鬆解決。

renice -n -10 {process_id}

問題:

我希望能夠將音頻從 VLC 播放到網路上偵聽多播 239.0.0.99 的設備,也可以從傳輸設備的耳機/線路輸出插座播放音頻。

我不知道如何在 ~/.asoundrc 中設置一個插頭、路由和多路,以便有一個 ALSA 設備 cvlc 可以播放,其中音頻被饋送到本地 hw:1(耳機插座)和 plug:tx (通過 tx 傳輸音頻的輸入)。

ALSA 合理的配置文件非常糟糕。我嘗試了以下對 .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 的音頻路由?

我終於解決了多房間音頻 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 -司機/

在本地和通過 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
  1. 傳輸端 - 將使用者添加到音頻組:
sudo usermod -a -G audio your_username
  1. 傳輸端 - 啟動 alsa loopback 模組:
modprobe snd-aloop
echo "snd-aloop" | sudo tee -a /etc/modules
  1. 傳輸端 - 設置 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"
}
  1. 傳輸端 - 設置 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
  1. 傳輸端 - 創建 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
  1. 傳輸端 - 執行 tx 發送方:
chmod +x ~/run_tx.sh        
sudo ~/run_tx.sh 
  1. 接收端 - 安裝包(只執行 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
  1. 接收方 - 創建 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
  1. 接收端 - 執行 rx 監聽器:
chmod +x ~/run_rx.sh        
sudo ~/run_rx.sh 
  1. 在 tx 端播放一些東西到 PulseAudio 預設接收器(localandtx)。它將通過 rx 設備的預設音頻輸出從 rx 端播放。

要在 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 &

引用自:https://unix.stackexchange.com/questions/629604