pulseaudio: atrasa a saída do aplicativo por quantidade de tempo

pulseaudio: atrasa a saída do aplicativo por quantidade de tempo

Tenho um aplicativo em que o áudio está à frente do vídeo, então gostaria de atrasar o áudio por meio segundo. Atualmente, estou redirecionando o áudio do aplicativo para um módulo nulo pulseaudio e, em seguida, usando parec para enviar a saída do monitor para um programa de buffer externo, que então envia os dados meio segundo depois de volta para o pulso. Existe uma maneira mais fácil no pulseaudio de fazer isso?

Responder1

Omódulo de loopbackpermitirá que você adicione até 2 segundos de atraso entre uma fonte e um coletor.

Responder2

Gostaria de compartilhar meu script bash (chamado ”atraso pa”) que usa os módulos loopback e null-sink já mencionados porIgnácio Vázquez-Abramspara estabelecer uma cadeia de coletores virtuais e loopbacks de comprimento arbitrário. Estou usando ativamente este script. Os coletores são chamados Delay1, Delay2,… Delayne o script primeiro descarrega quaisquer coletores com esse nome e quaisquer loopbacks usando esses coletores que possam ter sido criados por uma execução anterior. Em seguida, ele constrói a cadeia com o comprimento exigido pelo atraso solicitado, que é especificado em milissegundos como parâmetro de linha de comando. (Um atraso de 0 fará com que o script remova a cadeia anterior e depois saia.) O primeiro coletor virtual, Delay1, é sempre aquele ao qual se conectar para obter o atraso total. Os coletores intermediários também poderiam, teoricamente, ser usados, e todos recebem descrições que indicam a quantidade de atraso que resultaria da conexão a eles. É importante que Delay1 seja sempre o coletor a ser usado porque (pelo menos para mim no XFCE) o sistema “lembra” a qual coletor um programa estava conectado. Um programa conectado ao coletor Delay1 será revertido para ele mesmo que a cadeia tenha sido inexistente por um tempo (durante o qual o programa será conectado ao dispositivo de saída padrão). Então eu posso ligaratraso paquantas vezes for necessário para ajustar a duração do atraso e sem intervenção adicional, qualquer programa que utilize o atraso utilizará a nova cadeia estabelecida para cada execução. Isso também se aplica depois que eu ligueipa-atraso 0para ter áudio sem atraso por mais tempo. Acho que depois de suspender o meu computador o atraso tende a ser maior do que o especificado (o que está de acordo com oavisoque olatência_msecO parâmetro para o módulo de loopback é “apenas uma solicitação amigável”), então também mudo para o estado “pa-delay 0” antes de suspender.

#! /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

informação relacionada