自定义音频播放

自定义音频播放是用户在具有一定的研发能力的情况,希望自己控制播放来实现某些需求,因此ARTC提供了相关的功能,以方便用户实现这些需求。

功能介绍

ARTC 默认集成了经过市场验证的音频播放模块,能够满足大多数场景下的播放需求。但在某些特殊场景下,用户可能已有成熟的自定义音频播放模块,或需要对音频数据进行二次处理后再播放。为此,ARTC 提供了自定义音频播放能力,允许用户关闭内部播放逻辑,接管音频数据的接收与播放过程。

该功能的核心是通过开启音频帧回调,获取远端或本地的 PCM 音频数据,交由用户实现的播放设备进行处理和回放。

示例代码

Android端自定义音频播放Android/ARTCExample/AdvancedUsage/src/main/java/com/aliyun/artc/api/advancedusage/CustomAudioCaptureAndRender/CustomAudioRenderActivity.java

iOS端自定义音频播放iOS/ARTCExample/AdvancedUsage/CustomAudioRender/CustomAudioRenderVC.swift

前提条件

在使用自定义音频播放前,请确保满足以下条件:

  • 用户已具备完整的音频播放模块开发能力,或已有成熟的第三方/自研音频播放器;

  • 了解基本的音频处理流程,包括 PCM 数据格式、采样率、声道数等概念;

  • 已集成 ARTC SDK 并完成基础音视频通话功能的接入;

  • 明确业务需求必须绕过 ARTC 内部播放模块,否则建议继续使用默认播放方案以保证稳定性与兼容性。

功能实现

image

功能实现

1. 关闭 SDK 内部播放

当您需要使用 SDK 的自定义音频播放功能时,通常需要关闭 SDK 内部音频播放,推荐在调用getInstance创建引擎时传入 extras 参数来关闭 SDK 内部播放,相关参数如下:

user_specified_use_external_audio_player:表示是否使用外部播放。

  • "TRUE":使用外部音频播放,即关闭 SDK 内部播放。

  • "FALSE":不使用外部音频播放,即开启 SDK 内部播放。

Android

String extras = "{\"user_specified_use_external_audio_player\":\"TRUE\"}";
mAliRtcEngine = AliRtcEngine.getInstance(this, extras);

iOS

// 创建并初始化引擎
var customAudioPlayConfig: [String: String] = [:]
// 使用外部播放(停止SDK内部音频播放)
customAudioPlayConfig["user_specified_use_external_audio_player"] = "TRUE"
// 序列化为Json
guard let jsonData = try? JSONSerialization.data(withJSONObject: customAudioPlayConfig, options: []),
let extras = String(data: jsonData, encoding: .utf8) else {
    print("JSON 序列化失败")
    return
}
let engine = AliRtcEngine.sharedInstance(self, extras:extras)

2.监听音频回调

调用enableAudioFrameObserver 注册音频回调,需要传入参数:

  • enable:决定是否允许数据回调。

  • audioSource:回调的数据源类型,包含不同阶段的音频数据。自定义音频播放通常需要回调AliRtcAudioSourcePlayback待播放阶段的数据,对应回调onPlaybackAudioFrame

  • config:期望回调的音频参数,包括采样率、声道数等。

Android

// 设置回调配置
AliRtcEngine.AliRtcAudioFrameObserverConfig config = new AliRtcEngine.AliRtcAudioFrameObserverConfig();
config.sampleRate = AliRtcAudioSampleRate_48000;
config.channels = 1;
// 注册开启播放数据回调
mAliRtcEngine.enableAudioFrameObserver(true, AliRtcAudioSourcePlayback, config);

iOS

// 设置回调配置
var observerConfig: AliRtcAudioFrameObserverConfig = AliRtcAudioFrameObserverConfig()
observerConfig.sampleRate = ._Unknown
observerConfig.channels = .monoAudio
// 注册开启播放数据回调
let audioSource: AliRtcAudioSource = .playback
engine.enableAudioFrameObserver(true, audioSource: audioSource, config: observerConfig)

3.在回调用处理收到的PCM数据给系统音频设备

在回调中处理接收到的PCM数据,同时提交给音频设备。

Android

@Override
public boolean onPlaybackAudioFrame(AliRtcEngine.AliRtcAudioFrame frame) {
    // 播放回调的数据,自行实现

    return true;
}

iOS

func onPlaybackAudioFrame(_ frame: AliRtcAudioFrame) -> Bool {
    // 播放回调的数据,自行实现
    
    return true
}

4.离开频道,关闭监听

Android

mAliRtcEngine.enableAudioFrameObserver(false, AliRtcAudioSourcePlayback, config)

iOS

engine.enableAudioFrameObserver(false, audioSource: audioSource, config: observerConfig)

5. (可选)动态开启/关闭阿里内部播放

如果您的业务场景中需要在通话中动态开启/关闭 SDK 的内部播放,请调用setParameter接口。

Android

/* 动态关闭阿里内部播放 */
String parameter = "{\"audio\":{\"enable_system_audio_device_play\":\"FALSE\"}}";
mAliRtcEngine.setParameter(parameter);

/* 动态打开阿里内部播放 */
String parameter = "{\"audio\":{\"enable_system_audio_device_play\":\"TRUE\"}}"; 
mAliRtcEngine.setParameter(parameter);

iOS

// 动态关闭阿里内部播放
engine.setParameter("{\"audio\":{\"enable_system_audio_device_play\":\"FALSE\"}}")
// 动态开启阿里内部播放
engine.setParameter("{\"audio\":{\"enable_system_audio_device_play\":\"TRUE\"}}")