全部产品
Search
文档中心

ApsaraVideo Live:Pengambilan audio kustom

更新时间:Nov 05, 2025

Alibaba Real-Time Communication (ARTC) SDK menyediakan fitur pengambilan audio kustom yang fleksibel.

Deskripsi fitur

Modul audio internal dari ARTC SDK cukup memadai untuk kebutuhan audio dasar. Namun, dalam beberapa skenario, modul pengambilan audio internal mungkin tidak memenuhi kebutuhan pengembangan Anda. Anda mungkin perlu mengimplementasikan pengambilan audio kustom dalam skenario berikut:

  • Untuk menyelesaikan masalah yang terjadi ketika perangkat pengambilan audio sudah sedang digunakan.

  • Untuk mendapatkan data audio dari sistem pengambilan kustom atau file audio dan meneruskannya ke SDK untuk transmisi.

ARTC SDK mendukung pengambilan kustom yang fleksibel, memungkinkan Anda mengelola perangkat audio dan sumber audio sesuai dengan skenario bisnis Anda.

Kode contoh

Pengambilan audio kustom di Android: Android/ARTCExample/AdvancedUsage/src/main/java/com/aliyun/artc/api/advancedusage/CustomAudioCaptureAndRender/CustomAudioCaptureActivity.java.

Pengambilan audio kustom di iOS: iOS/ARTCExample/AdvancedUsage/CustomAudioCapture/CustomAudioCaptureVC.swift.

Prasyarat

Sebelum mengatur konfigurasi video, pastikan Anda telah memenuhi prasyarat berikut:

  • Anda memiliki Akun Alibaba Cloud yang valid dan telah membuat aplikasi ApsaraVideo Real-time Communication. Untuk informasi lebih lanjut, lihat Buat Aplikasi. Dapatkan App ID dan App Key dari Konsol Manajemen Aplikasi.

  • Anda telah mengintegrasikan ARTC SDK ke dalam proyek Anda dan mengimplementasikan fitur komunikasi real-time dasar. Untuk informasi lebih lanjut tentang integrasi SDK, lihat Unduh dan Integrasi SDK. Untuk informasi lebih lanjut tentang implementasi panggilan audio dan video, lihat Implementasi Panggilan Audio dan Video.

Implementasi

1. Aktifkan atau nonaktifkan pengambilan internal

Untuk menggunakan fitur pengambilan audio kustom, Anda harus memanggil antarmuka setParameter untuk menonaktifkan atau mengaktifkan modul pengambilan audio internal ARTC SDK.

Catatan
  • Antarmuka ini memerlukan string JSON.

  • Anda dapat memanggil antarmuka ini sebelum atau sesudah bergabung dengan saluran.

Android

/* Dinamis menonaktifkan pengambilan internal. */
String parameter = "{\"audio\":{\"enable_system_audio_device_record\":\"FALSE\"}}";
mAliRtcEngine.setParameter(parameter);

/* Dinamis mengaktifkan pengambilan internal. */
String parameter = "{\"audio\":{\"enable_system_audio_device_record\":\"TRUE\"}}"; 
mAliRtcEngine.setParameter(parameter);

iOS

/* Dinamis menonaktifkan pengambilan internal. */
[_engine setParameter:@"{\"audio\":{\"enable_system_audio_device_record\":\"FALSE\"}}"];

/* Dinamis mengaktifkan pengambilan internal. */
[_engine setParameter:@"{\"audio\":{\"enable_system_audio_device_record\":\"TRUE\"}}"];

Windows

/* Windows memungkinkan Anda mengaktifkan atau menonaktifkan pengambilan audio selama pembuatan. */
/* Nonaktifkan pengambilan internal. */
char* extra = "{\"user_specified_enable_use_virtual_audio_device\":\"TRUE\", \"user_specified_use_external_audio_record\":\"TRUE\"}";
mAliRtcEngine = AliRtcEngine.Create(extra);

/* Aktifkan pengambilan internal. */
char* extra = "{\"user_specified_enable_use_virtual_audio_device\":\"FALSE\", \"user_specified_use_external_audio_record\":\"FALSE\"}";
mAliRtcEngine = AliRtcEngine.Create(extra);

2. Tambahkan aliran audio eksternal

Panggil API addExternalAudioStream untuk menambahkan aliran audio eksternal dan mendapatkan ID aliran audio. Jika Anda memerlukan audio 3A (Acoustic Echo Cancellation (AEC), Automatic Gain Control (AGC), dan Acoustic Noise Suppression (ANS)), konfigurasikan parameter enable3A dalam AliRtcExternalAudioStreamConfig.

Catatan

Panggil antarmuka pada waktu berikut:

  • Untuk menggunakan fitur 3A, panggil addExternalAudioStream setelah aliran audio diterbitkan dan modul pengambilan kustom mendapatkan frame audio pertama. Ini berarti Anda harus memanggilnya setelah callback onAudioPublishStateChanged mengembalikan newState sebagai AliRtcStatsPublished (3).

  • Jika Anda tidak memerlukan fitur 3A, seperti saat mentransmisikan file lokal, file jaringan, atau data audio yang dihasilkan oleh teks-ke-ucapan (TTS), Anda dapat menambahkan aliran setelah membuat mesin. Kemudian, mulailah mendorong data audio setelah aliran audio diterbitkan.

