---
title: 媒体操作手册
url: https://doc.liz6.com/devops/media-ops
locale: zh
area: devops
tags:
- devops
date: 2026-06-30
modified: 2026-07-11
description: 媒体操作手册 音频/视频相关操作，包括 PipeWire 管理、音量控制、设备路由、录制和故障排查。 架构概览 PipeWire 架构:数据流走应用到硬件,WirePlumber/pipewire-pulse 是管理层 应用 PipeWire (media.session) ALSA 驱动 硬件 WirePlumber…
---

# 媒体操作手册

音频/视频相关操作，包括 PipeWire 管理、音量控制、设备路由、录制和故障排查。

## 架构概览

<svg viewBox="0 0 720 340" xmlns="http://www.w3.org/2000/svg" font-family="-apple-system,'Source Han Sans CN','Microsoft YaHei',sans-serif" role="img" aria-label="PipeWire 音频架构:应用到硬件的数据流,以及 WirePlumber 会话策略层与 pipewire-pulse 兼容层的位置">
  <defs><marker id="mopah" markerWidth="10" markerHeight="8" refX="8" refY="3" orient="auto"><path d="M0,0 L8,3 L0,6 Z" fill="#475569"/></marker></defs>
  <rect width="720" height="340" fill="#ffffff"/>
  <text x="360" y="28" text-anchor="middle" font-size="17" font-weight="700" fill="#1f2933">PipeWire 架构:数据流走应用到硬件,WirePlumber/pipewire-pulse 是管理层</text>
  <rect x="123" y="55" width="70" height="34" rx="6" fill="#e2e8f0"/>
  <text x="158" y="76" text-anchor="middle" font-size="12" font-weight="700" fill="#334155">应用</text>
  <line x1="193" y1="72" x2="209" y2="72" stroke="#475569" stroke-width="1.6" marker-end="url(#mopah)"/>
  <rect x="211" y="55" width="170" height="34" rx="6" fill="#4f46e5"/>
  <text x="296" y="76" text-anchor="middle" font-size="11" font-weight="700" fill="#ffffff">PipeWire (media.session)</text>
  <line x1="381" y1="72" x2="397" y2="72" stroke="#475569" stroke-width="1.6" marker-end="url(#mopah)"/>
  <rect x="399" y="55" width="110" height="34" rx="6" fill="#e2e8f0"/>
  <text x="454" y="76" text-anchor="middle" font-size="12" font-weight="700" fill="#334155">ALSA 驱动</text>
  <line x1="509" y1="72" x2="525" y2="72" stroke="#475569" stroke-width="1.6" marker-end="url(#mopah)"/>
  <rect x="527" y="55" width="70" height="34" rx="6" fill="#e2e8f0"/>
  <text x="562" y="76" text-anchor="middle" font-size="12" font-weight="700" fill="#334155">硬件</text>
  <line x1="296" y1="89" x2="296" y2="121" stroke="#475569" stroke-width="1.6" marker-end="url(#mopah)"/>
  <rect x="96" y="123" width="400" height="48" rx="8" fill="#f0fdfa" stroke="#99f6e4"/>
  <text x="296" y="143" text-anchor="middle" font-size="13" font-weight="700" fill="#115e59">WirePlumber</text>
  <text x="296" y="161" text-anchor="middle" font-size="11" fill="#0f766e">会话策略管理器, 替代 pipewire-media-session</text>
  <line x1="296" y1="171" x2="296" y2="203" stroke="#475569" stroke-width="1.6" marker-end="url(#mopah)"/>
  <rect x="96" y="205" width="400" height="48" rx="8" fill="#ffedd5"/>
  <text x="296" y="225" text-anchor="middle" font-size="13" font-weight="700" fill="#9a3412">pipewire-pulse</text>
  <text x="296" y="243" text-anchor="middle" font-size="11" fill="#c2410c">PulseAudio 兼容层, 给传统应用</text>
  <rect x="40" y="273" width="640" height="48" rx="8" fill="#eef2ff" stroke="#c7d2fe"/>
  <text x="360" y="293" text-anchor="middle" font-size="12.5" fill="#3730a3">音视频数据走上排(应用→PipeWire→ALSA→硬件);WirePlumber 管路由策略,pipewire-pulse 是兼容层。</text>
  <text x="360" y="311" text-anchor="middle" font-size="12.5" fill="#3730a3">pactl 操作 pipewire-pulse,wpctl 操作 PipeWire 原生层——排障先分清走的哪一层。</text>
</svg>

