v1.3.0: 离线渲染(音频/视频→空间音频FLAC, 渲染锁+文件就绪检查) + 组件看门狗(30s核对期望状态并自愈)
- 离线渲染.py: pan上混5.1 → sofalizer(H4 SOFA) → 房间IR(afir) → loudnorm → 96k FLAC
视频自动取音轨; 已是5.1的片源不重上混; 实测约 4.4 倍速
两道锁: (1)渲染锁 —— 一轮任务期间拒绝新任务, 不排队堆积
(2)文件就绪检查 —— 相隔1.2s两次stat大小/时间不变且ffprobe能读, 未落盘的跳过
三个入口: 命令行 / 面板「离线渲染」区(拖拽或贴路径, 实时进度+日志+取消) / 右键「打开方式」
- 音频守护.py + config/组件配置单.json: 30s 核对 DSP进程数与槽位新鲜度/链输出连线/
默认设备/虚拟声卡优先级/中间级音量/节点份数/面板/物理设备静音, 扫到就修
(能温和就温和, 链路级才重建), 同类问题 90s 冷却, 连续 3 次修不好转只报警
- 组件配置单.md: 链路拓扑 + 组件表 + 六个必须 + 自愈表
- 面板: 控制滑块从图表卡片独立成「控制」卡片; 数字/模拟输出音量条拉长到各占一半
(合计 = 虚拟声卡开关卡片总高); 新增离线渲染区
- 修: DSP 孤儿抢共享槽位导致重建后无声(claim_slot 抢不到槽位即退出 + 重建前收旧 DSP)
- 修: 打包会把正在用的 PipeWire 配置移开(prune_duplicate_confs 只在自己写到生效目录时清理)
- 修: 离线渲染的 SOFA/混响IR 改为多路径探测(开发目录与 deb 包内布局不同)
- .gitignore: 保留 reverb/ 房间IR(离线渲染要卷积的素材)
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
{
|
||||
"_说明": "电影院空间音频链路 —— 组件期望状态单。音频守护.py 读本文件逐项核对, 不符合就自动修复。",
|
||||
"_版本": "2026-09-13",
|
||||
"_依据": "2026-09-13 全链路修复后实测的稳定状态(当晚修掉 6 个坑: 双份conf/中间级被写坏/两滑块同源/上混未归一/HDMI抢默认/DSP孤儿)",
|
||||
|
||||
"项目目录": "/home/lou/桌面/工作区/实验/空间音频",
|
||||
"配置真源": "~/.config/pipewire/pipewire.conf.d/{90-cinema-spatial.conf,91-clock.conf}",
|
||||
"状态目录": "~/.local/state/cinema-spatial",
|
||||
"日志": "~/.local/state/cinema-spatial/guardian.log",
|
||||
|
||||
"节点": {
|
||||
"_说明": "滤波链的全部节点, 每个名字必须**恰好 1 份**(双份同名 conf 会各建一套 → 整链静默)",
|
||||
"全部": [
|
||||
"cinema_spatial_sink",
|
||||
"cinema_spatial_out",
|
||||
"cinema_spatial_up_sink",
|
||||
"cinema_spatial_up_norm",
|
||||
"cinema_spatial_up_raw",
|
||||
"cinema_spatial_up_out"
|
||||
],
|
||||
"必须单位增益": [
|
||||
"cinema_spatial_up_norm",
|
||||
"cinema_spatial_up_raw"
|
||||
],
|
||||
"_单位增益说明": "中间两级是链内部节点, 不归用户调。被写低会凭空掉十几 dB, 而账面只算首尾两级 → 看着正常却没声音",
|
||||
"虚拟声卡": [
|
||||
"cinema_spatial_up_sink",
|
||||
"cinema_spatial_sink"
|
||||
],
|
||||
"虚拟声卡最低优先级": 2000,
|
||||
"_优先级说明": "priority.session 必须压过所有物理输出(本机 HDMI 1196 / USB 1108 / 板载 1009), 否则默认设备被 HDMI 抢走且点不回来"
|
||||
},
|
||||
|
||||
"默认输出": {
|
||||
"必须是": "cinema_spatial_up_sink",
|
||||
"_说明": "媒体键/GNOME 顶栏改的就是这一级的音量, 由面板的菜单音量桥折算到物理输出"
|
||||
},
|
||||
|
||||
"DSP": {
|
||||
"脚本": "响度归一化/loudness_norm.py",
|
||||
"进程数": 2,
|
||||
"_进程数说明": "左右声道各一。多于 2 个 = 孤儿抢共享槽位 → 整链静音; 0 个 = 链里没有消费者 → 静音",
|
||||
"共享区": "/dev/shm/collaplex-loudness",
|
||||
"槽位数": 2,
|
||||
"槽位新鲜秒": 5,
|
||||
"_新鲜度说明": "每个槽 +16 是 f64 时刻, 超过该秒数没更新即为僵死",
|
||||
"目标响度dBFS": -14.0,
|
||||
"输出峰值上限": 0.985,
|
||||
"_输出峰值说明": "PEAK_CEIL, DSP 输出不会超过 -0.13 dBFS",
|
||||
"参数": {
|
||||
"LN_MAX_BOOST": 12,
|
||||
"LN_PEAK_CEIL": 0.985,
|
||||
"LN_FADE_BLOCKS": 4,
|
||||
"LN_FADE_GAP_BLOCKS": 24
|
||||
}
|
||||
},
|
||||
|
||||
"物理输出": {
|
||||
"匹配": "alsa_output.usb-EDIFIER_Technology_EDIFIER_Fit900NB_4250315939393214-00.iec958-stereo",
|
||||
"_匹配说明": "USB 耳机重启后 profile 可能在 iec958-stereo / analog-stereo 之间变, 名字会变; 所以按 EDIFIER 前缀匹配即可",
|
||||
"_路由": "数字(S/PDIF) 优先, 96kHz/24bit(S24LE); 实测音质优于模拟"
|
||||
},
|
||||
|
||||
"上混链": {
|
||||
"输出端": "cinema_spatial_up_out",
|
||||
"_输出端说明": "它的 output_FL/FR 必须显式连到物理设备的 playback_FL/FR",
|
||||
"六路能量归一": 0.4082,
|
||||
"_归一说明": "mixL/mixR 的 6 路 Gain 必须都是 1/sqrt(6)=0.4082; 每路 1.0 会让上混净增益 +6dB, 顶穿满刻度"
|
||||
},
|
||||
|
||||
"时钟": {
|
||||
"采样率": 96000,
|
||||
"允许": [96000],
|
||||
"_说明": "链路全程 96kHz; HRTF=SADIE-II H4 96k/512tap"
|
||||
},
|
||||
|
||||
"面板": {
|
||||
"端口": 8788,
|
||||
"脚本": "web/webui.py",
|
||||
"启动": "web/启动.sh",
|
||||
"_说明": "常驻; 内含菜单音量桥(系统音量键 → 扬声器电平)和电平采集"
|
||||
},
|
||||
|
||||
"看门狗": {
|
||||
"间隔秒": 30,
|
||||
"冷却秒": 90,
|
||||
"连续失败告警": 3,
|
||||
"_说明": "同一类问题在冷却期内不重复动手; 连续 3 次修不好就只报警不再折腾"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user