Android

AliRtcEngine.AliRtcExternalAudioStreamConfig config = new AliRtcEngine.AliRtcExternalAudioStreamConfig();
config.sampleRate = SAMPLE_RATE; // Laju sampel
config.channels = CHANNEL; // Jumlah saluran
// Volume publikasi
config.publishVolume = 100;
// Volume pemutaran lokal
config.playoutVolume = isLocalPlayout ? 100 : 0;
config.enable3A = true;

int result = mAliRtcEngine.addExternalAudioStream(config);
if (result <= 0) {
    return;
}
// Nilai kembali adalah ID aliran. Anda akan memerlukannya untuk mendorong data ke SDK.
mExternalAudioStreamId = result;

iOS

/* Atur parameter berdasarkan kebutuhan bisnis Anda. */
AliRtcExternalAudioStreamConfig *config = [AliRtcExternalAudioStreamConfig new];
// Harus sama dengan jumlah saluran dalam aliran audio PCM eksternal. Setel ke 1 untuk mono atau 2 untuk stereo.
config.channels = _pcmChannels;
// Harus sama dengan laju sampel aliran audio PCM eksternal.
config.sampleRate = _pcmSampleRate;
config.playoutVolume = 0;
config.publishVolume = 100;
_externalPlayoutStreamId = [self.engine addExternalAudioStream:config];

Windows

/* Dapatkan mesin media. */
IAliEngineMediaEngine* mAliRtcMediaEngine = nullptr;
    
mAliRtcEngine->QueryInterface(AliEngineInterfaceMediaEngine, (void **)&mAliRtcMediaEngine);
/* Atur parameter berdasarkan kebutuhan bisnis Anda. */
AliEngineExternalAudioStreamConfig config;
config.playoutVolume = currentAudioPlayoutVolume;
config.publishVolume = currentAudioPublishVolume;
config.channels = 1;
config.sampleRate = 48000;
config.publishStream = 0;
audioStreamID = mAliRtcMediaEngine->AddExternalAudioStream(config);

mAliRtcMediaEngine->Release();

3. Implementasikan modul pengambilan audio kustom

Fitur pengambilan kustom mengharuskan Anda mengambil dan memproses data audio berdasarkan skenario bisnis Anda. Anda kemudian dapat meneruskan data tersebut ke SDK untuk transmisi.

Alibaba Cloud menyediakan kode contoh yang menunjukkan cara membaca data dalam format PCM dari file PCM lokal atau mikrofon. Untuk implementasi contoh, lihat contoh pengambilan kustom ini.

4. Dorong data audio ke SDK menggunakan ID aliran audio eksternal

Setelah aliran audio diterbitkan (status dalam callback onAudioPublishStateChanged berubah menjadi AliRtcStatsPublished), panggil antarmuka pushExternalAudioStreamRawData. Atur parameter mExternalAudioStreamId ke ID aliran yang Anda dapatkan di Langkah 2 untuk meneruskan data audio yang ditangkap ke SDK.

Catatan
  • Mulailah mengirim data hanya setelah aliran audio diterbitkan. Status dalam callback onAudioPublishStateChanged harus AliRtcStatsPublished.

  • Atur numSamples dari AliRtcAudioFrame berdasarkan panjang data aktual. Pada beberapa perangkat, panjang data audio yang diperoleh menggunakan AudioRecord.read mungkin lebih kecil dari buffer input. Gunakan nilai kembali untuk menentukan panjang data audio aktual.

  • Saat memanggil pushExternalAudioStreamRawData, pemanggilan mungkin gagal jika buffer internal penuh. Anda harus menangani situasi ini dan mencoba lagi transmisi.

  • Secara umum, Anda dapat memanggil pushExternalAudioStreamRawData untuk mengirim data setiap 10 ms.

Android

