fix: 输出目标自动探测物理设备(去硬编码, 可移植); 加 91-clock 与 release 发布脚本

This commit is contained in:
edgevoid
2026-09-13 00:00:46 +08:00
parent 68db84a10c
commit 9d3265aa28
4 changed files with 99 additions and 5 deletions
+14 -4
View File
@@ -16,6 +16,7 @@ _ROOT = os.path.dirname(os.path.abspath(__file__))
# IR 目录: 环境变量优先(打包/安装场景指 /usr/share/cinema-spatial/hrir),
# 否则用项目内的软链 hrir/current (开发时换 HRTF 只改软链)。
IR = os.environ.get("CINEMA_SPATIAL_IR") or os.path.join(_ROOT, "hrir", "current")
OUT = os.environ.get("CINEMA_SPATIAL_OUT") or os.path.expanduser(
"~/.config/pipewire/pipewire.conf.d/90-cinema-spatial.conf"
)
@@ -68,6 +69,15 @@ def default_sink_name() -> str:
return first
# node.target —— filter-chain 的输出端必须送到"真实设备":
# - @DEFAULT_SINK@ 这类 pactl 占位符 PipeWire 不认(会当成设备名, 结果连到别的设备)
# - 完全不写则 WirePlumber 可能连错(实测连到 HDMI)
# 所以默认探测物理输出(优先 USB), 换设备后重跑本脚本即可。
# 也可 export CINEMA_SPATIAL_TARGET=<node.name> 强制指定。
_TARGET = os.environ.get("CINEMA_SPATIAL_TARGET") or default_sink_name()
TARGET_PROP = f'node.target = "{_TARGET}" ' if _TARGET else ""
def hrir_block(indent: str) -> list[str]:
"""12 个卷积器 + 6 个分发 + 左右耳混音。输入端口: cp<dir>:In"""
L: list[str] = []
@@ -107,14 +117,14 @@ def sink_51() -> list[str]:
' outputs = [ "mixL:Out" "mixR:Out" ]', " }",
" capture.props = { node.name = cinema_spatial_sink media.class = Audio/Sink "
"audio.channels = 6 audio.position = [ FL FR FC LFE BL BR ] }",
f' playback.props = {{ node.name = cinema_spatial_out node.passive = true node.target = "{default_sink_name()}" '
f' playback.props = {{ node.name = cinema_spatial_out {TARGET_PROP}'
"audio.channels = 2 audio.position = [ FL FR ] }",
" }", " }"]
return L
def sink_upmix() -> list[str]:
tgt = default_sink_name()
L = [" { name = libpipewire-module-filter-chain", " flags = [ nofail ]", " args = {",
' node.description = "电影院空间音频 (立体声上混)"',
' media.name = "Cinema Spatial Upmix"', " filter.graph = {", " nodes = [",
@@ -157,7 +167,7 @@ def sink_upmix() -> list[str]:
' outputs = [ "mixL:Out" "mixR:Out" ]', " }",
" capture.props = { node.name = cinema_spatial_up_sink media.class = Audio/Sink "
"audio.channels = 2 audio.position = [ FL FR ] }",
f' playback.props = {{ node.name = cinema_spatial_up_out node.passive = true node.target = "{tgt}" '
f' playback.props = {{ node.name = cinema_spatial_up_out {TARGET_PROP}'
"audio.channels = 2 audio.position = [ FL FR ] }",
" }", " }"]
return L
@@ -172,7 +182,7 @@ def main() -> int:
with open(OUT, "w", encoding="utf-8") as fh:
fh.write("\n".join(body))
print(f"已生成 {OUT} ({len(body)} 行)")
print(f"输出目标: {default_sink_name()}")
print(f"输出目标: {TARGET_PROP.replace('node.target = ', '').strip() or '自动(WirePlumber 路由到默认输出)'}")
return 0