オーディオがビデオより先に再生されるアプリが 1 つあるので、オーディオを 0.5 秒遅らせたいと思っています。現在、アプリのオーディオを pulseaudio の null モジュールにリダイレクトし、parec を使用してモニター出力を外部バッファリング プログラムに送信しています。外部バッファリング プログラムでは、データが 0.5 秒後に pulse に出力されます。pulseaudio 内でこれを行うより簡単な方法はありますか?
答え1
のループバックモジュールソースとシンクの間に最大 2 秒の遅延を追加できます。
答え2
私は自分のbashスクリプト(「pa遅延”)は、すでに述べたループバックモジュールとヌルシンクモジュールを使用します。イグナシオ・バスケス・エイブラムス任意の長さの仮想シンクとループバックのチェーンを確立します。私はこのスクリプトを積極的に使用しています。シンクはDelay1、Delay2、…Delayと呼ばれます。んそしてスクリプトは最初にその名前のシンクと、以前の実行で作成された可能性のあるこれらのシンクを使用するループバックをすべてアンロードします。次に、コマンドラインパラメータとしてミリ秒単位で指定される要求された遅延に必要な長さまでチェーンを構築します。(遅延が 0 の場合、スクリプトは以前のチェーンを削除してから終了します。) 最初の仮想シンクである Delay1 は、完全な遅延を得るために常に接続されるシンクです。中間のシンクも理論的には使用できますが、それらはすべて、接続によって生じる遅延の量を示す説明が与えられています。Delay1 が常に使用するシンクであることが重要です。なぜなら、(少なくとも私の XFCE の場合) システムはプログラムがどのシンクに接続されたかを「記憶」しているからです。Delay1 シンクに接続されたプログラムは、チェーンがしばらく存在していなかった場合でも (その間、プログラムはデフォルトの出力デバイスに接続されます)、そのシンクに戻ります。したがって、次のように呼び出すことができます。pa遅延遅延の長さを調整するために必要な回数だけ実行し、それ以上介入することなく、遅延を使用するプログラムは実行ごとに確立された新しいチェーンを使用します。これは、私が呼び出した後にも適用されます。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