Tous les produits
Search
Centre de documentation

Alibaba Cloud Model Studio:Capture audio personnalisée

Dernière mise à jour :Sep 07, 2026

Cette rubrique explique comment mettre en œuvre une capture audio personnalisée avec le SDK client AOQ. Elle couvre l'ajout de flux audio externes, l'injection de données PCM et la gestion du cycle de vie des flux.

Présentation

Le module audio intégré du SDK client AOQ répond aux besoins fondamentaux, mais peut s'avérer insuffisant dans certains scénarios. La capture audio personnalisée est particulièrement utile pour :

  • Contourner les conflits de périphériques de capture audio.
  • Transmettre au SDK des données audio issues d'un système de capture spécifique ou d'un fichier.
  • Publier via le SDK de l'audio généré par synthèse vocale IA (TTS).

Le SDK client AOQ offre une prise en charge flexible de la capture personnalisée, permettant de gérer vos propres périphériques et sources audio selon votre cas d'usage. Les données du flux audio externe sont mixées avec l'audio capturé en interne avant publication.

Exemple de code

Bientôt disponible.

Prérequis

  • Vous avez créé une instance de moteur en appelant createEngine.
  • La connexion au serveur est établie (le callback onConnectionStatusChange a signalé l'état AoqConnectionStatusConnected).

Mise en œuvre

1. Démarrer ou arrêter la capture audio

Commencez par lancer la capture audio. Les données du flux audio externe sont mixées avec celles de la capture interne avant publication. Si la capture par le microphone interne n'est pas nécessaire, définissez isExternal=true pour désactiver le périphérique de capture interne.

// Option 1: Internal capture — external audio stream data is mixed with microphone data
AoqClientEngine.AoqAudioCaptureConfig config = new AoqClientEngine.AoqAudioCaptureConfig();
config.isExternal = false; // Use internal microphone capture
config.isVoipMode = false;
engine.startAudioCapture(config);

// Option 2: No internal capture — only external audio stream data is published
AoqClientEngine.AoqAudioCaptureConfig config = new AoqClientEngine.AoqAudioCaptureConfig();
config.isExternal = true; // Do not open the microphone; external audio stream provides the data
engine.startAudioCapture(config);

2. Ajouter le flux audio externe après la connexion

Dès que le callback onConnectionStatusChange signale l'état AoqConnectionStatusConnected, appelez addAudioExternalStream pour ajouter le flux audio externe. Attribuez-lui un identifiant streamId unique pour injecter les données et gérer le flux.

Si un traitement 3A (annulation d'écho, suppression du bruit, contrôle automatique du gain) est requis, activez le paramètre enable3A dans AoqAudioExternalStreamConfig.

// Add the stream after confirming connection in the onConnectionStatusChange callback
@Override
public void onConnectionStatusChange(AoqClientEngine.AoqConnectionStatus status) {
    if (status == AoqClientEngine.AoqConnectionStatus.AoqConnectionStatusConnected) {
        addExternalAudioStream();
    }
}

private void addExternalAudioStream() {
    AoqClientEngine.AoqAudioExternalStreamConfig config = new AoqClientEngine.AoqAudioExternalStreamConfig();
    config.sampleRate = 48000;       // Sample rate — must match the actual audio data
    config.channels = 1;             // Channel count
    config.publishVolume = 100;      // Publishing volume [0-100]
    config.playoutVolume = 0;        // Local playback volume [0-100]; 0 = no local playback
    config.maxBufferDuration = 1000; // Maximum buffer duration (milliseconds)
    config.enable3A = true;          // Whether to apply 3A processing to input PCM

    String streamId = "external_audio_1";
    int ret = engine.addAudioExternalStream(streamId, config);
    if (ret == 0) {
        mExternalStreamId = streamId;
    }
}
Paramètres :

Paramètre

Type

Valeur par défaut

Description

trackType

AoqTrackType

AoqTrackTypeAudio

Type de piste audio

codecType

AoqEncoderType

AoqEncoderTypeAudioPCM

Format du flux audio

channels

int

1

Nombre de canaux

sampleRate

int

48000

Fréquence d'échantillonnage (Hz)

playoutVolume

int

100

Volume de lecture locale [0–100]

publishVolume

int

100

Volume de publication [0–100]

maxBufferDuration

int

1000

Durée maximale du tampon (millisecondes)

enable3A

boolean

false

Activation du traitement 3A sur les données PCM entrantes

3. Capturer ou obtenir des données PCM

Implémentez votre propre mécanisme de capture audio ou source de données adapté à votre cas d'usage, puis injectez ces données dans le SDK. Les sources courantes incluent :

  • Capture microphone : utilisez l'API AudioRecord d'Android pour capturer des données PCM.
  • Lecture de fichier : extrayez les données PCM depuis un fichier audio local au format PCM ou WAV.
  • Synthèse vocale IA : récupérez les données PCM produites par un moteur de synthèse vocale.
  • Flux réseau : décodez les données PCM issues d'un flux audio réseau.

Les données audio doivent être au format PCM. Notez la fréquence d'échantillonnage, le nombre de canaux et les autres paramètres pour construire l'objet AoqAudioFrameData.

4. Injecter les données audio dans le SDK via l'identifiant de flux

Appelez pushAudioExternalStreamData pour transmettre les données PCM capturées au SDK.

  • Pour une capture matérielle : utilisez des trames de 10 ms et lancez l'injection dès que des données sont disponibles.
  • Pour une entrée sur fichier : utilisez des trames de 40 ms et insérez une pause de 30 ms entre chaque injection.
  • Gérez un indicateur running pour contrôler la boucle d'injection. Interrompez cette boucle lorsque le moteur s'arrête ou que l'identifiant de flux est supprimé.
// Member variable: flag to control the push loop
private volatile boolean mPushRunning = false;

// Push a single audio frame

private void pushAudioData(byte[] audioData, int bytesRead) {

    if (engine == null || mExternalStreamId == null || bytesRead <= 0) {
        return;
    }

    int channels = 1;
    int bytesPerSample = 2; // 16-bit PCM
    int sampleRate = 48000;

    // Build the audio frame data object
    AoqClientEngine.AoqAudioFrameData frameData = new AoqClientEngine.AoqAudioFrameData();
    frameData.dataPtr = audioData;
    frameData.dataSize = bytesRead;
    frameData.numOfSamples = bytesRead / (channels * bytesPerSample);
    frameData.bytesPerSample = bytesPerSample;
    frameData.numOfChannels = channels;
    frameData.samplesPerSec = sampleRate;

    // Push data and handle buffer-full errors
    int ret;
    final int WAIT_MS = 30;

    do {
        // Check whether the running flag and stream ID are still valid
        if (!mPushRunning || mExternalStreamId == null) {
            break;
        }
        ret = engine.pushAudioExternalStreamData(mExternalStreamId, frameData);
        if (ret == 110) { // AoqErrorCodeAudioExternalBufferFull
            try {
                Thread.sleep(WAIT_MS);
            } catch (InterruptedException e) {
                break;
            }
        } else {
            break;
        }
    } while (true);
}
Remarques importantes :
  • N'injectez des données qu'après l'établissement de la connexion et l'ajout du flux audio externe.
  • Assurez-vous que la propriété numOfSamples de l'objet AoqAudioFrameData correspond à la longueur réelle des données.
  • L'appel à pushAudioExternalStreamData peut échouer si le tampon interne est plein (code d'erreur 110). Réessayez après un court délai.
  • En capture temps réel, privilégiez des trames de 10 ms et injectez les données dès qu'elles sont disponibles, tout en gérant le code d'erreur 110.
  • Pour une entrée sur fichier, optez pour des trames de 40 ms avec une injection toutes les 30 ms, en prévoyant la gestion du code d'erreur 110.
  • Avant l'arrêt du moteur (destroy) ou la suppression d'un identifiant de flux, passez mPushRunning = false afin d'interrompre la boucle d'injection et d'éviter tout accès à des ressources déjà libérées.

5. Supprimer le flux audio externe

Lorsque la capture personnalisée n'est plus nécessaire, arrêtez d'abord la boucle d'injection, puis appelez removeAudioExternalStream pour supprimer le flux audio externe.

// Stop pushing first
stopPushAudio();
// Then remove the external audio stream
engine.removeAudioExternalStream(mExternalStreamId);
mExternalStreamId = null;