AgentSkillsCN

rust-rodio-wsl2-audio

修复在 WSL2 上使用 rodio/cpal 时遇到的 Rust 音频编译与运行时问题。适用场景如下:(1) 构建时出现“crate ‘alsa-sys’ 所需的系统库 ‘alsa’ 未找到”的错误;(2) 无法在无 sudo 权限的情况下安装 libasound2-dev;(3) 即使编译成功,仍可能在运行时出现“未知 PCM 默认设备”或“无法找到卡 ‘0’”的错误。本修复方案既提供了手动提取 .deb 包的编译 workaround,也提出了通过 ALSA 到 PulseAudio 路由实现的运行时修复方案。

SKILL.md
--- frontmatter
name: rust-rodio-wsl2-audio
description: |
  Fix Rust audio compilation and runtime issues on WSL2 using rodio/cpal. Use when:
  (1) Build fails with "The system library 'alsa' required by crate 'alsa-sys' was not found",
  (2) Cannot install libasound2-dev without sudo access, (3) Runtime error "Unknown PCM default"
  or "cannot find card '0'" even after successful compilation. Covers compilation workaround
  using manual .deb extraction AND runtime fix using ALSA-to-PulseAudio routing.
author: Claude Code
version: 2.0.0
date: 2026-01-23

Rust Audio (rodio) on WSL2

Problem

Compiling and running Rust projects using rodio (or cpal) for audio on WSL2 fails at two stages:

  1. Compile time: Missing ALSA development headers
  2. Runtime: ALSA can't find audio devices because WSL2 uses PulseAudio via WSLg

Context / Trigger Conditions

Compilation Error

code
The system library `alsa` required by crate `alsa-sys` was not found.
The file `alsa.pc` needs to be installed and the PKG_CONFIG_PATH environment variable must contain its parent directory.

Runtime Error (after successful compilation)

code
ALSA lib confmisc.c:855:(parse_card) cannot find card '0'
ALSA lib pcm.c:2721:(snd_pcm_open_noupdate) Unknown PCM default
thread 'main' panicked at ... InitFailed

Solution

Part 1: Compilation Workaround (Without sudo)

If you can't install libasound2-dev via apt:

bash
# 1. Download the dev package without installing
cd /tmp
apt-get download libasound2-dev

# 2. Extract the package
mkdir -p /tmp/alsa-dev
dpkg-deb -x libasound2-dev_*.deb /tmp/alsa-dev

# 3. Fix the pkg-config file to point to extracted location
cat > /tmp/alsa-dev/usr/lib/x86_64-linux-gnu/pkgconfig/alsa.pc << 'EOF'
prefix=/tmp/alsa-dev/usr
exec_prefix=/tmp/alsa-dev/usr
libdir=/usr/lib/x86_64-linux-gnu
includedir=${prefix}/include

Name: alsa
Description: Advanced Linux Sound Architecture (ALSA) - Library
Version: 1.2.11
Libs: -L${libdir} -lasound
Cflags: -I${includedir}
EOF

# 4. Create the development symlink (links to system runtime library)
mkdir -p /tmp/alsa-dev/usr/lib/x86_64-linux-gnu
ln -sf /usr/lib/x86_64-linux-gnu/libasound.so.2 \
       /tmp/alsa-dev/usr/lib/x86_64-linux-gnu/libasound.so

# 5. Build with environment variables set
PKG_CONFIG_PATH=/tmp/alsa-dev/usr/lib/x86_64-linux-gnu/pkgconfig \
LIBRARY_PATH=/tmp/alsa-dev/usr/lib/x86_64-linux-gnu:$LIBRARY_PATH \
cargo build

Part 2: Runtime Fix - ALSA to PulseAudio Routing

This is the key to making audio actually work on WSL2!

bash
# 1. Download and extract the ALSA PulseAudio plugins
cd /tmp
apt-get download libasound2-plugins
mkdir -p /tmp/alsa-plugins
dpkg-deb -x libasound2-plugins*.deb /tmp/alsa-plugins

