Files
One-KVM/docs/modules/audio.md
mofeng-git a8a3b6c66b feat: 添加 RustDesk 协议支持和项目文档
- 新增 RustDesk 模块,支持与 RustDesk 客户端连接
  - 实现会合服务器协议和 P2P 连接
  - 支持 NaCl 加密和密钥交换
  - 添加视频帧和 HID 事件适配器
- 添加 Protobuf 协议定义 (message.proto, rendezvous.proto)
- 新增完整项目文档
  - 各功能模块文档 (video, hid, msd, otg, webrtc 等)
  - hwcodec 和 RustDesk 协议技术报告
  - 系统架构和技术栈文档
- 更新 Web 前端 RustDesk 配置界面和 API
2025-12-31 18:59:52 +08:00

9.5 KiB

Audio 模块文档

1. 模块概述

Audio 模块负责音频采集和编码,支持 ALSA 采集和 Opus 编码。

1.1 主要功能

  • ALSA 音频采集
  • Opus 编码
  • 多质量配置
  • WebSocket/WebRTC 传输

1.2 文件结构

src/audio/
├── mod.rs              # 模块导出
├── controller.rs       # AudioController (15KB)
├── capture.rs          # ALSA 采集 (12KB)
├── encoder.rs          # Opus 编码 (8KB)
├── shared_pipeline.rs  # 共享管道 (15KB)
├── monitor.rs          # 健康监视 (11KB)
└── device.rs           # 设备枚举 (8KB)

2. 架构设计

┌─────────────────────────────────────────────────────────────────────────────┐
│                         Audio Architecture                                   │
└─────────────────────────────────────────────────────────────────────────────┘

ALSA Device (hw:0,0)
        │
        │ PCM 48kHz/16bit/Stereo
        ▼
┌─────────────────┐
│ AudioCapturer   │
│  (capture.rs)   │
└────────┬────────┘
         │
         ▼
┌─────────────────────────────────────────┐
│         SharedAudioPipeline             │
│  ┌─────────────────────────────────┐   │
│  │      Opus Encoder               │   │
│  │   48kHz → 24-96 kbps            │   │
│  └─────────────────────────────────┘   │
└────────────────┬────────────────────────┘
                 │
       ┌─────────┴─────────┐
       │                   │
       ▼                   ▼
┌─────────────┐    ┌─────────────┐
│  WebSocket  │    │   WebRTC    │
│   Stream    │    │ Audio Track │
└─────────────┘    └─────────────┘

3. 核心组件

3.1 AudioController (controller.rs)

pub struct AudioController {
    /// 采集器
    capturer: Arc<RwLock<Option<AudioCapturer>>>,

    /// 共享管道
    pipeline: Arc<SharedAudioPipeline>,

    /// 配置
    config: Arc<RwLock<AudioConfig>>,

    /// 状态
    state: Arc<RwLock<AudioState>>,

    /// 事件总线
    events: Arc<EventBus>,
}

impl AudioController {
    /// 创建控制器
    pub fn new(config: &AudioConfig, events: Arc<EventBus>) -> Result<Self>;

    /// 启动音频
    pub async fn start(&self) -> Result<()>;

    /// 停止音频
    pub async fn stop(&self) -> Result<()>;

    /// 订阅音频帧
    pub fn subscribe(&self) -> broadcast::Receiver<AudioFrame>;

    /// 获取状态
    pub fn status(&self) -> AudioStatus;

    /// 设置质量
    pub fn set_quality(&self, quality: AudioQuality) -> Result<()>;

    /// 列出设备
    pub fn list_devices(&self) -> Vec<AudioDeviceInfo>;

    /// 重新加载配置
    pub async fn reload(&self, config: &AudioConfig) -> Result<()>;
}

pub struct AudioStatus {
    pub enabled: bool,
    pub streaming: bool,
    pub device: Option<String>,
    pub sample_rate: u32,
    pub channels: u16,
    pub bitrate: u32,
    pub error: Option<String>,
}

3.2 AudioCapturer (capture.rs)

pub struct AudioCapturer {
    /// PCM 句柄
    pcm: PCM,

    /// 设备名
    device: String,

    /// 采样率
    sample_rate: u32,

    /// 通道数
    channels: u16,

    /// 帧大小
    frame_size: usize,

    /// 运行状态
    running: AtomicBool,
}

impl AudioCapturer {
    /// 打开设备
    pub fn open(device: &str, config: &CaptureConfig) -> Result<Self>;

    /// 读取音频帧
    pub fn read_frame(&self) -> Result<Vec<i16>>;

    /// 启动采集
    pub fn start(&self) -> Result<()>;

    /// 停止采集
    pub fn stop(&self);

    /// 是否运行中
    pub fn is_running(&self) -> bool;
}

pub struct CaptureConfig {
    pub sample_rate: u32,   // 48000
    pub channels: u16,      // 2
    pub frame_size: usize,  // 960 (20ms)
    pub buffer_size: usize, // 4800
}

3.3 OpusEncoder (encoder.rs)

pub struct OpusEncoder {
    /// Opus 编码器
    encoder: audiopus::Encoder,

    /// 采样率
    sample_rate: u32,

    /// 通道数
    channels: u16,

    /// 帧大小
    frame_size: usize,

