All Products
Search
Document Center

ApsaraVideo Live:Play and publish external audio

Last Updated:Jun 04, 2026

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:

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.

Note

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

  • startAudioAccompany

  • stopAudioAccompany

  • pauseAudioAccompany

  • resumeAudioAccompany

  • preloadAudioEffect

  • unloadAudioEffect

  • playAudioEffect

  • stopAudioEffect

  • stopAllAudioEffects

  • pauseAudioEffect

  • pauseAllAudioEffects

  • resumeAudioEffect

  • resumeAllAudioEffects

Manage playback progress

  • getAudioAccompanyDuration

  • getAudioAccompanyCurrentPosition

  • setAudioAccompanyPosition


Manage playback volume

  • setAudioAccompanyVolume

  • setAudioAccompanyPublishVolume

  • getAudioAccompanyPublishVolume

  • setAudioAccompanyPlayoutVolume

  • getAudioAccompanyPlayoutVolume

  • setAudioEffectPublishVolume

  • getAudioEffectPublishVolume

  • setAudioEffectPlayoutVolume

  • getAudioEffectPlayoutVolume

  • setAllAudioEffectsPublishVolume

  • setAllAudioEffectsPlayoutVolume

Playback status callbacks

Local:

  • onAudioAccompanyStateChanged

Remote:

  • onRemoteAudioAccompanyStarted

  • onRemoteAudioAccompanyFinished

Local:

  • onAudioEffectFinished

Get audio file information

  • getAudioFileInfo

  • onAudioFileInfo

Play an accompaniment

The accompaniment APIs play only one audio file at a time.

  1. 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)
  2. 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.

Note

You must assign a unique ID to each sound effect. Your application is responsible for managing these IDs.

  1. 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);
  2. (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 unloadAudioEffect to 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);
  1. 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

image

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

  1. How do I let only remote users hear the startAudioAccompany accompaniment without my microphone audio?

    Call muteLocalMic before or during playback to mute the microphone. Remote users then hear only the accompaniment.