pulseaudio:按時間量延遲應用程式的輸出

pulseaudio:按時間量延遲應用程式的輸出

我有一個應用程序,其中音訊位於視訊之前,因此我想將音訊延遲半秒。我目前正在將應用程式的音訊重定向到pulseaudio null 模組,然後使用parec 將監視器輸出發送到外部緩衝程序,然後半秒後將資料輸出回pulse。在pulseaudio中是否有更簡單的方法來做到這一點?

答案1

環回模組將允許您在來源和接收器之間添加最多 2 秒的延遲。

答案2

我想分享我的 bash 腳本(名為“帕延遲」)使用已經提到的環回和空接收器模組伊格納西奧·巴斯克斯·艾布拉姆斯建立任意長度的虛擬接收器和環回鏈。我正在積極使用這個腳本。這些接收器稱為 Delay1、Delay2、... Delayn並且腳本首先卸載該名稱的任何接收器以及使用這些接收器(可能是由先前運行創建的)的任何環回。然後,它將鏈建構成所請求的延遲所需的長度,該延遲以毫秒為單位指定為命令列參數。 (延遲為 0 將使腳本刪除前一個鏈,然後退出。)第一個虛擬接收器 Delay1 始終是要連接的虛擬接收器,以獲得完整的延遲。理論上也可以使用中間接收器,並且它們都給出了描述,說明連接到它們會導致的延遲量。重要的是,Delay1 始終是要使用的接收器,因為(至少對於我在 XFCE 中)系統「記住」程式連接到哪個接收器。即使該鏈已經不存在一段時間(在此期間程式將連接到預設輸出裝置),連接到 Delay1 接收器的程式也會恢復到它。所以我可以打電話帕延遲根據需要經常調整延遲長度,並且無需進一步幹預,任何使用延遲的程序都將使用每次運行建立的新鏈。這也適用於我打電話後PA延遲0獲得更長時間的無延遲音訊。我發現掛起計算機後,延遲往往比指定的要長(這與警告認為延遲_毫秒環回模組的參數是“僅友好請求”),因此我在掛起之前也更改為“pa-delay 0”狀態。

#! /bin/bash

delay_msec="$1"
if [[ ! $delay_msec =~ ^[0-9]+$ ]]; then
    echo "Usage: $( basename "$0" ) delay_milliseconds" >&2
    exit 2
fi
max_loopback_delay=2000

list_delay_loopback_modules() {
    pactl list modules short | grep -P '\tmodule-loopback\t(.*\s)?source=Delay[1-9][0-9]*[.]monitor(\s|$)' | cut -f1
}

list_delay_null_modules() {
    pactl list modules short | grep -P '\tmodule-null-sink\t(.*\s)?sink_name=Delay[1-9][0-9]*(\s|$)' | cut -f1
}

build_module_array() {
    local object_type="$1"
    local array="$( echo "$1" | sed 's/-/_/g' )"
    typeset -n array
    local object_list="$( 
        pactl list "$object_type" |
        perl -00 -p -e ' chomp; s{\s*\n\s*}{|}mg; s{$}{\n}; ' |
        sed -En -e 's/^[a-zA-Z ]* #([0-9]+)[|].*[|]Owner Module: ([0-9]+)[|].*/\1:\2/p'
    )"
    while IFS=: read object module; do
        array[$module]=$object
    done <<<"$object_list"
}

for module in $( list_delay_loopback_modules ); do
    pactl unload-module "$module"
done
for module in $( list_delay_null_modules ); do
    pactl unload-module "$module"
done

last_loopback_delay=$(( (delay_msec + max_loopback_delay - 1) % max_loopback_delay + 1 ))
loops=$(( (delay_msec - last_loopback_delay) / max_loopback_delay + 1 ))
(( loops > 0 )) || exit 0

nbsp="$( echo -e '\u00a0' )"
narrownbsp="$( echo -e '\u202f' )"
i=1
module="$( pactl load-module module-null-sink sink_name="Delay$i" sink_properties="device.description=\"Delay:${nbsp}${delay_msec}${narrownbsp}ms\"" )"
while (( ++i <= loops )); do
    module="$( pactl load-module module-null-sink sink_name="Delay$i" sink_properties="device.description=\"Delay:${nbsp}$(( delay_msec - (i - 1) * max_loopback_delay ))${narrownbsp}ms\"" )"
done
i=$loops
module="$( pactl load-module module-loopback source="Delay$i.monitor" latency_msec=$last_loopback_delay )"
last_loopback_module=$module
while (( --i > 0 )); do
    module="$( pactl load-module module-loopback source="Delay$i.monitor" sink=Delay$(( i + 1 )) latency_msec=$max_loopback_delay )"
done

build_module_array sinks
build_module_array sources
build_module_array sink-inputs
build_module_array source-outputs

for module in $( list_delay_null_modules ); do
    pactl set-source-volume ${sources[$module]} '100%'
    pactl set-sink-volume   ${sinks[$module]}   '100%'
done
for module in $( list_delay_loopback_modules ); do
    pactl set-source-output-volume ${source_outputs[$module]} '100%'
    test "$module" == "$last_loopback_module" && continue
    pactl set-sink-input-volume    ${sink_inputs[$module]}    '100%'
done

相關內容