    /// 码率
    bitrate: u32,
}

impl OpusEncoder {
    /// 创建编码器
    pub fn new(quality: AudioQuality) -> Result<Self>;

    /// 编码 PCM 数据
    pub fn encode(&mut self, pcm: &[i16]) -> Result<Vec<u8>>;

    /// 设置码率
    pub fn set_bitrate(&mut self, bitrate: u32) -> Result<()>;

    /// 获取码率
    pub fn bitrate(&self) -> u32;

    /// 重置编码器
    pub fn reset(&mut self) -> Result<()>;
}

3.4 SharedAudioPipeline (shared_pipeline.rs)

pub struct SharedAudioPipeline {
    /// 采集器
    capturer: Arc<RwLock<Option<AudioCapturer>>>,

    /// 编码器
    encoder: Arc<Mutex<OpusEncoder>>,

    /// 广播通道
    tx: broadcast::Sender<AudioFrame>,

    /// 采集任务
    capture_task: Arc<RwLock<Option<JoinHandle<()>>>>,

    /// 配置
    config: Arc<RwLock<AudioConfig>>,
}

impl SharedAudioPipeline {
    /// 创建管道
    pub fn new(config: &AudioConfig) -> Result<Self>;

    /// 启动管道
    pub async fn start(&self) -> Result<()>;

    /// 停止管道
    pub async fn stop(&self) -> Result<()>;

    /// 订阅音频帧
    pub fn subscribe(&self) -> broadcast::Receiver<AudioFrame>;

    /// 获取统计
    pub fn stats(&self) -> PipelineStats;
}

pub struct AudioFrame {
    /// Opus 数据
    pub data: Bytes,

    /// 时间戳
    pub timestamp: u64,

    /// 帧序号
    pub sequence: u64,
}

4. 音频质量

pub enum AudioQuality {
    /// 24 kbps - 最低带宽
    VeryLow,

    /// 48 kbps - 低带宽
    Low,

    /// 64 kbps - 中等
    Medium,

    /// 96 kbps - 高质量
    High,
}

impl AudioQuality {
    pub fn bitrate(&self) -> u32 {
        match self {
            Self::VeryLow => 24000,
            Self::Low => 48000,
            Self::Medium => 64000,
            Self::High => 96000,
        }
    }
}

5. 配置

#[derive(Serialize, Deserialize)]
#[typeshare]
pub struct AudioConfig {
    /// 是否启用
    pub enabled: bool,

    /// 设备名
    pub device: Option<String>,

    /// 音频质量
    pub quality: AudioQuality,

    /// 自动启动
    pub auto_start: bool,
}

impl Default for AudioConfig {
    fn default() -> Self {
        Self {
            enabled: true,
            device: None,  // 使用默认设备
            quality: AudioQuality::Medium,
            auto_start: false,
        }
    }
}

6. API 端点

端点 方法 描述
/api/audio/status GET 获取音频状态
/api/audio/start POST 启动音频
/api/audio/stop POST 停止音频
/api/audio/devices GET 列出设备
/api/audio/quality GET 获取质量
/api/audio/quality POST 设置质量
/api/ws/audio WS 音频流

响应格式

// GET /api/audio/status
{
    "enabled": true,
    "streaming": true,
    "device": "hw:0,0",
    "sample_rate": 48000,
    "channels": 2,
    "bitrate": 64000,
    "error": null
}

// GET /api/audio/devices
{
    "devices": [
        {
            "name": "hw:0,0",
            "description": "USB Audio Device",
            "is_default": true
        }
    ]
}

7. WebSocket 音频流

// 连接 WebSocket
const ws = new WebSocket('/api/ws/audio');
ws.binaryType = 'arraybuffer';

// 初始化 Opus 解码器
const decoder = new OpusDecoder();

// 接收音频帧
ws.onmessage = (event) => {
    const frame = new Uint8Array(event.data);
    const pcm = decoder.decode(frame);
    audioContext.play(pcm);
};

8. 事件

pub enum SystemEvent {
    AudioStateChanged {
        enabled: bool,
        streaming: bool,
        device: Option<String>,
        error: Option<String>,
    },
}

9. 错误处理

#[derive(Debug, thiserror::Error)]
pub enum AudioError {
    #[error("Device not found: {0}")]
    DeviceNotFound(String),

    #[error("Device busy: {0}")]
    DeviceBusy(String),

    #[error("ALSA error: {0}")]
    AlsaError(String),

    #[error("Encoder error: {0}")]
    EncoderError(String),

    #[error("Not streaming")]
    NotStreaming,
}

10. 使用示例

let controller = AudioController::new(&config, events)?;

// 启动音频
controller.start().await?;

// 订阅音频帧
let mut rx = controller.subscribe();
while let Ok(frame) = rx.recv().await {
    // 处理 Opus 数据
    send_to_client(frame.data);
}

// 停止
controller.stop().await?;

11. 常见问题

Q: 找不到音频设备?

  1. 检查 ALSA 配置
  2. 运行 arecord -l
  3. 检查权限

Q: 音频延迟高?

  1. 减小帧大小
  2. 降低质量
  3. 检查网络

Q: 音频断断续续?

  1. 增大缓冲区
  2. 检查 CPU 负载
  3. 使用更低质量