关键概念:
- **PipeWire** = 统一的音视频服务, 同时替代 PulseAudio 和 JACK
- **WirePlumber** = 设备热插拔/自动路由策略 (谁插了耳机、切了 HDMI 输出)
- **pipewire-pulse** = PulseAudio 兼容层, 让 PA 应用透明使用 PipeWire
- **pactl** 操作的是 pipewire-pulse, **wpctl** 操作的是 PipeWire 原生层

## 状态查看

```bash
# 服务状态
systemctl --user status pipewire wireplumber pipewire-pulse

# PipeWire 原生信息
pw-cli info                          # PipeWire 服务概要
pw-dump                              # 完整 dump (节点/端口/链接)
pw-top                               # 实时性能监控 (类似 htop)
pw-cli list-objects                  # 列出所有对象

# WirePlumber 设备
wpctl status                         # 设备总览 (sinks/sources/默认设备)
wpctl inspect <id>                   # 查看某设备/节点详情

# PulseAudio 兼容层
pactl info                           # PulseAudio 服务信息
pactl list sinks                     # 列出所有音频输出
pactl list sources                   # 列出所有音频输入 (含 monitor)
pactl list cards                     # 声卡信息 (profile/ports)
pactl list sink-inputs               # 正在播放的音频流
pactl list modules                   # 已加载模块

# 硬件
aplay -l                             # ALSA 播放设备列表
arecord -l                           # ALSA 录音设备列表
lspci | grep -i audio                # PCI 音频设备
cat /proc/asound/cards               # 内核视角的声卡
```

## 音量控制

```bash
# wpctl (推荐, PipeWire 原生)
wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+      # 默认输出 +5%
wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-      # 默认输出 -5%
wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.5      # 设为 50%
wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle     # 切换静音
wpctl set-volume <sink-id> 0.75                # 指定 sink 设 75%

# pactl (PulseAudio 兼容层)
pactl set-sink-volume @DEFAULT_SINK@ +5%
pactl set-sink-volume @DEFAULT_SINK@ 50%
pactl set-sink-mute @DEFAULT_SINK@ toggle

# amixer (ALSA 底层, 直接调硬件)
amixer scontrols                      # 列出简单混音器控件
amixer sget Master                    # 查看 Master 音量
amixer sset Master 80%                # 设 Master 为 80%
amixer sset Master 5%+                # Master +5%
amixer sset Master toggle             # 切换静音
amixer sset Headphone 70%
```

## 音频路由 (切换输出设备)

```bash
# 列出可用 sinks 并切换
wpctl status                          # 记下目标 sink 的 ID
wpctl set-default <sink-id>           # 设为默认输出
wpctl inspect <sink-id>               # 确认切换生效

# 迁移当前播放流到指定 sink
pactl list sink-inputs                # 记下 sink-input ID
pactl move-sink-input <input-id> <sink-id>

# 切换到特定设备 (按名称)
SINK=$(pactl list sinks short | grep -i "hdmi\|analog\|usb" | head -1 | awk '{print $1}')
pactl set-default-sink "$SINK"

# 查看声卡 profile (模拟/数字/HDMI 切换)
pactl list cards
pactl set-card-profile <card-name> output:analog-stereo
pactl set-card-profile <card-name> output:hdmi-stereo
pactl set-card-profile <card-name> output:iec958-stereo  # SPDIF
```

## WirePlumber / PipeWire 重启

```bash
# 重启整个音频栈 (软重启, 应用不自知)
systemctl --user restart pipewire pipewire-pulse wireplumber

# 单独重启 WirePlumber (设备列表刷新)
systemctl --user restart wireplumber

# 完全重置 (先 kill 再起)
systemctl --user stop pipewire pipewire-pulse wireplumber
sleep 1
systemctl --user start pipewire wireplumber pipewire-pulse
```

## 故障排查

```bash
# 1. 检查是否有声音输出
paplay /usr/share/sounds/alsa/Front_Center.wav    # 测试音
speaker-test -t sine -f 440 -l 1                   # 440Hz 正弦波 (绕过 PA/PW)

# 2. 检查 pipewire-pulse 是否僵死 (常见: Chrome 视频卡死)
pactl info 2>&1                                    # 看是否报错/超时
paplay /usr/share/sounds/alsa/Front_Center.wav     # 如果 124 退出, pipewire-pulse 已僵
# 修复: systemctl --user restart pipewire-pulse

# 3. 检查是否有进程独占声卡
fuser /dev/snd/*                                   # 谁占用了音频设备
lsof /dev/snd/*                                    # 更详细

# 4. 检查 ALSA 层是否正常
aplay -D hw:0,0 /usr/share/sounds/alsa/Front_Center.wav  # 绕过 PipeWire 直接播放
speaker-test -D hw:0,0 -t sine -f 440 -l 1
# 如果 ALSA 直接播正常但 PipeWire 没声 → PipeWire 层问题
# 如果 ALSA 也报错 → 驱动/硬件问题

# 5. USB/HDMI 热插拔没反应
wpctl status                          # 看设备是否出现
systemctl --user restart wireplumber  # 强制刷新设备列表
journalctl --user -u wireplumber -f   # 看 WirePlumber 日志

# 6. 蓝牙音频
bluetoothctl connect XX:XX:XX:XX:XX:XX
# 连上后 wireplumber 自动创建 BT sink, wpctl status 可见
# 没出现: systemctl --user restart wireplumber

# 7. 同时多输出 (如有需要)
pactl load-module module-combine-sink   # 创建合并 sink, 同时输出到所有设备
# 卸载: pactl unload-module module-combine-sink
```