# 2. Create ~/.asoundrc to route ALSA through PulseAudio
cat > ~/.asoundrc << 'EOF'
# Route ALSA through PulseAudio for WSL2 compatibility
pcm.!default {
    type pulse
}

ctl.!default {
    type pulse
}
EOF

# 3. Run your application with ALSA_PLUGIN_DIR set
ALSA_PLUGIN_DIR=/tmp/alsa-plugins/usr/lib/x86_64-linux-gnu/alsa-lib \
./target/debug/your-app

Complete One-Liner Setup

bash
# Run this once to set up everything
cd /tmp && \
apt-get download libasound2-dev libasound2-plugins && \
mkdir -p /tmp/alsa-dev /tmp/alsa-plugins && \
dpkg-deb -x libasound2-dev_*.deb /tmp/alsa-dev && \
dpkg-deb -x libasound2-plugins*.deb /tmp/alsa-plugins && \
mkdir -p /tmp/alsa-dev/usr/lib/x86_64-linux-gnu && \
ln -sf /usr/lib/x86_64-linux-gnu/libasound.so.2 /tmp/alsa-dev/usr/lib/x86_64-linux-gnu/libasound.so && \
cat > /tmp/alsa-dev/usr/lib/x86_64-linux-gnu/pkgconfig/alsa.pc << 'PCEOF'
prefix=/tmp/alsa-dev/usr
exec_prefix=/tmp/alsa-dev/usr
libdir=/usr/lib/x86_64-linux-gnu
includedir=${prefix}/include
Name: alsa
Description: ALSA
Version: 1.2.11
Libs: -L${libdir} -lasound
Cflags: -I${includedir}
PCEOF
cat > ~/.asoundrc << 'ASOUNDEOF'
pcm.!default { type pulse }
ctl.!default { type pulse }
ASOUNDEOF
echo "Setup complete!"

Build and Run Commands

bash
# Build
PKG_CONFIG_PATH=/tmp/alsa-dev/usr/lib/x86_64-linux-gnu/pkgconfig \
LIBRARY_PATH=/tmp/alsa-dev/usr/lib/x86_64-linux-gnu \
cargo build

# Run with audio
ALSA_PLUGIN_DIR=/tmp/alsa-plugins/usr/lib/x86_64-linux-gnu/alsa-lib \
./target/debug/your-app

Verification

Compilation success:

bash
PKG_CONFIG_PATH=/tmp/alsa-dev/usr/lib/x86_64-linux-gnu/pkgconfig \
LIBRARY_PATH=/tmp/alsa-dev/usr/lib/x86_64-linux-gnu \
cargo build 2>&1 | grep -E "(Compiling|Finished)"

Runtime success (no ALSA errors):

bash
ALSA_PLUGIN_DIR=/tmp/alsa-plugins/usr/lib/x86_64-linux-gnu/alsa-lib \
./target/debug/your-app 2>&1 | grep -i alsa
# Should show NO output (no errors)

Audio test:

  • You should hear audio through your Windows speakers/headphones
  • WSLg routes the audio: App → ALSA → PulseAudio plugin → WSLg → Windows

Notes

  • The runtime ALSA library (libasound.so.2) IS installed on most WSL2 distros
  • Only the dev headers/symlink and plugins are missing
  • PulseAudio socket exists at /mnt/wslg/runtime-dir/pulse/native
  • The ~/.asoundrc file persists across sessions
  • ALSA_PLUGIN_DIR must be set each time you run the app (or add to shell profile)
  • Consider adding to ~/.bashrc: export ALSA_PLUGIN_DIR=/tmp/alsa-plugins/usr/lib/x86_64-linux-gnu/alsa-lib

Troubleshooting

Still getting ALSA errors?

  1. Verify PulseAudio is running: ls /mnt/wslg/runtime-dir/pulse/
  2. Check plugin exists: ls $ALSA_PLUGIN_DIR/libasound_module_pcm_pulse.so
  3. Verify .asoundrc: cat ~/.asoundrc

No sound but no errors?

  1. Check Windows volume mixer
  2. Verify WSLg audio: paplay /usr/share/sounds/alsa/Front_Center.wav (if installed)

References