// Anggaplah data audio yang ditangkap ada di audioData, ukurannya adalah bytesRead byte, dan itu adalah data 10 ms.
if (mAliRtcEngine != null && bytesRead > 0) {
    // Buat objek AliRtcAudioFrame.
    AliRtcEngine.AliRtcAudioFrame sample = new AliRtcEngine.AliRtcAudioFrame();
    sample.data = audioData;
    sample.numSamples = bytesRead / (channels * (bitsPerSample / 8)); // Hitung jumlah sampel berdasarkan jumlah byte yang dibaca.
    sample.numChannels = channels;
    sample.sampleRate = sampleRate;
    sample.bytesPerSample = bitsPerSample / 8;

    // Dorong data ke SDK.
    int ret = mAliRtcEngine.pushExternalAudioStreamRawData(mExternalAudioStreamId, sample);

    if (ret != 0) {
        if (ret == ErrorCodeEnum.ERR_SDK_AUDIO_INPUT_BUFFER_FULL) {
            // Tangani kasus buffer penuh. Tunggu beberapa saat lalu coba lagi. Durasi coba ulang maksimum biasanya beberapa ratus ms.
            int retryCount = 0;
            final int MAX_RETRY_COUNT = 20;
            final int BUFFER_FULL_WAIT_MS = 30;
            while (ret == ErrorCodeEnum.ERR_SDK_AUDIO_INPUT_BUFFER_FULL && retryCount < MAX_RETRY_COUNT) {
                if(!isPushingAudio) {
                    break;
                }
                try {
                    Thread.sleep(BUFFER_FULL_WAIT_MS);
                    ret = mAliRtcEngine.pushExternalAudioStreamRawData(mExternalAudioStreamId, sample);
                    retryCount++;
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }

            // Jika coba ulang masih gagal, catat log.
            if (ret != 0) {
                Log.w("CustomAudioCapture", "Gagal mendorong data audio. Kode kesalahan: " + ret + ", Jumlah coba ulang: " + retryCount);
            }
        } else {
            // Tangani kesalahan lainnya.
            Log.e("CustomAudioCapture", "Gagal mendorong data audio. Kode kesalahan: " + ret);
        }
    }
}

iOS

// Buat objek AliRtcAudioFrame dari data audio yang ditangkap.
let sample = AliRtcAudioFrame()
sample.dataPtr = UnsafeMutableRawPointer(mutating: pcmData)
sample.samplesPerSec = pcmSampleRate
sample.bytesPerSample = Int32(MemoryLayout<Int16>.size)
sample.numOfChannels = pcmChannels
sample.numOfSamples = numOfSamples

var retryCount = 0

while retryCount < 20 {
    if !(pcmInputThread?.isExecuting ?? false) {
        break
    }
    // Dorong data audio ke SDK.
    let rc = rtcEngine?.pushExternalAudioStream(externalPublishStreamId, rawData: sample) ?? 0

    // Tangani buffer penuh.
    // 0x01070101 SDK_AUDIO_INPUT_BUFFER_FULL: Buffer penuh. Retransmisi diperlukan.
    if rc == 0x01070101 && !(pcmInputThread?.isCancelled ?? true) {
        Thread.sleep(forTimeInterval: 0.03) // 30 ms
        retryCount += 1;
    } else {
        if rc < 0 {
            "pushExternalAudioStream error, ret: \(rc)".printLog()
        }
        break
    }
}

Windows

Catatan

Di Windows, sebelum mengimplementasikan pengambilan kustom, Anda harus memanggil antarmuka QueryInterface untuk mendapatkan objek mesin media.

/* Dapatkan mesin media. */
IAliEngineMediaEngine* mAliRtcMediaEngine = nullptr;   
mAliRtcEngine->QueryInterface(AliEngineInterfaceMediaEngine, (void **)&mAliRtcMediaEngine);

// Buat frame audio dari data.
AliEngineAudioRawData rawData;
rawData.dataPtr = frameInfo.audio_data[0];
rawData.numOfSamples = (int) (frameInfo.audio_data[0].length / (2 * frameInfo.audio_channels));
rawData.bytesPerSample = 2;
rawData.numOfChannels = frameInfo.audio_channels;
rawData.samplesPerSec = frameInfo.audio_sample_rate;
// Dorong data ke SDK.
int ret = mAliRtcMediaEngine->PushExternalAudioStreamRawData(audioStreamID, rawData);
// Tangani buffer penuh dan kesalahan lainnya.

// Lepaskan mesin media.
mAliRtcMediaEngine->Release();

5. Hapus aliran audio eksternal

Untuk menghentikan penerbitan audio dari pengambilan kustom, panggil antarmuka removeExternalAudioStream untuk menghapus aliran audio eksternal.

Android

mAliRtcEngine.removeExternalAudioStream(mExternalAudioStreamId);

iOS

[self.engine removeExternalAudioStream:_externalPublishStreamId];

Windows

/* Dapatkan mesin media. */
IAliEngineMediaEngine* mAliRtcMediaEngine = nullptr;
    
mAliRtcEngine->QueryInterface(AliEngineInterfaceMediaEngine, (void **)&mAliRtcMediaEngine);

mAliRtcMediaEngine->RemoveExternalAudioStream(audioStreamID);
mAliRtcMediaEngine->Release();

FAQ

  • Jika perangkat fisik tidak digunakan untuk memberikan input, kami sarankan mengirim data setiap 10 hingga 50 ms.

    • Kami sarankan Anda mengikuti jam perangkat audio fisik. Anda dapat memanggil antarmuka saat perangkat menangkap data.

    • Jika tidak ada perangkat fisik yang digunakan sebagai driver, kami sarankan Anda mengirim data setiap 10 ms hingga 50 ms.

  • Bisakah saya menggunakan fitur 3A internal (AEC, AGC, dan ANS) dari SDK dengan pengambilan audio kustom?

    • Ya, Anda bisa. Di Langkah 2, saat Anda menambahkan aliran audio eksternal, Anda dapat mengatur parameter enable3A untuk mengaktifkan atau menonaktifkan fitur 3A internal SDK.