Topik ini menjelaskan cara mencampurkan sumber audio eksternal—seperti musik latar, efek suara, atau aliran audio PCM kustom—ke dalam aliran audio SDK ARTC, sehingga Anda dapat memutar audio campuran tersebut secara lokal dan mengalirkannya ke pengguna remote di saluran.
Deskripsi fitur
SDK ARTC mendukung pencampuran audio eksternal untuk pemutaran lokal dan publikasi ke pengguna remote. Fitur ini memungkinkan Anda mengintegrasikan serta mengirimkan berbagai sumber audio, mulai dari file yang telah direkam sebelumnya dalam format seperti MP4, WAV, dan AAC hingga aliran data PCM real-time.
Kasus penggunaan
Pengambilan aliran file audio: Masukkan secara dinamis efek suara, musik latar, atau konten ucapan ke dalam siaran langsung. Misalnya, Anda dapat memicu suara notifikasi produk selama siaran langsung e-commerce atau memuat efek suara ambient selama siaran langsung game.
Pengambilan aliran PCM: Digunakan untuk layanan suara interaktif real-time. Misalnya, Anda dapat mengambil aliran audio PCM yang dihasilkan oleh output teks-ke-ucapan (TTS) dari sistem layanan pelanggan cerdas.
Kode contoh
Android: Android/ARTCExample/BasicUsage/src/main/java/com/aliyun/artc/api/basicusage/PlayAudioFiles/PlayAudioFilesActivity.java
iOS: iOS/ARTCExample/BasicUsage/PlayAudioFiles/PlayAudioFilesVC.swift
Sebelum memulai
Sebelum mengimplementasikan fitur ini, pastikan Anda memenuhi persyaratan berikut:
Buat aplikasi ARTC dan peroleh AppID serta AppKey dari Konsol ApsaraVideo Live.
Integrasikan SDK ARTC ke dalam proyek Anda dan implementasikan fitur panggilan audio dan video dasar.
Putar atau publikasikan file audio
Cara kerja
Fitur ini dirancang untuk memutar atau mempublikasikan file audio selama sesi real-time dan menyediakan dua set API untuk kasus penggunaan yang berbeda:
API iringan: Ditujukan untuk memutar file audio yang lebih panjang, seperti musik latar atau iringan musik. Hanya satu file audio dapat diputar dalam satu waktu.
API efek suara: Dioptimalkan untuk memutar klip audio pendek dan transien, seperti tepuk tangan atau tawa. Beberapa efek suara dapat diputar secara bersamaan.
Sebelum memutar atau mempublikasikan audio eksternal, Anda harus terlebih dahulu bergabung ke saluran dan mulai mempublikasikan aliran audio primary Anda. Tunggu callback onAudioPublishStateChanged untuk memastikan aliran audio Anda telah dipublikasikan.
Fitur terkait adalah sebagai berikut:
Fitur | API iringan | API efek suara |
Putar, hentikan, jeda, dan lanjutkan file audio |
|
|
Dapatkan dan sesuaikan progres pemutaran |
| |
Dapatkan dan sesuaikan volume pemutaran audio |
|
|
Laporkan status pemutaran file audio | Lokal:
Remote:
| Lokal:
|
Dapatkan informasi file audio |
| |
Mainkan iringan
Hanya satu file iringan dapat diputar dalam satu waktu.
Bergabung ke saluran dan publikasikan aliran audio. Ini diaktifkan secara default di SDK.
Android
// Untuk memutar sumber audio eksternal, Anda harus terlebih dahulu mempublikasikan aliran audio primary. Ini diaktifkan secara default. mAliRtcEngine.publishLocalAudioStream(true);iOS
// Untuk memutar sumber audio eksternal, Anda harus terlebih dahulu mempublikasikan aliran audio primary. Ini diaktifkan secara default. engine.publishLocalAudioStream(true)Kontrol pemutaran
Setelah bergabung ke saluran dan mempublikasikan aliran audio, panggil startAudioAccompany untuk memutar iringan. Pemanggilan yang berhasil akan memicu callback onAudioAccompanyStateChanged pada client lokal dan callback onRemoteAudioAccompanyStarted pada client remote.
Gunakan API berikut untuk mengontrol pemutaran:
stopAudioAccompany: Menghentikan pemutaran.pauseAudioAccompany: Menjeda pemutaran.resumeAudioAccompany: Melanjutkan pemutaran.getAudioAccompanyDuration,getAudioAccompanyCurrentPosition, dansetAudioAccompanyPosition: Mendapatkan durasi file dan mengontrol progres pemutaran.setAudioAccompanyVolume: Mengatur volume pemutaran lokal dan volume publikasi remote untuk iringan.getAudioAccompanyPublishVolumedansetAudioAccompanyPublishVolume: Mendapatkan atau menyesuaikan volume pemutaran remote untuk iringan.getAudioAccompanyPlayoutVolumedansetAudioAccompanyPlayoutVolume: Mendapatkan atau menyesuaikan volume pemutaran lokal untuk iringan.
Android
// Path ke file iringan audio.
private String mMixingMusicFilepath = "/assets/music.wav";
// Konfigurasikan pemutaran iringan audio.
AliRtcEngine.AliRtcAudioAccompanyConfig config = new AliRtcEngine.AliRtcAudioAccompanyConfig();
config.loopCycles = -1; // Jumlah putaran. -1 berarti putaran tak terbatas.
config.publishVolume = publishVolume; // Volume publikasi. Rentang: [0-100].
config.playoutVolume = playbackVolume; // Volume pemutaran lokal. Rentang: [0-100].
config.startPosMs = 0; // Posisi awal pemutaran dalam milidetik.
// Mulai pemutaran
mAliRtcEngine.startAudioAccompany(mMixingMusicFilepath, config);
// Jeda/Lanjutkan iringan
mAliRtcEngine.pauseAudioAccompany();
mAliRtcEngine.resumeAudioAccompany();
// Hentikan pemutaran
mAliRtcEngine.stopAudioAccompany();
// Dapatkan durasi file iringan dalam ms. Panggil metode ini setelah startAudioAccompany, jika tidak akan mengembalikan -1.
int duration = mAliRtcEngine.getAudioAccompanyDuration();
// Untuk mendapatkan durasi file tertentu, panggil getAudioFileInfo. Anda dapat memanggil ini setelah membuat engine. Hasilnya dikembalikan dalam callback onAudioFileInfo.
mAliRtcEngine.getAudioFileInfo(filePath);
@Override
public void onAudioFileInfo(AliRtcEngine.AliRtcAudioFileInfo info, AliRtcEngine.AliRtcAudioAccompanyErrorCode errorCode) {
handler.post(() -> {
String msg = "onAudioFileInfo.file:" + info.filePath + "duration:" + info.durationMs + "audioPlayingErrorCode=" + errorCode;
ToastHelper.showToast(PlayAudioFilesActivity.this, msg, Toast.LENGTH_SHORT);
});
}
// Dapatkan/Setel volume.
mAliRtcEngine.setAudioAccompanyVolume(50); // [0, 100]
int publishVolume = mAliRtcEngine.getAudioAccompanyPublishVolume();
mAliRtcEngine.setAudioAccompanyPublishVolume(50);
int playoutVolume = mAliRtcEngine.getAudioAccompanyPlayoutVolume();
mAliRtcEngine.setAudioAccompanyPlayoutVolume(50);
// Dapatkan/Setel progres pemutaran.
int currPosition = mAliRtcEngine.getAudioAccompanyCurrentPosition(); // Posisi saat ini dalam ms.
int targetPosition = 1000; // Contoh: mulai memutar dari tanda 1000 ms.
mAliRtcEngine.setAudioAccompanyPosition(targetPosition);iOS
// Path ke file iringan.
let filePath = Bundle.main.path(forResource: "music", ofType: "wav")
// Konfigurasikan pemutaran iringan.
let config = AliRtcAudioAccompanyConfig()
config.loopCycles = loopCount
config.publishVolume = publishVolume
config.playoutVolume = playoutVolume
config.startPosMs = 0
// Mulai pemutaran.
let result = rtcEngine.startAudioAccompany(withFile: filePath, config: config)
// Jeda/Lanjutkan pemutaran.
rtcEngine.pauseAudioAccompany()
rtcEngine.resumeAudioAccompany()
// Hentikan pemutaran.
rtcEngine.stopAudioAccompany()
// Dapatkan durasi file iringan audio dalam ms. Panggil metode ini setelah startAudioAccompany, jika tidak akan mengembalikan -1.
let duration = rtcEngine.getAudioAccompanyDuration()
// Untuk mendapatkan durasi file tertentu, panggil getAudioFileInfo. Anda dapat memanggil ini setelah membuat engine. Hasilnya dikembalikan dalam callback onAudioFileInfo.
rtcEngine.getAudioFileInfo(filePath)
func onAudioFileInfo(_ info: AliRtcAudioFileInfo, errorCode: AliRtcAudioAccompanyErrorCode) {
"onAudioFileInfo, filePath: \(info.filePath), durationMs: \(info.durationMs), errorCode: \(errorCode)".printLog()
}
// Dapatkan/Setel volume.
rtcEngine.setAudioAccompanyVolume(50) // Setel volume publikasi dan pemutaran sekaligus. Rentang: [0-100].
let audioPublishVolume = rtcEngine.getAudioAccompanyPublishVolume() // Dapatkan volume publikasi.
rtcEngine.setAudioAccompanyPublishVolume(50) // Setel volume publikasi. Rentang: [0-100].
let audioPlayoutVolume = rtcEngine.getAudioAccompanyPlayoutVolume() // Dapatkan volume pemutaran lokal.
rtcEngine.setAudioAccompanyPlayoutVolume(50) // Setel volume pemutaran lokal. Rentang: [0-100].
// Dapatkan/Setel progres pemutaran.
let currentPosition = rtcEngine.getAudioAccompanyCurrentPosition() // Posisi saat ini dalam ms.
let targetPosition:Int32 = 1000; // Contoh: mulai memutar dari tanda 1000 ms.
rtcEngine.setAudioAccompanyPosition(targetPosition)Mainkan efek suara
Untuk memutar beberapa efek suara sekaligus (misalnya, tepuk tangan dan tawa), gunakan API seperti preloadAudioEffect dan playAudioEffect.
Setiap file efek suara memerlukan ID unik. Anda harus mengelola ID-ID ini dalam aplikasi Anda.
Bergabung ke saluran dan publikasikan aliran audio. Ini diaktifkan secara default di SDK.
Android
// Untuk memutar sumber audio eksternal, Anda harus terlebih dahulu mempublikasikan aliran audio primary. Ini diaktifkan secara default. mAliRtcEngine.publishLocalAudioStream(true);iOS
// Untuk memutar sumber audio eksternal, Anda harus terlebih dahulu mempublikasikan aliran audio primary. Ini diaktifkan secara default. engine.publishLocalAudioStream(true)(Opsional) Pra-muat sumber daya
Untuk meningkatkan performa saat memutar efek berulang kali, pra-muat file ke memori dengan memanggil preloadAudioEffect.
preloadAudioEffect: Memuat file efek suara yang ditentukan. Mendukung file lokal maupun URL file online. Disarankan menggunakan file lokal.unloadAudioEffect: Saat file efek suara tidak lagi diperlukan, panggil API ini untuk melepasnya dan membebaskan sumber daya.
Android
// Pra-muat file efek suara dengan ID dan path file yang ditentukan. Anda harus menentukan ID tersebut.
mAliRtcEngine.preloadAudioEffect(mCurrSoundID, filePath);
// Lepaskan file efek suara dengan ID yang ditentukan.
mAliRtcEngine.unloadAudioEffect(mCurrSoundID);iOS
// Pra-muat file efek suara dengan ID dan path file yang ditentukan. Anda harus menentukan ID tersebut.
rtcEngine.preloadAudioEffect(withSoundId: self.soundId, filePath: filePath)
// Lepaskan file efek suara dengan ID yang ditentukan.
rtcEngine.unloadAudioEffect(withSoundId: self.currentEffectIndex)Kontrol pemutaran
Setelah bergabung ke saluran dan mempublikasikan aliran audio, panggil playAudioEffect untuk memutar file efek suara. Saat pemutaran selesai, callback onAudioEffectFinished akan dipicu pada client lokal.
Gunakan API berikut untuk mengontrol pemutaran:
stopAudioEffect,stopAllAudioEffects: Menghentikan pemutaran.pauseAudioEffect,pauseAllAudioEffects: Menjeda pemutaran.resumeAudioEffect,resumeAllAudioEffects: Melanjutkan pemutaran.getAudioEffectPublishVolume,setAudioEffectPublishVolume,setAllAudioEffectsPublishVolume: Mendapatkan atau mengatur volume publikasi.getAudioEffectPlayoutVolume,setAudioEffectPlayoutVolume,setAllAudioEffectsPlayoutVolume: Mendapatkan atau mengatur volume pemutaran lokal.
Android
// Mainkan efek suara.
AliRtcEngine.AliRtcAudioEffectConfig config = new AliRtcEngine.AliRtcAudioEffectConfig();
config.loopCycles = -1; // Jumlah putaran pemutaran. -1 berarti putaran tak terbatas.
config.startPosMs = 0; // Posisi awal pemutaran dalam milidetik.
config.publishVolume = 50; // Volume publikasi. Rentang: [0-100].
config.playoutVolume = 50; // Volume pemutaran lokal. Rentang: [0, 100].
mAliRtcEngine.playAudioEffect(mCurrSoundID, filePath, config);
// Hentikan pemutaran.
mAliRtcEngine.stopAudioEffect(soundId);
mAliRtcEngine.stopAllAudioEffects();
// Jeda pemutaran.
mAliRtcEngine.pauseAudioEffect(soundId);
mAliRtcEngine.pauseAllAudioEffects();
// Lanjutkan pemutaran.
mAliRtcEngine.resumeAudioEffect(soundId);
mAliRtcEngine.resumeAllAudioEffects();
// Dapatkan atau atur volume.
// Volume publikasi.
mAliRtcEngine.getAudioEffectPublishVolume(soundId);
mAliRtcEngine.setAudioEffectPublishVolume(soundId, 50);
mAliRtcEngine.setAllAudioEffectsPublishVolume(50);
// Volume pemutaran.
mAliRtcEngine.getAudioEffectPlayoutVolume(soundId);
mAliRtcEngine.setAudioEffectPlayoutVolume(soundId, 50);
mAliRtcEngine.setAllAudioEffectsPlayoutVolume(50);iOS
// Mainkan
let config = AliRtcAudioEffectConfig()
config.loopCycles = -1
config.startPosMs = 0
config.publishVolume = 50
config.playoutVolume = 50
let result = rtcEngine.playAudioEffect(withSoundId: self.soundId, filePath: filePath, config: config)
if result != 0 {
UIAlertController.showAlertWithMainThread(msg: "Gagal memutar efek suara. Kode error: \(result)", vc: self)
}
// Hentikan pemutaran.
rtcEngine.stopAudioEffect(withSoundId: soundId)
rtcEngine.stopAllAudioEffects()
// Jeda pemutaran.
rtcEngine.pauseAudioEffect(withSoundId: soundId)
rtcEngine.pauseAllAudioEffects()
// Lanjutkan pemutaran.
rtcEngine.resumeAudioEffect(withSoundId: soundId)
rtcEngine.resumeAllAudioEffects()
// Dapatkan atau atur volume.
rtcEngine.getAudioEffectPublishVolume(withSoundId: soundId)
rtcEngine.setAudioEffectPublishVolumeWithSoundId(soundId, volume: 50)
rtcEngine.setAllAudioEffectsPublishVolume(50)
rtcEngine.resumeAudioEffect(withSoundId: soundId)
rtcEngine.getAudioEffectPlayoutVolume(withSoundId: soundId)
rtcEngine.setAudioEffectPlayoutVolumeWithSoundId(soundId, volume: 50)Putar atau publikasikan data audio PCM
Jika data audio yang perlu Anda putar atau publikasikan berformat PCM, rujuk metode yang dijelaskan dalam Custom audio capture.
Cara kerja
Kode contoh
Tambahkan aliran input eksternal
Android
/* Atur parameter sesuai kebutuhan. */
AliRtcEngine.AliRtcExternalAudioStreamConfig config = new AliRtcEngine.AliRtcExternalAudioStreamConfig();
/* Untuk menonaktifkan pemutaran lokal, atur volume playout lokal ke 0. */
config.playoutVolume = currentAudioPlayoutVolume;
/* Untuk menonaktifkan publikasi, atur volume publikasi ke 0. */
config.publishVolume = currentAudioPublishVolume;
config.channels = 1;
config.sampleRate = 48000;
// Metode ini mengembalikan ID aliran input eksternal. Gunakan ID ini untuk mendorong data ke SDK.
audioStreamID = mAliRtcEngine.addExternalAudioStream(config);iOS
/* Atur parameter sesuai kebutuhan. */
AliRtcExternalAudioStreamConfig *config = [AliRtcExternalAudioStreamConfig new];
config.channels = _pcmChannels;
config.sampleRate = _pcmSampleRate;
/* Untuk menonaktifkan pemutaran lokal, atur volume playout ke 0. */
config.playoutVolume = 0;
/* Untuk menonaktifkan publikasi, atur volume publikasi ke 100. */
config.publishVolume = 100;
// Metode ini mengembalikan ID aliran input eksternal. Gunakan ID ini untuk mendorong data ke SDK.
_externalPlayoutStreamId = [self.engine addExternalAudioStream:config];Dorong data PCM ke aliran audio
Android
AliRtcEngine.AliRtcAudioFrame rawData = new AliRtcEngine.AliRtcAudioFrame();
rawData.data = frameInfo.audio_data[0];
rawData.numSamples = (int) (frameInfo.audio_data[0].length / (2 * frameInfo.audio_channels));
rawData.bytesPerSample = 2;
rawData.numChannels = frameInfo.audio_channels;
rawData.samplesPerSec = frameInfo.audio_sample_rate;
int ret = mAliRtcEngine.pushExternalAudioStreamRawData(audioStreamID, rawData);
if(ret == 0x01070101) {
// Buffer penuh.
sleep(20);
} else if(ret < 0) {
/* Terjadi pengecualian. Periksa parameter dan status publikasi. */
}iOS
AliRtcAudioFrame *sample = [AliRtcAudioFrame new];
sample.dataPtr = _pcmLocalData;
sample.samplesPerSec = _pcmLocalSampleRate;
sample.bytesPerSample = sizeof(int16_t);
sample.numOfChannels = _pcmLocalChannels;
sample.numOfSamples = numOfSamples;
int rc = [self.engine pushExternalAudioStream:_externalPlayoutStreamId rawData:sample];
if(rc == 0x01070101) {
// Buffer penuh.
sleep(20);
} else if(ret < 0) {
/* Terjadi pengecualian. Periksa parameter dan status publikasi. */
}Hapus aliran audio eksternal
Android
mAliRtcEngine.removeExternalAudioStream(audioStreamID);iOS
[self.engine removeExternalAudioStream:_externalPublishStreamId];FAQ
Bagaimana cara menggunakan
startAudioAccompanyuntuk hanya mempublikasikan iringan, bukan audio mikrofon saya?Panggil metode
muteLocalMicsebelum atau selama pemutaran iringan. Hal ini akan membisukan input mikrofon Anda, sehingga pengguna remote hanya akan mendengar audio dari aliran iringan.