Add audio backend fix: DeckLink → ALSA + snd-aloop loopback
Resolve aborts on first launch on systems without a DeckLink card (default Local.Audio.Type = DeckLink), and Resolve's audio engine retries forever enumerating raw ALSA hardware when PipeWire owns every real card — the "render queue stuck in progress with no output" hang. Patches default-config.dat (and any existing user config.dat) to ALSA, then loads snd-aloop as a virtual ALSA card PipeWire ignores, persists it via /etc/modules-load.d/, and writes a PipeWire loopback bridge so monitor audio remains audible during playback. Skip with RESOLVE_NO_ALOOP=1. Ported from the Intel Arc installer where the fix was originally debugged.
This commit is contained in:
parent
f387d84414
commit
b9b8dbc6dc
2 changed files with 211 additions and 1 deletions
|
|
@ -432,9 +432,120 @@ EOF
|
|||
update-desktop-database "${HOME}/.local/share/applications" >/dev/null 2>&1 || true
|
||||
sudo gtk-update-icon-cache -f /usr/share/icons/hicolor >/dev/null 2>&1 || true
|
||||
|
||||
# ==================== Audio backend fix (DeckLink → ALSA) ====================
|
||||
#
|
||||
# Resolve ships with `Local.Audio.Type = DeckLink` as the default in its
|
||||
# system-wide config template at /opt/resolve/share/default-config.dat.
|
||||
# That's correct for users with a Blackmagic DeckLink capture/playback card,
|
||||
# but on systems without one Resolve aborts on first launch. Patch both the
|
||||
# template (so future first-launches are correct) and any existing user
|
||||
# config (so the current install isn't broken).
|
||||
log "Switching Resolve audio backend default from DeckLink to ALSA..."
|
||||
TEMPLATE=/opt/resolve/share/default-config.dat
|
||||
if [[ -f "${TEMPLATE}" ]] && grep -q '^Local\.Audio\.Type = DeckLink$' "${TEMPLATE}"; then
|
||||
sudo sed -i 's|^Local\.Audio\.Type = DeckLink$|Local.Audio.Type = ALSA|' "${TEMPLATE}"
|
||||
log " Patched system template ${TEMPLATE}"
|
||||
fi
|
||||
USER_CFG="${HOME}/.local/share/DaVinciResolve/configs/config.dat"
|
||||
if [[ -f "${USER_CFG}" ]] && grep -q '^Local\.Audio\.Type = DeckLink$' "${USER_CFG}"; then
|
||||
cp "${USER_CFG}" "${USER_CFG}.bak.$(date +%s)"
|
||||
sed -i 's|^Local\.Audio\.Type = DeckLink$|Local.Audio.Type = ALSA|' "${USER_CFG}"
|
||||
log " Patched existing user config ${USER_CFG} (backup .bak.<timestamp> created)"
|
||||
fi
|
||||
|
||||
# ==================== snd-aloop (the actual render-blocker fix) ====================
|
||||
#
|
||||
# Resolve's audio engine opens raw ALSA hardware via snd_pcm_open("hw:%d", ...)
|
||||
# — it never goes through ALSA's plugin layer (default/pulse/pipewire) and it
|
||||
# enumerates EVERY card under /dev/snd/controlC[0-32] looking for a usable PCM.
|
||||
# When every real ALSA card on the system is owned/contested by PipeWire's
|
||||
# session manager, Resolve's enumeration loops forever, the render queue
|
||||
# never spawns the encoder, and the user sees:
|
||||
# - alsa device meters "flickering" in wireplumber (each enumeration cycle
|
||||
# briefly opens controlC*; PipeWire reacts)
|
||||
# - render that "won't start" with no error in ResolveDebug.txt
|
||||
# Confirmed via strace: 14000+ SNDRV_CTL_IOCTL_PCM_INFO ENXIO ioctls and
|
||||
# 47000+ /dev/snd/controlCN ENOENT opens during the failed render attempt,
|
||||
# concentrated AFTER the user clicks Render — i.e. a tight retry loop.
|
||||
#
|
||||
# THE FIX: load the kernel's snd-aloop module. It exposes a virtual ALSA
|
||||
# loopback card that PipeWire ignores (no ACP profile, not auto-acquired).
|
||||
# Resolve's enumerator finds it, can fully own it, settles on it, and the
|
||||
# render proceeds. Side effect: a "Loopback" device shows up in alsamixer
|
||||
# and pavucontrol — harmless.
|
||||
#
|
||||
# Skipped if RESOLVE_NO_ALOOP=1 (e.g. user already has a dedicated audio
|
||||
# interface that Resolve uses). Persistent across reboots via
|
||||
# /etc/modules-load.d/.
|
||||
if [[ "${RESOLVE_NO_ALOOP:-0}" == "1" ]]; then
|
||||
log "Skipping snd-aloop setup (RESOLVE_NO_ALOOP=1)"
|
||||
else
|
||||
log "Setting up snd-aloop (virtual ALSA card so Resolve render can start)..."
|
||||
if ! lsmod | grep -qE '^snd_aloop'; then
|
||||
if sudo modprobe snd-aloop 2>/dev/null; then
|
||||
log " snd-aloop loaded for the current session"
|
||||
else
|
||||
warn " modprobe snd-aloop failed — kernel may lack the module."
|
||||
warn " On Arch this is part of linux/linux-zen/linux-lts; verify: modinfo snd-aloop"
|
||||
fi
|
||||
else
|
||||
log " snd-aloop already loaded"
|
||||
fi
|
||||
ALOOP_CONF=/etc/modules-load.d/snd-aloop.conf
|
||||
if [[ ! -f "${ALOOP_CONF}" ]] || ! grep -qx 'snd-aloop' "${ALOOP_CONF}" 2>/dev/null; then
|
||||
echo 'snd-aloop' | sudo tee "${ALOOP_CONF}" >/dev/null
|
||||
log " Wrote ${ALOOP_CONF} (autoloads at boot)"
|
||||
else
|
||||
log " ${ALOOP_CONF} already configured"
|
||||
fi
|
||||
|
||||
# Bridge snd-aloop capture → default sink so monitor audio is audible.
|
||||
# Without this, Resolve writes to the loopback and the audio goes nowhere
|
||||
# (loopback is a black hole until something captures the other side).
|
||||
# The bridge is a PipeWire loopback module loaded from user config; it
|
||||
# tracks the default sink so headphone/HDMI switching keeps working.
|
||||
ALOOP_BRIDGE_DIR="${HOME}/.config/pipewire/pipewire.conf.d"
|
||||
ALOOP_BRIDGE_FILE="${ALOOP_BRIDGE_DIR}/50-resolve-aloop-bridge.conf"
|
||||
mkdir -p "${ALOOP_BRIDGE_DIR}"
|
||||
if [[ ! -f "${ALOOP_BRIDGE_FILE}" ]]; then
|
||||
cat > "${ALOOP_BRIDGE_FILE}" <<'EOF'
|
||||
# DaVinci Resolve aloop monitor bridge — managed by Omarchy_resolve_v2.sh
|
||||
# Bridges snd-aloop's capture side to the system default sink so Resolve's
|
||||
# monitor audio is audible while editing. Without this, Resolve renders fine
|
||||
# but you hear nothing during playback. Remove this file + restart PipeWire
|
||||
# to disable.
|
||||
context.modules = [
|
||||
{ name = libpipewire-module-loopback
|
||||
args = {
|
||||
node.description = "DaVinci Resolve aloop monitor bridge"
|
||||
capture.props = {
|
||||
node.name = "resolve-aloop-capture"
|
||||
target.object = "alsa_input.platform-snd_aloop.0.analog-stereo"
|
||||
node.passive = true
|
||||
}
|
||||
playback.props = {
|
||||
node.name = "resolve-aloop-playback"
|
||||
media.class = "Stream/Output/Audio"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
EOF
|
||||
log " Wrote ${ALOOP_BRIDGE_FILE} (PipeWire loopback bridge)"
|
||||
# Reload user PipeWire services so the new conf is picked up
|
||||
if systemctl --user is-active --quiet pipewire 2>/dev/null; then
|
||||
systemctl --user restart pipewire pipewire-pulse wireplumber 2>/dev/null || true
|
||||
log " Reloaded user PipeWire services"
|
||||
fi
|
||||
else
|
||||
log " ${ALOOP_BRIDGE_FILE} already in place"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "✅ DaVinci Resolve installed to /opt/resolve"
|
||||
echo " (vendor libc++ kept; libcrypt.so.1 ensured)"
|
||||
echo " (vendor libc++ kept; libcrypt.so.1 ensured; audio backend → ALSA + snd-aloop)"
|
||||
echo " Launch from your app menu, or run: resolve-nvidia-open"
|
||||
echo " Skip snd-aloop module setup: RESOLVE_NO_ALOOP=1 ./Omarchy_resolve_v2.sh"
|
||||
echo " Logs: ~/.local/share/DaVinciResolve/logs/ResolveDebug.txt"
|
||||
echo
|
||||
|
|
|
|||
99
README.md
99
README.md
|
|
@ -97,6 +97,41 @@ Resolve doesn't support native Wayland. The wrapper script (`resolve-nvidia-open
|
|||
- Installs udev rules for Blackmagic hardware (capture cards, control panels)
|
||||
- Points all launchers at the XWayland wrapper
|
||||
|
||||
### 7. Audio Backend Fix (DeckLink → ALSA + `snd-aloop`)
|
||||
|
||||
Two issues are fixed automatically:
|
||||
|
||||
**Default audio backend.** Resolve's shipped `default-config.dat` sets
|
||||
`Local.Audio.Type = DeckLink`, which causes Resolve to abort on first launch
|
||||
on systems without a Blackmagic DeckLink capture/playback card. The script
|
||||
patches both the system template and any existing user config to use `ALSA`
|
||||
(backing up the user config to `config.dat.bak.<timestamp>`).
|
||||
|
||||
**Render-blocker hang.** Resolve's audio engine opens raw ALSA hardware
|
||||
(`hw:N`) and enumerates every card under `/dev/snd/control*`. When all real
|
||||
ALSA cards are owned/contested by PipeWire's session manager, the
|
||||
enumeration retries forever — the render queue never spawns the encoder, the
|
||||
job sits at "in progress" with growing ETA, no output file appears, and
|
||||
nothing useful lands in `ResolveDebug.txt`. `strace` shows tens of thousands
|
||||
of `SNDRV_CTL_IOCTL_PCM_INFO` `ENXIO` ioctls per failed render.
|
||||
|
||||
The fix is to load the kernel's `snd-aloop` module. PipeWire ignores it (no
|
||||
ACP profile, not auto-acquired), so Resolve can fully own it and the render
|
||||
proceeds normally. The script:
|
||||
|
||||
- Runs `modprobe snd-aloop` for the current session
|
||||
- Writes `/etc/modules-load.d/snd-aloop.conf` so it autoloads at boot
|
||||
- Writes a PipeWire loopback bridge at
|
||||
`~/.config/pipewire/pipewire.conf.d/50-resolve-aloop-bridge.conf` so
|
||||
monitor audio routes from the loopback's capture side to the system
|
||||
default sink (without it, Resolve renders fine but you hear nothing
|
||||
during playback; headphone/HDMI sink switching keeps working through
|
||||
the bridge)
|
||||
- Restarts user PipeWire services so the bridge loads immediately
|
||||
|
||||
Set `RESOLVE_NO_ALOOP=1` to skip this entirely (useful if you have a
|
||||
dedicated audio interface Resolve already uses cleanly).
|
||||
|
||||
## Files Installed
|
||||
|
||||
### Application
|
||||
|
|
@ -145,6 +180,18 @@ By default, the script syncs the package database without upgrading. To include
|
|||
RESOLVE_FULL_UPGRADE=1 ./Omarchy_resolve_v2.sh
|
||||
```
|
||||
|
||||
### Skip the `snd-aloop` Audio Fix
|
||||
|
||||
If you have a dedicated audio interface (e.g. Focusrite Scarlett, MOTU, etc.)
|
||||
that Resolve already uses cleanly, you don't need the virtual loopback card:
|
||||
|
||||
```bash
|
||||
RESOLVE_NO_ALOOP=1 ./Omarchy_resolve_v2.sh
|
||||
```
|
||||
|
||||
This skips the `modprobe snd-aloop`, the `/etc/modules-load.d/` entry, and
|
||||
the PipeWire loopback bridge. The DeckLink → ALSA config patch still runs.
|
||||
|
||||
### Hybrid GPU Laptops (Optimus)
|
||||
|
||||
If you have an Intel iGPU + NVIDIA dGPU, edit the wrapper to force Resolve onto the NVIDIA GPU:
|
||||
|
|
@ -180,6 +227,53 @@ Stale lockfiles from a previous crash. The wrapper clears these automatically, b
|
|||
rm -f /tmp/qtsingleapp-DaVinci*
|
||||
```
|
||||
|
||||
### Render queue says "in progress" forever, no output file
|
||||
|
||||
This is the audio render-blocker hang — Resolve's audio engine is stuck
|
||||
enumerating ALSA cards. Confirm `snd-aloop` is loaded:
|
||||
|
||||
```bash
|
||||
lsmod | grep snd_aloop
|
||||
```
|
||||
|
||||
If absent, load it and retry:
|
||||
|
||||
```bash
|
||||
sudo modprobe snd-aloop
|
||||
```
|
||||
|
||||
If you ran the installer with `RESOLVE_NO_ALOOP=1` and want to opt back in,
|
||||
re-run the installer without that variable, or do it manually:
|
||||
|
||||
```bash
|
||||
sudo modprobe snd-aloop
|
||||
echo 'snd-aloop' | sudo tee /etc/modules-load.d/snd-aloop.conf
|
||||
```
|
||||
|
||||
If `lsmod` shows `snd_aloop` is loaded but renders still hang, check the
|
||||
clip codec with `ffprobe` — ProRes RAW will hang silently on Linux without
|
||||
Apple's ProRes RAW SDK plugins, which is a separate issue from this audio
|
||||
fix.
|
||||
|
||||
### No audio during playback / monitor sink switches don't work
|
||||
|
||||
The PipeWire loopback bridge at
|
||||
`~/.config/pipewire/pipewire.conf.d/50-resolve-aloop-bridge.conf` routes
|
||||
the snd-aloop capture side to your default sink. If headphone/HDMI
|
||||
switching stops working for Resolve playback, restart user PipeWire
|
||||
services:
|
||||
|
||||
```bash
|
||||
systemctl --user restart pipewire pipewire-pulse wireplumber
|
||||
```
|
||||
|
||||
To remove the bridge entirely:
|
||||
|
||||
```bash
|
||||
rm ~/.config/pipewire/pipewire.conf.d/50-resolve-aloop-bridge.conf
|
||||
systemctl --user restart pipewire pipewire-pulse wireplumber
|
||||
```
|
||||
|
||||
### Missing library errors
|
||||
|
||||
Re-run the installer — it will re-patch RPATH and re-check dependencies:
|
||||
|
|
@ -233,6 +327,11 @@ sudo rm -f /usr/lib/udev/rules.d/99-BlackmagicDevices.rules
|
|||
sudo rm -f /usr/lib/udev/rules.d/99-ResolveKeyboardHID.rules
|
||||
sudo rm -f /usr/lib/udev/rules.d/99-DavinciPanel.rules
|
||||
|
||||
# Remove the snd-aloop autoload entry + PipeWire bridge (optional)
|
||||
sudo rm -f /etc/modules-load.d/snd-aloop.conf
|
||||
rm -f ~/.config/pipewire/pipewire.conf.d/50-resolve-aloop-bridge.conf
|
||||
systemctl --user restart pipewire pipewire-pulse wireplumber
|
||||
|
||||
# Remove user data (WARNING: deletes all projects and settings)
|
||||
rm -rf ~/.local/share/DaVinciResolve
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue