Pipeline audio de bureau
La crate adk-audio fournit des entrĂ©es/sorties audio de bureau multiplateformes derriĂšre lâindicateur de fonctionnalitĂ© desktop-audio. Trois composants â AudioCapture, AudioPlayback et VadTurnManager â permettent la capture au microphone, la lecture par les haut-parleurs et la gestion des tours de parole pilotĂ©e par la VAD pour crĂ©er des agents vocaux de bureau.
Vue dâensemble
Le pipeline audio de bureau connecte le matériel audio du systÚme au systÚme de pipelines adk-audio existant :
Microphone â AudioCapture â AudioStream â [VAD â STT â Agent â TTS] â AudioPlayback â Speaker
Tous les composants utilisent la crate cpal pour lâaudio multiplateforme (CoreAudio sur macOS, PipeWire/ALSA/PulseAudio sur Linux, WASAPI sur Windows) et produisent ou consomment le type AudioFrame standard.
Indicateurs de fonctionnalité
[dependencies]
# Cross-platform (macOS, Linux, Windows) via cpal
adk-audio = { version = "2.1.0", features = ["desktop-audio"] }
La fonctionnalitĂ© desktop-audio implique vad (pour VadProcessor) et ajoute cpal comme dĂ©pendance. Elle est intentionnellement exclue de la fonctionnalitĂ© all afin dâĂ©viter dâintroduire des dĂ©pendances audio spĂ©cifiques aux plateformes dans les compilations CI.
Prise en charge de PipeWire
Sur les distributions Linux modernes (Fedora 34+, Ubuntu 22.10+, Arch), PipeWire a remplacĂ© PulseAudio et ALSA comme serveur audio par dĂ©faut. La fonctionnalitĂ© desktop-audio fonctionne de maniĂšre transparente avec PipeWire grĂące Ă sa couche de compatibilitĂ© ALSA â aucune configuration supplĂ©mentaire nâest nĂ©cessaire.
Un backend PipeWire natif (desktop-pipewire) utilisant la crate pipewire (v0.9) est prĂ©vu dans une prochaine version. PipeWire natif offrirait une latence plus faible et une gestion directe des sessions. Son intĂ©gration est actuellement bloquĂ©e par un conflit de dĂ©pendances : redis-protocol 6.0.0 verrouille cookie-factory =0.3.2 tandis que le libspa de pipewire nĂ©cessite 0.3.3. Une fois que le projet amont assouplira ce verrouillage, le backend natif pourra ĂȘtre ajoutĂ©.
Démarrage rapide
Répertorier les périphériques audio
use adk_audio::{AudioCapture, AudioPlayback};
let inputs = AudioCapture::list_input_devices()?;
for device in &inputs {
println!("Mic: {} ({})", device.name(), device.id());
}
let outputs = AudioPlayback::list_output_devices()?;
for device in &outputs {
println!("Speaker: {} ({})", device.name(), device.id());
}
Capturer le son du microphone
use adk_audio::{AudioCapture, CaptureConfig};
use std::time::{Duration, Instant};
let mut capture = AudioCapture::new();
let devices = AudioCapture::list_input_devices()?;
let device = devices.first().expect("no input device");
let config = CaptureConfig::default(); // 16kHz, mono, 20ms frames
let mut stream = capture.start_capture(device.id(), &config)?;
let start = Instant::now();
while start.elapsed() < Duration::from_secs(3) {
if let Some(frame) = stream.recv().await {
// frame.data: PCM-16 LE bytes
// frame.sample_rate: 16000
// frame.channels: 1
// frame.duration_ms: 20
}
}
capture.stop_capture();
Lire du son sur les haut-parleurs
use adk_audio::{AudioFrame, AudioPlayback};
let mut playback = AudioPlayback::new();
let devices = AudioPlayback::list_output_devices()?;
let device = devices.first().expect("no output device");
let frame = AudioFrame::silence(16000, 1, 1000); // 1 second
playback.play(device.id(), &frame).await?;
playback.stop();
Gestion des tours de parole par VAD
use std::sync::Arc;
use adk_audio::{
AudioCapture, CaptureConfig, VadConfig, VadMode,
VadTurnManager, VoiceActivityEvent, VadProcessor,
};
let vad: Arc<dyn VadProcessor> = /* your VadProcessor impl */;
let config = VadConfig {
mode: VadMode::HandsFree,
silence_threshold_ms: 500,
speech_threshold_ms: 200,
};
let mut manager = VadTurnManager::new(vad, config)?;
let mut capture = AudioCapture::new();
let stream = capture.start_capture(device_id, &CaptureConfig::default())?;
manager.start(stream, |event| {
match event {
VoiceActivityEvent::SpeechStarted => println!("Speech started"),
VoiceActivityEvent::SpeechEnded { duration_ms } => {
println!("Speech ended ({duration_ms}ms)");
}
}
});
Composants
AudioDevice
Descripteur dâun pĂ©riphĂ©rique audio systĂšme (entrĂ©e ou sortie). Contient un id opaque et un name lisible par lâutilisateur.
CaptureConfig
Configuration de la capture par microphone :
| Champ | Type | Valeur par défaut | Description |
|---|---|---|---|
sample_rate | u32 | 16000 | FrĂ©quence dâĂ©chantillonnage en Hz |
channels | u8 | 1 | Nombre de canaux (1=mono, 2=stéréo) |
frame_duration_ms | u32 | 20 | Durée de chaque AudioFrame |
Appelez validate() avant utilisation â rejette les valeurs nulles avec AudioError::Device.
AudioCapture
Capture du microphone via cpal. La méthode start_capture() renvoie un AudioStream (mpsc::Receiver<AudioFrame> borné avec une capacité de 64). Les trames sont produites à des intervalles de frame_duration_ms au format PCM-16 LE.
AudioPlayback
Lecture sur haut-parleur via cpal. La méthode play() met en file les échantillons d'un AudioFrame dans une mémoire tampon partagée que le callback de sortie cpal vide. Appelez stop() pour libérer le périphérique.
VadTurnManager
Consomme un AudioStream, applique VadProcessor::is_speech() à chaque trame et émet des valeurs VoiceActivityEvent via un callback enregistré.
Deux modes :
- HandsFree â dĂ©tection automatique des limites de la parole Ă l'aide de seuils configurables de durĂ©e du silence et de la parole
- PushToTalk â aucun Ă©vĂ©nement automatique ; l'appelant contrĂŽle le dĂ©clenchement en externe
VadConfig
| Champ | Type | Description |
|---|---|---|
mode | VadMode | HandsFree or PushToTalk |
silence_threshold_ms | u32 | Silence consécutif avant SpeechEnded |
speech_threshold_ms | u32 | Discours consécutif avant SpeechStarted |
Appelez validate() avant utilisation â rejette les seuils nuls avec AudioError::Vad.
CrĂ©ation dâun agent vocal
Le modĂšle complet dâun agent vocal conversationnel :
- Capturer lâaudio depuis le microphone
- Détecter les limites de la parole avec VAD
- Transcrire la parole avec GeminiStt (ou tout autre
SttProvider) - Envoyer la transcription Ă un LlmAgent pour le raisonnement
- Synthétiser la réponse avec GeminiTts (ou tout autre
TtsProvider) - Lire lâaudio synthĂ©tisĂ© via le haut-parleur
Consultez examples/desktop_audio/src/voice_agent.rs pour un exemple complet fonctionnel utilisant de véritables fournisseurs cloud Gemini.
Sécurité des threads
Tous les types audio de bureau (AudioCapture, AudioPlayback, VadTurnManager) sont Send + Sync, ce qui permet de les partager en toute sécurité entre les tùches Tokio.
Gestion des erreurs
Les erreurs audio de bureau utilisent lâĂ©numĂ©ration AudioError existante :
| Composant | Variante dâerreur | Quand |
|---|---|---|
| AudioCapture | AudioError::Device | Périphérique introuvable, hÎte indisponible, validation de la configuration |
| AudioPlayback | AudioError::Device | PĂ©riphĂ©rique introuvable, hĂŽte indisponible, Ă©chec de lâouverture/de lâĂ©criture |
| VadTurnManager | AudioError::Vad | Validation de la configuration (seuils à zéro) |
Prise en charge de la plateforme
| Plateforme | Backend audio | Statut |
|---|---|---|
| macOS | CoreAudio | Pris en charge |
| Linux | PipeWire (via la compatibilité ALSA) | Pris en charge (installer libasound2-dev) |
| Linux | ALSA / PulseAudio (legacy) | Pris en charge (installer libasound2-dev) |
| Windows | WASAPI | Pris en charge |
Sur Linux moderne, PipeWire est le serveur audio par défaut et a remplacé PulseAudio et ALSA. La fonctionnalité desktop-audio fonctionne de maniÚre transparente sur PipeWire grùce à sa couche de compatibilité ALSA. Un backend natif PipeWire utilisant le crate pipewire est prévu pour une prochaine version (actuellement bloqué par un conflit de dépendances en amont dans redis-protocol).
Exemples
Consultez examples/desktop_audio/ pour découvrir 6 exemples pratiques, dont un agent vocal conversationnel complet avec STT/TTS Gemini réels.