d8c3a27821
- 离线渲染.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(离线渲染要卷积的素材)
176 lines
9.2 KiB
Bash
176 lines
9.2 KiB
Bash
#!/bin/bash
|
|
# 把电影院空间音频全链打包成 deb
|
|
# 2026-09-12 首版; 2026-09-13 v1.2.0 加响度归一化; v1.3.0 加离线渲染 + 组件看门狗
|
|
# 包名 collaplex-cinema-spatial, Arch: all (纯脚本+数据, 无编译)
|
|
set -eu
|
|
SRC="/home/lou/桌面/工作区/实验/空间音频"
|
|
PKG="collaplex-cinema-spatial"
|
|
VER="1.3.0"
|
|
BUILD="/tmp/${PKG}-deb"
|
|
ROOT="/usr/share/cinema-spatial"
|
|
SOFA_SRC="$SRC/sofa/H4_HRIR_SOFA/H4_HRIR_SOFA/H4_96K_24bit_512tap_FIR_SOFA.sofa"
|
|
|
|
echo "=== 1. 准备目录 ==="
|
|
rm -rf "$BUILD"
|
|
mkdir -p "$BUILD/DEBIAN" "$BUILD/usr/bin" \
|
|
"$BUILD${ROOT}/hrir" "$BUILD${ROOT}/sofa" "$BUILD${ROOT}/loudness" \
|
|
"$BUILD${ROOT}/config" "$BUILD${ROOT}/reverb" \
|
|
"$BUILD/usr/share/applications" \
|
|
"$BUILD/usr/share/pipewire/pipewire.conf.d"
|
|
|
|
# ★ 源必须是项目目录: 旧版从 ~/.local/bin 拷, 那份可能落后于项目(2026-09-13 补回丢失的 cp)
|
|
cp "$SRC/空间音频" "$SRC/mpv-影院" "$BUILD/usr/bin/"
|
|
chmod 755 "$BUILD/usr/bin/空间音频" "$BUILD/usr/bin/mpv-影院"
|
|
|
|
echo "=== 3. HRTF 数据 (12 个 IR + SOFA) ==="
|
|
cp "$SRC/hrir/H4-96k/"*.wav "$BUILD${ROOT}/hrir/"
|
|
cp "$SOFA_SRC" "$BUILD${ROOT}/sofa/"
|
|
|
|
echo "=== 4. 项目脚本与文档 ==="
|
|
# ★ 音频状态.py 是 CLI 的设备/状态后端(CLI 会去找 $ROOT/音频状态.py), 漏打会致
|
|
# "切设备/诊断"直接报"缺 音频状态.py" —— 2026-09-13 补
|
|
cp "$SRC/生成配置.py" "$SRC/音频状态.py" "$SRC/换HRTF.sh" "$SRC/README.md" "$BUILD${ROOT}/"
|
|
chmod 755 "$BUILD${ROOT}/换HRTF.sh"
|
|
|
|
echo "=== 4b. 响度归一化 (pipe 插件挂的自研 DSP) ==="
|
|
# ★ 包内一律用 ASCII 路径。pipe 插件的 command 传中文路径时**静默失效**
|
|
# —— 节点照建、音频绕过、DSP 不 fork、零日志(2026-09-13 排了一整轮)。
|
|
# DSP = $ROOT/loudness/loudness_norm.py
|
|
# wrapper = /usr/bin/collaplex-loudness-norm
|
|
# 项目开发目录仍是中文(响度归一化/), 只在打包时改名。
|
|
cp "$SRC/响度归一化/loudness_norm.py" "$SRC/响度归一化/read_state.py" "$BUILD${ROOT}/loudness/"
|
|
|
|
echo "=== 4c. 房间混响 IR (离线渲染要卷积它) ==="
|
|
# ★ 离线渲染.py 里混响 IR 与 SOFA 都是"多路径探测": 开发目录 reverb/房间混响IR-96k.wav,
|
|
# 包内 /usr/share/cinema-spatial/reverb/ 同名 —— 漏打这个包, 离线渲染的混响会静默不叠加。
|
|
cp "$SRC/reverb/房间混响IR-96k.wav" "$BUILD${ROOT}/reverb/"
|
|
|
|
echo "=== 4d. 离线渲染 + 组件看门狗 (v1.3.0) ==="
|
|
# 离线渲染.py: 音频/视频 -> 空间音频 FLAC(走同一套 5.1 上混 + SOFA HRTF + 混响 + loudnorm)
|
|
# 音频守护.py: 30 秒一轮核对 config/组件配置单.json, 扫到问题自动修
|
|
# 组件配置单: 机器可读的期望状态(json) + 人读版(md)
|
|
cp "$SRC/离线渲染.py" "$SRC/音频守护.py" "$SRC/组件配置单.md" "$BUILD${ROOT}/"
|
|
cp "$SRC/config/组件配置单.json" "$BUILD${ROOT}/config/"
|
|
chmod 755 "$BUILD${ROOT}/离线渲染.py" "$BUILD${ROOT}/音频守护.py"
|
|
# 右键"打开方式"入口: 包内落地到 /usr/bin(collaplex-render), 数据仍在 $ROOT
|
|
cp "$SRC/离线渲染-打开.sh" "$BUILD/usr/bin/collaplex-render"
|
|
chmod 755 "$BUILD/usr/bin/collaplex-render"
|
|
# 桌面项: 项目里存一份"包内版"模板(Exec 直接指向 /usr/bin/collaplex-render),
|
|
# 打包原样拷进 /usr/share/applications/ —— 不用 sed 现改, 免得模板与包内不一致。
|
|
cp "$SRC/桌面项/collaplex-render.desktop" "$BUILD/usr/share/applications/"
|
|
chmod 644 "$BUILD/usr/share/applications/collaplex-render.desktop"
|
|
cat > "$BUILD/usr/bin/collaplex-loudness-norm" <<'WRAP'
|
|
#!/bin/sh
|
|
# Collaplex 响度归一化 — pipe 插件入口(wrapper)
|
|
# ★ pipe 的 command 只支持「程序 + 一个参数」, 参数只能在这个脚本里设;
|
|
# ★ 路径必须纯 ASCII —— 中文路径会被 pipe 插件静默忽略
|
|
# (wrapper 是 ASCII, 它内部再去 exec 什么名字都没关系)。
|
|
export LN_MAX_BOOST=20
|
|
export LN_MAX_CUT=20
|
|
export LN_RATE=96000
|
|
exec /usr/bin/python3 /usr/share/cinema-spatial/loudness/loudness_norm.py
|
|
WRAP
|
|
chmod 755 "$BUILD/usr/bin/collaplex-loudness-norm"
|
|
|
|
echo "=== 5. PipeWire 配置 (用安装路径生成) ==="
|
|
mkdir -p "$BUILD${ROOT}/web"
|
|
cp "$SRC/web/index.html" "$SRC/web/webui.py" "$SRC/web/启动.sh" "$BUILD${ROOT}/web/"
|
|
chmod 755 "$BUILD${ROOT}/web/启动.sh"
|
|
|
|
# LN 入口用包内 ASCII 路径(不是开发机的 ~/.local/bin)
|
|
# ★ CINEMA_SPATIAL_KEEP_CONFS=1: 生成"包内那份"配置时**绝不能**去清理用户/系统目录 ——
|
|
# 否则打包动作会把正在用的那份移开, 虚拟声卡当场消失(2026-09-13 踩过)。
|
|
CINEMA_SPATIAL_IR="${ROOT}/hrir" \
|
|
CINEMA_SPATIAL_LN="/usr/bin/collaplex-loudness-norm" \
|
|
CINEMA_SPATIAL_OUT="$BUILD/usr/share/pipewire/pipewire.conf.d/90-cinema-spatial.conf" \
|
|
CINEMA_SPATIAL_KEEP_CONFS=1 \
|
|
python3 "$SRC/生成配置.py"
|
|
cp "$SRC/91-clock.conf" \
|
|
"$BUILD/usr/share/pipewire/pipewire.conf.d/"
|
|
|
|
echo "=== 6. control ==="
|
|
cat > "$BUILD/DEBIAN/control" <<EOF
|
|
Source: collaplex-cinema-spatial
|
|
Package: collaplex-cinema-spatial
|
|
Section: sound
|
|
Priority: optional
|
|
Architecture: all
|
|
Version: $VER
|
|
Maintainer: edgevoid <edgevoid@users.noreply.github.com>
|
|
Depends: pipewire, libmysofa1, mpv, xdg-utils, ffmpeg
|
|
Description: Cinema spatial audio for headphones (HRTF virtual surround)
|
|
Renders audio into binaural using a SADIE-II human HRTF through a PipeWire
|
|
filter-chain virtual sink, so ordinary headphones give a cinema-like
|
|
sense of direction and space.
|
|
.
|
|
Provides two virtual sinks (5.1 passthrough and stereo-upmixed), the
|
|
space-audio / mpv-cinema commands, and a web console on 127.0.0.1:8788.
|
|
.
|
|
Core: image-source room acoustics tracing (8473 early-reflection paths,
|
|
0-80 ms) + Sabine statistical tail (80 ms-2 s) -> a 96 kHz true room
|
|
impulse response, convolved binaurally; wet path energy-normalised.
|
|
.
|
|
Loudness normalisation: an external DSP fed by the filter-chain "pipe"
|
|
plugin levels every application to one adjustable target (-40..-6 dBFS)
|
|
at 6 dB/s slew, both channels sharing one gain so the image never drifts.
|
|
.
|
|
Offline rendering: the same chain (5.1 upmix -> SOFA HRTF -> room reverb
|
|
-> loudness) applied to files instead of the live sink, encoded to 96 kHz
|
|
binaural FLAC. Audio and video inputs (video's audio track is used). Two
|
|
guards: a render lock (no second job while one runs) and a landed-file
|
|
check (files still being written/downloaded are skipped).
|
|
.
|
|
Component watchdog: a 30 s loop verifies the whole chain against a
|
|
machine-readable spec (component states) and repairs what drifted.
|
|
EOF
|
|
|
|
echo "=== 7. 打包 ==="
|
|
cat > "$BUILD/DEBIAN/postinst" <<'EOF'
|
|
#!/bin/sh
|
|
set -e
|
|
if [ "$1" = "configure" ]; then
|
|
echo "collaplex-cinema-spatial 已安装。"
|
|
echo " 命令: 空间音频 开|开5.1|关|状态 mpv-影院 电影.mkv"
|
|
echo " 离线渲染: collaplex-render 片子.mp4 歌.mp3"
|
|
echo " (或文件管理器里右键 → 打开方式 → Collaplex 离线渲染)"
|
|
echo " 看门狗: python3 /usr/share/cinema-spatial/音频守护.py"
|
|
echo " (30 秒一轮核对 config/组件配置单.json, 扫到问题自动修)"
|
|
echo " 控制台: http://127.0.0.1:8788/ (Collaplex 音效)"
|
|
echo " 虚拟声卡: /usr/share/pipewire/pipewire.conf.d/"
|
|
echo " 生效: systemctl --user restart pipewire pipewire-pulse wireplumber"
|
|
# ★ PipeWire 对 conf.d/*.conf **两份都加载**(不做用户级覆盖系统级)。若用户目录里
|
|
# 还有一份开发时生成的同名配置, 就会建出两套同名节点 —— 音频进错那一份 = 没声音。
|
|
echo " ★ 检查用户目录是否还有一份同名配置(有就会被同时加载, 症状=没声音):"
|
|
echo " ls ~/.config/pipewire/pipewire.conf.d/90-cinema-spatial.conf 91-clock.conf"
|
|
echo " 有就移开: mv ~/.config/pipewire/pipewire.conf.d/<文件>{,.disabled-dup}"
|
|
# 装完把控制台直接推给用户看: 先把面板起起来(已经在跑就不重复起), 再开浏览器。
|
|
# 注意本脚本是 root 身份跑的, 要 su 到登录用户 + 补上 XDG_RUNTIME_DIR,
|
|
# 否则 xdg-open 找不到会话总线/显示, 一声不吭什么都不发生。
|
|
U=""
|
|
if command -v loginctl >/dev/null 2>&1; then
|
|
U=$(loginctl list-sessions --no-legend 2>/dev/null | awk '{print $3}' | grep -v '^root$' | head -1 || true)
|
|
fi
|
|
if [ -z "$U" ] && command -v who >/dev/null 2>&1; then
|
|
U=$(who 2>/dev/null | awk 'NR==1{print $1}' || true)
|
|
fi
|
|
if [ -n "$U" ] && [ "$U" != "root" ]; then
|
|
UID_=$(id -u "$U" 2>/dev/null || true)
|
|
if [ -n "$UID_" ]; then
|
|
su - "$U" -c "XDG_RUNTIME_DIR=/run/user/$UID_ /usr/share/cinema-spatial/web/启动.sh" >/dev/null 2>&1 || true
|
|
sleep 2
|
|
su - "$U" -c "XDG_RUNTIME_DIR=/run/user/$UID_ setsid -f xdg-open http://127.0.0.1:8788/ >/dev/null 2>&1" || true
|
|
echo " (已为用户 $U 启动控制台并打开浏览器)"
|
|
fi
|
|
fi
|
|
fi
|
|
EOF
|
|
chmod 755 "$BUILD/DEBIAN/postinst"
|
|
dpkg-deb -b --root-owner-group "$BUILD" "$HOME/桌面/${PKG}_${VER}_all.deb"
|
|
echo
|
|
echo "=== 结果 ==="
|
|
ls -lh "$HOME/桌面/${PKG}_${VER}_all.deb"
|
|
echo
|
|
dn=$(dpkg-deb -c "$HOME/桌面/${PKG}_${VER}_all.deb" | wc -l)
|
|
echo "包内文件数: $dn"
|
|
dpkg-deb -c "$HOME/桌面/${PKG}_${VER}_all.deb" | awk '{print $6}' | grep -v "/$"
|