Todos os produtos
Search
Central de documentação

Alibaba Cloud Model Studio:Captura de áudio personalizada

Última atualização: Sep 02, 2026

Descreve como implementar a captura de áudio personalizada com o AOQ Client SDK, incluindo a adição de fluxos de áudio externos, o envio de dados PCM e o gerenciamento do ciclo de vida do fluxo.

Visão geral

O módulo de áudio integrado do AOQ Client SDK atende às necessidades básicas, mas em alguns cenários o módulo de captura padrão pode não ser suficiente. A captura de áudio personalizada é útil quando você precisa:

  • Contornar conflitos de dispositivos de captura de áudio.
  • Inserir dados de áudio de um sistema de captura personalizado ou de um arquivo de áudio no SDK para transmissão.
  • Publicar áudio gerado por TTS de IA por meio do SDK.

O AOQ Client SDK oferece suporte flexível à captura personalizada, permitindo que você gerencie seus próprios dispositivos e fontes de áudio conforme o caso de uso. Os dados do fluxo de áudio externo são mixados com o áudio capturado internamente antes da publicação.

Código de exemplo

Em breve.

Pré-requisitos

  • Uma instância de engine foi criada chamando createEngine.
  • Uma conexão com o servidor foi estabelecida (o callback onConnectionStatusChange reportou AoqConnectionStatusConnected).

Implementação

1. Iniciar ou parar a captura de áudio

Inicie primeiro a captura de áudio. Os dados do fluxo de áudio externo são mixados com os dados de captura interna antes da publicação. Se não for necessária a captura interna pelo microfone, defina isExternal=true para desativar o dispositivo de captura interno.

// 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. Após conectar, adicione o fluxo de áudio externo

Assim que o callback onConnectionStatusChange reportar AoqConnectionStatusConnected, chame addAudioExternalStream para adicionar o fluxo de áudio externo. Atribua um streamId exclusivo, que será usado para enviar dados e gerenciar o fluxo.

Caso seja necessário processamento 3A (cancelamento de eco, supressão de ruído e controle automático de ganho), configure o parâmetro enable3A em 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;
    }
}
Parâmetros:

Parâmetro

Tipo

Padrão

Descrição

trackType

AoqTrackType

AoqTrackTypeAudio

Tipo de faixa de áudio

codecType

AoqEncoderType

AoqEncoderTypeAudioPCM

Formato do fluxo de áudio

channels

int

1

Número de canais

sampleRate

int

48000

Taxa de amostragem (Hz)

playoutVolume

int

100

Volume de reprodução [0–100]

publishVolume

int

100

Volume de publicação [0–100]

maxBufferDuration

int

1000

Duração máxima do buffer (milissegundos)

enable3A

boolean

false

Indica se deve aplicar processamento 3A ao PCM de entrada

3. Capturar ou obter dados PCM

Implemente sua própria captura de áudio ou source adequada ao seu caso de uso e insira os dados no SDK. As fontes de dados mais comuns incluem:

  • Captura por microfone: Utilize o AudioRecord do Android para capturar dados PCM.
  • Leitura de arquivo: Extraia dados PCM de um arquivo de áudio local nos formatos PCM ou WAV.
  • TTS de IA: Obtenha dados PCM de um mecanismo de síntese de fala.
  • Fluxo de rede: Decodifique dados PCM a partir de um fluxo de áudio em rede.

Os dados de áudio devem estar no formato PCM. Registre a taxa de amostragem, o número de canais e outros parâmetros para construir o objeto AoqAudioFrameData.

4. Enviar dados de áudio para o SDK via stream ID

Chame pushAudioExternalStreamData para inserir os dados PCM capturados no SDK.

  • Para captura por hardware: utilize quadros de 10 ms e envie sempre que houver dados disponíveis.
  • Para entrada baseada em arquivo: utilize quadros de 40 ms e aguarde 30 ms entre os envios.
  • Mantenha uma flag running. Saia do loop de envio quando a engine for encerrada ou o stream ID for removido.
// 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);
}
Observações importantes:
  • Comece a enviar dados somente após estabelecer a conexão e adicionar o fluxo de áudio externo.
  • Configure numOfSamples de AoqAudioFrameData para corresponder ao tamanho real dos dados.
  • A chamada a pushAudioExternalStreamData pode falhar se o buffer interno estiver cheio (código de erro 110). Tente novamente após um curto intervalo.
  • Em capturas em tempo real, use quadros de 10 ms e envie sempre que houver dados disponíveis. Trate o código de erro 110 adequadamente.
  • Para entrada baseada em arquivo, utilize quadros de 40 ms e envie a cada 30 ms. Trate o código de erro 110 adequadamente.
  • Antes de encerrar a engine (destroy) ou remover um stream ID, defina mPushRunning = false para interromper o loop de envio e evitar acesso a recursos já liberados.

5. Remover o fluxo de áudio externo

Quando a captura personalizada não for mais necessária, pare primeiro o loop de envio e depois chame removeAudioExternalStream para remover o fluxo de áudio externo.

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