### 常见症状速查

| 症状 | 可能原因 | 命令 |
|------|---------|------|
| Chrome 视频进度条不走, 有缓冲 | pipewire-pulse 僵死 | `systemctl --user restart pipewire-pulse` |
| 完全没声 | 默认 sink 错了 | `wpctl status` 看 default sink |
| 插耳机不自动切 | WirePlumber 没反应过来 | `systemctl --user restart wireplumber` |
| 某些应用出声某些不出 | 走了不同 sink | `pactl list sink-inputs` 看路由 |
| 蓝牙耳机连上没声 | BT profile 掉了 | `pactl list cards` 看 profile |

## 录制

```bash
# 屏幕录制 (PipeWire + wf-recorder, Wayland 原生)
wf-recorder -f output.mp4                    # 录全屏
wf-recorder -g "$(slurp)" -f output.mp4      # 选区录制
wf-recorder --audio -f output.mp4            # 带音频 (需要 pipewire)
wf-recorder --audio=HDMI -f output.mp4       # 指定音频源

# 音频录制 (PipeWire)
pw-record output.wav                          # 默认输入设备录制
pw-record --target=<node-id> output.wav       # 指定输入源

# PulseAudio 兼容
parecord output.wav                           # 默认 mic 录音
parecord --device=<source> output.wav         # 指定输入源
parec --device=<sink>.monitor output.wav      # 录制系统输出 (内录)

# 截图 (Wayland/Hyprland)
grim screenshot.png                           # 全屏截图
grim -g "$(slurp)" screenshot.png             # 选区截图
grim - | wl-copy                              # 截图到剪贴板
```

## 音量/媒体键

Hyprland 媒体键绑定示例 (`hyprland.lua`):

```lua
-- 音量控制 (wpctl)
hl.dsp.bind({"SUPER"}, "XF86AudioRaiseVolume",  function() hl.exec("wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+") end)
hl.dsp.bind({"SUPER"}, "XF86AudioLowerVolume",  function() hl.exec("wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-") end)
hl.dsp.bind({"SUPER"}, "XF86AudioMute",         function() hl.exec("wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle") end)
hl.dsp.bind({"SUPER"}, "XF86AudioMicMute",      function() hl.exec("wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle") end)

-- 播放控制 (playerctl, 需要安装)
hl.dsp.bind({}, "XF86AudioPlay",  function() hl.exec("playerctl play-pause") end)
hl.dsp.bind({}, "XF86AudioNext",  function() hl.exec("playerctl next") end)
hl.dsp.bind({}, "XF86AudioPrev",  function() hl.exec("playerctl previous") end)
```

`playerctl` 其他用法:
```bash
playerctl play-pause                  # 控制当前播放器
playerctl -p spotify next             # 指定播放器
playerctl -a play-pause               # 所有播放器
playerctl -l                          # 列出可控制的播放器
playerctl metadata                    # 当前歌曲信息
playerctl metadata --format '{{artist}} - {{title}}'
```

## 视频/编解码信息

```bash
ffprobe video.mp4                     # 视频完整信息
ffprobe -v quiet -show_streams video.mp4 | grep codec  # 只看编解码
ffprobe -v quiet -show_entries stream=codec_name,width,height video.mp4

# 查看硬件编解码支持
vainfo                                # VA-API (Intel/AMD)
vulkaninfo | grep -i video            # Vulkan Video 扩展
ffmpeg -encoders | grep vaapi         # 可用 VA-API 编码器
```

## 固件

```bash
# AMD GPU 固件 (编解码/显示)
ls /lib/firmware/amdgpu/              # gc_*, psp_*, sdma_*, vcn_* 等
dmesg | grep -i "firmware\|amdgpu"    # 固件加载日志

# SOF (Sound Open Firmware, Intel 音频 DSP)
dmesg | grep -i sof
ls /lib/firmware/intel/sof/
```
