Mix external audio—background music, sound effects, or PCM streams—into the ARTC SDK audio stream for local playback and remote sharing.
Overview
The ARTC SDK supports external audio input in MP4, WAV, AAC, and PCM formats. You can integrate pre-recorded files or real-time data streams.
Use cases
-
Publishing audio files: Insert sound effects, background music, or spoken content into live streams, such as product alerts in e-commerce or ambient effects in games.
-
Publishing PCM streams: Suited for real-time voice services, such as publishing TTS-generated PCM audio in customer service systems.
Sample code
Android: Android/ARTCExample/BasicUsage/src/main/java/com/aliyun/artc/api/basicusage/PlayAudioFiles/PlayAudioFilesActivity.java
iOS: iOS/ARTCExample/BasicUsage/PlayAudioFiles/PlayAudioFilesVC.swift
Harmony: Harmony/ARTCExample/entry/src/main/ets/pages/basicusage/PlayAudioFilesPage.ets.
Before you begin
Before you begin, ensure the following:
-
You have an Alibaba Cloud account and have created an ARTC application (Create an application). Obtain the AppID and AppKey from the ApsaraVideo Live console.
-
You have integrated the ARTC SDK (Integrate the SDK) and implemented basic audio and video calls (Implement an audio and video call).
Play or publish audio files
How it works
Two sets of APIs are available for playing or publishing audio files:
-
Accompaniment APIs: Play longer audio files such as background music. Only one file can play at a time.
-
Sound effect APIs: Play short audio clips such as applause or laughter. Multiple effects can play simultaneously.
Before playing or publishing external audio, join a channel and publish your local audio stream. Wait for the onAudioPublishStateChanged callback to confirm publishing.
Related APIs:
|
Feature |
Accompaniment APIs |
Sound effect APIs |
|
Control playback |
|
|
|
Manage playback progress |
|
|
|
Manage playback volume |
|
|
|
Playback status callbacks |
Local:
Remote:
|
Local:
|
|
Get audio file information |
|
|
Play an accompaniment
The accompaniment APIs play only one audio file at a time.
-
Join a channel and publish the audio stream. Enabled by default.
Android
// To play an accompaniment or sound effect, you must publish the audio stream. This is enabled by default in the SDK. mAliRtcEngine.publishLocalAudioStream(true);iOS
// To play an accompaniment or sound effect, you must publish the audio stream. This is enabled by default in the SDK. engine.publishLocalAudioStream(true)Harmony
// Publish the local audio stream. This is enabled by default. this.rtcEngine.publishLocalAudioStream(true);Mac
// To play an accompaniment or sound effect, you must publish the audio stream. This is enabled by default in the SDK. [self.engine publishLocalAudioStream:TRUE];Windows
mAliRtcEngine->publishLocalAudioStream(true) -
Control playback
Call startAudioAccompany to start playback. This triggers onAudioAccompanyStateChanged locally and onRemoteAudioAccompanyStarted remotely.
Other playback control APIs:
-
stopAudioAccompany: Stop playback. -
pauseAudioAccompany: Pause playback. -
resumeAudioAccompany: Resume playback. -
getAudioAccompanyDuration, getAudioAccompanyCurrentPosition, setAudioAccompanyPosition: Get duration and control playback progress. -
setAudioAccompanyVolume: Set both local playback and remote publishing volume. -
getAudioAccompanyPublishVolume, setAudioAccompanyPublishVolume: Get or set the remote publishing volume. -
getAudioAccompanyPlayoutVolume, setAudioAccompanyPlayoutVolume: Get or set the local playback volume.
Android
// Path to the accompaniment file.
private String mMixingMusicFilepath = "/assets/music.wav";
// Configure accompaniment playback.
AliRtcEngine.AliRtcAudioAccompanyConfig config = new AliRtcEngine.AliRtcAudioAccompanyConfig();
config.loopCycles = -1; // Number of loops. -1 indicates infinite looping.
config.publishVolume = publishVolume; // Publishing volume. Range: [0, 100].
config.playoutVolume = playbackVolume; // Local playback volume. Range: [0, 100].
config.startPosMs = 0; // Playback starting position.
// Start playback.
mAliRtcEngine.startAudioAccompany(mMixingMusicFilepath, config);
// Pause/Resume the accompaniment.
mAliRtcEngine.pauseAudioAccompany();
mAliRtcEngine.resumeAudioAccompany();
// Stop playback.
mAliRtcEngine.stopAudioAccompany();
// Get the duration of the accompaniment file in ms. Call this method after startAudioAccompany, otherwise it returns -1.
int duration = mAliRtcEngine.getAudioAccompanyDuration();
// To get the duration of a specific file, call getAudioFileInfo. You can call this after creating the engine. The result is returned in the onAudioFileInfo callback.
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);
});
}
// Get/Set the volume.
mAliRtcEngine.setAudioAccompanyVolume(50); // Range: [0, 100].
int publishVolume = mAliRtcEngine.getAudioAccompanyPublishVolume();
mAliRtcEngine.setAudioAccompanyPublishVolume(50);
int playoutVolume = mAliRtcEngine.getAudioAccompanyPlayoutVolume();
mAliRtcEngine.setAudioAccompanyPlayoutVolume(50);
// Get/Set playback progress.
int currPosition = mAliRtcEngine.getAudioAccompanyCurrentPosition(); // Unit: ms.
int targetPosition = 1000; // Example: start playing from the 1000 ms mark.
mAliRtcEngine.setAudioAccompanyPosition(targetPosition);
iOS
// Path to the accompaniment file.
let filePath = Bundle.main.path(forResource: "music", ofType: "wav")
// Configure accompaniment playback.
let config = AliRtcAudioAccompanyConfig()
config.loopCycles = loopCount
config.publishVolume = publishVolume
config.playoutVolume = playoutVolume
config.startPosMs = 0
// Start playback.
let result = rtcEngine.startAudioAccompany(withFile: filePath, config: config)
// Pause/Resume playback.
rtcEngine.pauseAudioAccompany()
rtcEngine.resumeAudioAccompany()
// Stop playback.
rtcEngine.stopAudioAccompany()
// Get the duration of the accompaniment file in ms. Call this method after startAudioAccompany, otherwise it returns -1.
let duration = rtcEngine.getAudioAccompanyDuration()
// To get the duration of a specific file, call getAudioFileInfo. You can call this after creating the engine. The result is returned in the onAudioFileInfo callback.
rtcEngine.getAudioFileInfo(filePath)
func onAudioFileInfo(_ info: AliRtcAudioFileInfo, errorCode: AliRtcAudioAccompanyErrorCode) {
"onAudioFileInfo, filePath: \(info.filePath), durationMs: \(info.durationMs), errorCode: \(errorCode)".printLog()
}
// Get/Set the volume.
rtcEngine.setAudioAccompanyVolume(50) // Set both the publishing and playback volume of the accompaniment. Range: [0-100].
let audioPublishVolume = rtcEngine.getAudioAccompanyPublishVolume() // Get the current publishing volume of the accompaniment.
rtcEngine.setAudioAccompanyPublishVolume(50) // Set the publishing volume of the accompaniment. Range: [0-100].
let audioPlayoutVolume = rtcEngine.getAudioAccompanyPlayoutVolume() // Get the current local playback volume of the accompaniment.
rtcEngine.setAudioAccompanyPlayoutVolume(50) // Set the local playback volume of the accompaniment. Range: [0-100].
// Get/Set playback progress.
let currentPosition = rtcEngine.getAudioAccompanyCurrentPosition() // Unit: ms.
let targetPosition:Int32 = 1000; // Example: start playing from the 1000 ms mark.
rtcEngine.setAudioAccompanyPosition(targetPosition)
Harmony
// Path to the accompaniment file.
private accompanimentFile: string = 'music.wav';
// Start the accompaniment.
private async startAudioAccompany(): Promise<void> {
if (!this.rtcEngine) {
prompt.showToast({ message: 'RTC engine not initialized', duration: 2000 });
return;
}
if (!this.hasJoined) {
prompt.showToast({ message: 'Join a channel first', duration: 2000 });
return;
}
try {
// Get the loop count.
const loopCount = this.loopCount.trim() === '' ? -1 : parseInt(this.loopCount);
const publishVolume = this.pushVolume; // Publishing volume.
const playbackVolume = this.playVolume; // Local playback volume.
// Create an accompaniment configuration.
const config: AliRtcAudioAccompanyConfig = new AliRtcAudioAccompanyConfig();
config.loopCycles = loopCount; // Number of loops. -1 indicates infinite looping.
config.publishVolume = publishVolume; // Publishing volume. Range: [0, 100].
config.playoutVolume = playbackVolume; // Local playback volume. Range: [0, 100].
config.startPosMs = 0; // Playback starting position.
// Use the sandbox file path.
const audioPath = this.sandboxManager.getSandboxFilePath(this.accompanimentFile);
// Start playback.
this.rtcEngine.startAudioAccompany(audioPath, config);
// Get the audio duration and update the progress bar.
const audioDuration = this.rtcEngine.getAudioAccompanyDuration(); // Unit: ms.
if (audioDuration > 0) {
this.audioDuration = audioDuration;
}
console.info('Start playing accompaniment');
} catch (error) {
console.error('Error playing accompaniment:', error);
prompt.showToast({ message: 'Error playing accompaniment', duration: 2000 });
}
}
// Pause the accompaniment.
private pauseAudioAccompany(): void {
if (!this.rtcEngine) {
prompt.showToast({ message: 'RTC engine not initialized', duration: 2000 });
return;
}
this.rtcEngine.pauseAudioAccompany();
console.info('Pause accompaniment playback');
}
// Resume the accompaniment.
private resumeAudioAccompany(): void {
if (!this.rtcEngine) {
prompt.showToast({ message: 'RTC engine not initialized', duration: 2000 });
return;
}
this.rtcEngine.resumeAudioAccompany();
console.info('Resume accompaniment playback');
}
// Stop the accompaniment.
private stopAudioAccompany(): void {
if (!this.rtcEngine) {
prompt.showToast({ message: 'RTC engine not initialized', duration: 2000 });
return;
}
this.rtcEngine.stopAudioAccompany();
console.info('Stop accompaniment playback');
}
// Set the accompaniment volume.
private setAudioAccompanyVolume(volume: number): void {
if (this.rtcEngine && this.hasJoined) {
this.rtcEngine.setAudioAccompanyVolume(volume); // Range: [0, 100].
}
}
// Set the publishing volume.
private setAudioAccompanyPublishVolume(volume: number): void {
if (this.rtcEngine && this.hasJoined) {
this.rtcEngine.setAudioAccompanyPublishVolume(volume); // Range: [0, 100].
}
}
// Set the playback volume.
private setAudioAccompanyPlayoutVolume(volume: number): void {
if (this.rtcEngine && this.hasJoined) {
this.rtcEngine.setAudioAccompanyPlayOutVolume(volume); // Range: [0, 100].
}
}
// Get the publishing volume.
private getAudioAccompanyPublishVolume(): number {
if (this.rtcEngine) {
return this.rtcEngine.getAudioAccompanyPublishVolume();
}
return 0;
}
// Get the playback volume.
private getAudioAccompanyPlayoutVolume(): number {
if (this.rtcEngine) {
return this.rtcEngine.getAudioAccompanyPlayoutVolume();
}
return 0;
}
// Set the playback position.
private setAudioAccompanyPosition(position: number): void {
if (this.rtcEngine && this.hasJoined) {
if (position >= 0 && position <= this.audioDuration) {
this.rtcEngine.setAudioAccompanyPosition(position); // Unit: ms.
}
}
}
// Get the current playback position.
private getAudioAccompanyCurrentPosition(): number {
if (this.rtcEngine && this.hasJoined) {
return this.rtcEngine.getAudioAccompanyCurrentPosition(); // Unit: ms.
}
return 0;
}
// Example of a timer to update playback progress.
private updatePlayProgress(): void {
if (this.rtcEngine && this.hasJoined) {
const currentPosition = this.rtcEngine.getAudioAccompanyCurrentPosition();
this.playProgress = currentPosition;
}
}
Mac
AliRtcAudioAccompanyConfig *config = [[AliRtcAudioAccompanyConfig alloc] init];
config.onlyLocalPlay = localPlay;
config.replaceMic = replaceMic;
config.loopCycles = self.loopLabel.intValue;
config.startPosMs = startPosMs;
config.publishVolume = publishVolume;
config.playoutVolume = playVolume;
NSString *string;
int ret = [self.engine startAudioAccompanyWithFile:self.playURLString config:config];
if (ret) {
string = [NSString stringWithFormat:@"Playback failed. Check the parameter configuration: %d",ret];
} else {
[self.isChangeMicBtn setEnabled:FALSE] ;
if (startPos > 0 && startPosMs == 0) {
string = @"Playback started successfully (music duration not available, start position parameter ignored)";
} else {
string = @"Playback started successfully";
}
}
// Pause/Resume playback.
[self.engine pauseAudioAccompany];
[self.engine resumeAudioAccompany];
// Stop playback.
[self.engine stopAudioAccompany];
// Get the duration of the accompaniment file in ms. Call this method after startAudioAccompany, otherwise it returns -1.
int duration = [self.engine getAudioAccompanyDuration];
// To get the duration of a specific file, call getAudioFileInfo. You can call this after creating the engine. The result is returned in the onAudioFileInfo callback.
[self.engine getAudioFileInfo:filePath];
- (void)onAudioFileInfo:(AliRtcAudioFileInfo* _Nonnull)info errorCode:(AliRtcAudioAccompanyErrorCode)errorCode {
/* Update UI status */
dispatch_async(dispatch_get_main_queue(), ^{
if (self.accompanyVC) {
[self.accompanyVC updateAudioFileInfo:info errorCode:errorCode];
}
if (self.effectVC) {
[self.effectVC updateAudioFileInfo:info errorCode:errorCode];
}
});
}
// Get/Set volume.
[self.engine setAudioAccompanyVolume:sender.integerValue];
// Set both the publishing and playback volume of the accompaniment. Range: [0, 100].
int volume = [self.engine getAudioAccompanyPublishVolume];
sender.title = [NSString stringWithFormat:@"Get publishing volume: %d",volume];
[self.engine setAudioAccompanyPublishVolume:50]; // Set the publishing volume of the accompaniment. Range: [0, 100].
int audioPlayoutVolume = [self.engine getAudioAccompanyPlayoutVolume]; // Get the current local playback volume of the accompaniment.
[self.engine setAudioAccompanyPlayoutVolume:50]; // Set the local playback volume of the accompaniment. Range: [0, 100].
// Get/Set playback progress.
int duration = [self.engine getAudioAccompanyDuration];
long position = duration * sender.integerValue/100;
[self.engine setAudioAccompanyPosition:(int)position];
Windows
AliEngineAudioAccompanyConfig config;
config.onlyLocalPlay = (0 == mbCheckPubAcc);
config.loopCycles = miEditCycleNum;
config.replaceMic = (0 != mbCheckAccReplaceMic);
config.startPosMs = startPosMs;
config.playoutVolume = mbCheckAccMixVol ? miStaticAccMixVol : miStaticAccPlayoutVol;
config.publishVolume = mbCheckAccMixVol ? miStaticAccMixVol : miStaticAccPubVol;
if (0 != mAliRtcEngine->StartAudioAccompany(strPath.c_str(), config))
{
AfxMessageBox(_T("Failed to start accompaniment!"));
return;
}
// Pause/Resume the accompaniment.
mAliRtcEngine->PauseAudioAccompany();
mAliRtcEngine->ResumeAudioAccompany();
// Stop playback.
mAliRtcEngine->StopAudioAccompany();
// Get the duration of the accompaniment file in ms. Call this method after startAudioAccompany, otherwise it returns -1.
int duration = mAliRtcEngine->GetAudioAccompanyDuration();
// To get the duration of a specific file, call getAudioFileInfo. You can call this after creating the engine. The result is returned in the onAudioFileInfo callback.
mAliRtcEngine->GetAudioFileInfo(filePath);
void CTutorialDlg::OnAudioFileInfo(AliEngineAudioFileInfo info,
AliEngineAudioAccompanyErrorCode errorCode) {
/* Notify the UI to refresh. */
CAudioAccompanyDlg::AudioFileInfo *audioInfo = new CAudioAccompanyDlg::AudioFileInfo();
audioInfo->filePath = AliStringToCString(info.filePath);
audioInfo->durationMs = info.durationMs;
::PostMessage(cshell_dlg.GetAudioAccompanyHwnd(), MM_AUDIO_ACCOMPANY_AUDIO_FILE_INFO, (WPARAM)audioInfo, (LPARAM)errorCode);
CAudioEffectDlg::AudioFileInfo *effectInfo = new CAudioEffectDlg::AudioFileInfo();
effectInfo->filePath = AliStringToCString(info.filePath);
effectInfo->durationMs = info.durationMs;
::PostMessage(cshell_dlg.GetAudioEffectHwnd(), MM_AUDIO_EFFECT_AUDIO_FILE_INFO, (WPARAM)effectInfo, (LPARAM)errorCode);
}
/* Get/Set the volume. */
mAliRtcEngine->SetAudioAccompanyVolume(50); // Range: [0, 100].
int publishVolume = mAliRtcEngine->GetAudioAccompanyPublishVolume();
mAliRtcEngine->SetAudioAccompanyPublishVolume(50);
int playoutVolume = mAliRtcEngine->GetAudioAccompanyPlayoutVolume();
mAliRtcEngine->SetAudioAccompanyPlayoutVolume(50);
/* Get/Set playback progress. */
int currPosition = mAliRtcEngine->GetAudioAccompanyCurrentPosition(); // Unit: ms.
int targetPosition = 1000; // Example: start playing from the 1000 ms mark.
mAliRtcEngine->SetAudioAccompanyPosition(targetPosition);
Play sound effects
Use preloadAudioEffect and playAudioEffect to play multiple sound effects simultaneously.
You must assign a unique ID to each sound effect. Your application is responsible for managing these IDs.
-
Join a channel and publish the audio stream. This is enabled by default in the SDK.
Android
// To play an accompaniment or sound effect, you must publish the audio stream. This is enabled by default in the SDK. mAliRtcEngine.publishLocalAudioStream(true);iOS
// To play an accompaniment or sound effect, you must publish the audio stream. This is enabled by default in the SDK. engine.publishLocalAudioStream(true)Harmony
// Publish the local audio stream. This is enabled by default. this.rtcEngine.publishLocalAudioStream(true);Mac
// To play an accompaniment or sound effect, you must publish the audio stream. This is enabled by default in the SDK. [self.engine publishLocalAudioStream:TRUE];Windows
mAliRtcEngine->PublishLocalAudioStream(true); -
(Optional) Preload resources
For repeated playback, preload the audio file into memory with preloadAudioEffect.
-
preloadAudioEffect: Loads a sound effect file. Supports local files and network URLs. Local files are recommended. -
Call
unloadAudioEffectto unload a sound effect and release resources.
Android
// Load the sound effect file with the specified ID and filePath. You must define the ID.
mAliRtcEngine.preloadAudioEffect(mCurrSoundID, filePath);
// Unload the sound effect file with the specified ID.
mAliRtcEngine.unloadAudioEffect(mCurrSoundID);
iOS
// Load the sound effect file with the specified ID and filePath. You must define the ID.
rtcEngine.preloadAudioEffect(withSoundId: self.soundId, filePath: filePath)
// Unload the sound effect file with the specified ID.
rtcEngine.unloadAudioEffect(withSoundId: self.currentEffectIndex)
Harmony
// Load the sound effect file with the specified ID and filePath. You must define the ID.
this.rtcEngine.preloadAudioEffect(1, audioPath);
// Unload the sound effect file with the specified ID.
this.rtcEngine.unloadAudioEffect(this.currSoundID);
Mac
// Load the sound effect file with the specified ID and filePath. You must define the ID.
[self.engine preloadAudioEffectWithSoundId:weakSelf.currentIndex filePath:chooseFileString];
// Unload the sound effect file with the specified ID.
[self.engine unloadAudioEffectWithSoundId:info.effectId];
Windows
// Load the sound effect file with the specified ID and filePath. You must define the ID.
mAliRtcEngine->PreloadAudioEffect(mCurrSoundID, filePath);
// Unload the sound effect file with the specified ID.
mAliRtcEngine->UnloadAudioEffect(mCurrSoundID);
-
Control playback
Call playAudioEffect to play a sound effect. The onAudioEffectFinished callback fires when playback completes.
Other playback control APIs:
-
stopAudioEffect/stopAllAudioEffects: Stop a specific or all sound effects. -
pauseAudioEffect/pauseAllAudioEffects: Pause a specific or all sound effects. -
resumeAudioEffect/resumeAllAudioEffects: Resume a specific or all sound effects. -
getAudioEffectPublishVolume, setAudioEffectPublishVolume, setAllAudioEffectsPublishVolume: Get or set the remote publishing volume. -
getAudioEffectPlayoutVolume, setAudioEffectPlayoutVolume, setAllAudioEffectsPlayoutVolume: Get or set the local playback volume.
Android
// Play the sound effect.
AliRtcEngine.AliRtcAudioEffectConfig config = new AliRtcEngine.AliRtcAudioEffectConfig();
config.loopCycles = -1; // Number of loops. -1 indicates infinite looping.
config.startPosMs = 0; // Playback starting position.
config.publishVolume = 50; // Publishing volume. Range: [0, 100].
config.playoutVolume = 50; // Local playback volume. Range: [0, 100].
mAliRtcEngine.playAudioEffect(mCurrSoundID, filePath, config);
// Stop playback.
mAliRtcEngine.stopAudioEffect(soundId);
mAliRtcEngine.stopAllAudioEffects();
// Pause playback.
mAliRtcEngine.pauseAudioEffect(soundId);
mAliRtcEngine.pauseAllAudioEffects();
// Resume playback.
mAliRtcEngine.resumeAudioEffect(soundId);
mAliRtcEngine.resumeAllAudioEffects();
// Get or set the volume.
// Publishing volume
mAliRtcEngine.getAudioEffectPublishVolume(soundId);
mAliRtcEngine.setAudioEffectPublishVolume(soundId, 50);
mAliRtcEngine.setAllAudioEffectsPublishVolume(50);
// Playback volume
mAliRtcEngine.getAudioEffectPlayoutVolume(soundId);
mAliRtcEngine.setAudioEffectPlayoutVolume(soundId, 50);
mAliRtcEngine.setAllAudioEffectsPlayoutVolume(50);
iOS
// Play
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: "Failed to play sound effect. Error code: \(result)", vc: self)
}
// Stop playback.
rtcEngine.stopAudioEffect(withSoundId: soundId)
rtcEngine.stopAllAudioEffects()
// Pause playback.
rtcEngine.pauseAudioEffect(withSoundId: soundId)
rtcEngine.pauseAllAudioEffects()
// Resume playback.
rtcEngine.resumeAudioEffect(withSoundId: soundId)
rtcEngine.resumeAllAudioEffects()
// Get or set the 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)
Harmony
// Play
const config: AliRtcAudioEffectConfig = new AliRtcAudioEffectConfig();
config.loopCycles = loopCount;
config.startPosMs = 0;
config.publishVolume = this.soundEffectVolume;
config.playoutVolume = this.soundEffectVolume;
const audioPath = this.sandboxManager.getSandboxFilePath(filePath);
this.rtcEngine.playAudioEffect(this.currSoundID, audioPath, config);
// Stop playback.
this.rtcEngine.stopAudioEffect(soundId);
this.rtcEngine.stopAllAudioEffects();
// Pause playback.
this.rtcEngine.pauseAudioEffect(soundId);
this.rtcEngine.pauseAllAudioEffects();
// Resume playback.
this.rtcEngine.resumeAudioEffect(soundId);
this.rtcEngine.resumeAllAudioEffects();
Mac
// Play
AliRtcAudioEffectConfig *config = [AliRtcAudioEffectConfig new];
config.loopCycles = self.circleCountLabel.intValue;
config.needPublish = publish;
config.playoutVolume = info.playoutVolume;
config.publishVolume = info.publishVolume;
config.startPosMs = startPosMs;
int ret = [self.engine playAudioEffectWithSoundId:info.effectId filePath:self.playURLString config:config];
// Stop playback.
[self.engine stopAudioEffectWithSoundId:effectId];
[self.engine stopAllAudioEffects];
// Pause playback.
[self.engine pauseAudioEffectWithSoundId:effectId];
[self.engine pauseAllAudioEffects];
// Resume playback.
[self.engine resumeAudioEffectwithSoundId:soundId];
[self.engine resumeAllAudioEffects];
// Get or set the volume.
int volume = [self.engine getAudioEffectPublishVolumeWithSoundId:soundId];
[self.engine setAudioEffectPublishVolumeWithSoundId:soundId volume: 50];
[self.engine setAllAudioEffectsPublishVolume:50];
[self.engine resumeAudioEffectwithSoundId: soundId];
[self.engine getAudioEffectPlayoutVolumewithSoundId: soundId];
[self.engine setAudioEffectPlayoutVolumeWithSoundId:soundId volume: 50];
Windows
// Play the sound effect.
AliEngineAudioEffectConfig config ;
config.loopCycles = -1; // Number of loops. -1 indicates infinite looping.
config.startPosMs = 0; // Playback starting position.
config.publishVolume = 50; // Publishing volume. Range: [0, 100].
config.playoutVolume = 50; // Local playback volume. Range: [0, 100].
mAliRtcEngine->PlayAudioEffect(mCurrSoundID, filePath, config);
// Stop playback.
mAliRtcEngine->StopAudioEffect(soundId);
mAliRtcEngine->StopAllAudioEffects();
// Pause playback.
mAliRtcEngine->PauseAudioEffect(soundId);
mAliRtcEngine->PauseAllAudioEffects();
// Resume playback.
mAliRtcEngine->ResumeAudioEffect(soundId);
mAliRtcEngine->ResumeAllAudioEffects();
// Get or set the volume.
// Publishing volume
mAliRtcEngine->GetAudioEffectPublishVolume(soundId);
mAliRtcEngine->SetAudioEffectPublishVolume(soundId, 50);
mAliRtcEngine->SetAllAudioEffectsPublishVolume(50);
// Playback volume
mAliRtcEngine->GetAudioEffectPlayoutVolume(soundId);
mAliRtcEngine->SetAudioEffectPlayoutVolume(soundId, 50);
mAliRtcEngine->SetAllAudioEffectsPlayoutVolume(50);
Play or publish PCM audio data
PCM audio uses the Custom audio capture APIs.
How it works
Sample code
Add an external input stream
Android
/* Set the parameters based on your business needs. */
AliRtcEngine.AliRtcExternalAudioStreamConfig config = new AliRtcEngine.AliRtcExternalAudioStreamConfig();
/* Set the playout volume to 0 to disable local playback. */
config.playoutVolume = currentAudioPlayoutVolume;
/* Set the publishing volume to 0 to disable publishing. */
config.publishVolume = currentAudioPublishVolume;
config.channels = 1;
config.sampleRate = 48000;
// The method returns an external input stream ID. Use this ID to push data into the SDK.
audioStreamID = mAliRtcEngine.addExternalAudioStream(config);
iOS
/* Set the parameters based on your business needs. */
AliRtcExternalAudioStreamConfig *config = [AliRtcExternalAudioStreamConfig new];
config.channels = _pcmChannels;
config.sampleRate = _pcmSampleRate;
/* Set the playout volume to 0 to disable local playback. */
config.playoutVolume = 0;
/* Set the publishing volume to 100. This example uses 100, but you can set it to 0 to disable publishing. */
config.publishVolume = 100;
// The method returns an external input stream ID. Use this ID to push data into the SDK.
_externalPlayoutStreamId = [self.engine addExternalAudioStream:config];
Push PCM data to the stream
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) {
// The buffer is full.
sleep(20);
} else if(ret < 0) {
/* An exception occurred. Check the parameters and publishing state. */
}
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) {
// The buffer is full.
sleep(20);
} else if(ret < 0) {
/* An exception occurred. Check the parameters and publishing state. */
}
Remove the external audio stream
Android
mAliRtcEngine.removeExternalAudioStream(audioStreamID);
iOS
[self.engine removeExternalAudioStream:_externalPublishStreamId];
FAQ
-
How do I let only remote users hear the
startAudioAccompanyaccompaniment without my microphone audio?Call
muteLocalMicbefore or during playback to mute the microphone. Remote users then hear only the accompaniment.