如何获取音频PCM数据

本篇文档将介绍使用AICallKit SDK获取音频PCM数据。

功能描述

PCM(Pulse Code Modulation,脉冲编码调制)是一种将模拟信号转换为数字信号的技术。它通过对模拟信号进行采样和量化,生成一系列离散的数字值,这些数字值直接表示原始信号的幅度。在AI实时互动中,您可以通过集成AICallKit SDK来调用相关接口,来获取用户端或者智能体端的音频PCM数据。

应用场景

在数字人通话过程中,您可以利用获取的PCM数据以驱动数字人实现更为生动的肢体语言和表情。同时,您也可以将获取的PCM数据保存为文件以便于后续的留存。

获取音频PCM数据

AICallKit SDK目前的API并未直接提供获取用户或智能体音频PCM数据的回调。然而,它依赖于底层ARTC SDK所提供的音频裸数据回调。您可以基于AICallKit所暴露的ARTC SDK引擎对象,实现音频裸数据回调。

说明

当某些功能在AICallKits SDK中未提供相关API,而在原子的ARTC SDK中可用时,可以通过上述方式获取ARTC SDK引擎的对象AliRtcEngine,随后使用AliRtcEngine对象调用其原子接口。

步骤一:获取ARTC SDK引擎对象AliRtcEngine

您需要在AICallKit SDKonCallBegin回调中获取ARTC SDK引擎对象AliRtcEngine,示例代码如下:

Android

@Override
public void onCallBegin() {
    AliRtcEngine rtcEngine = mARTCAICallEngine.getRtcEngine();
    if (rtcEngine != null) {
        //调用rtc的方法
    }
 }

iOS

// 确保你的工程所在的模块已经依赖了AliVCSDK_***相关的SDK,否则这里import会失败
#if canImport(AliVCSDK_ARTC)
import AliVCSDK_ARTC
#elseif canImport(AliVCSDK_InteractiveLive)
import AliVCSDK_InteractiveLive
#elseif canImport(AliVCSDK_Standard)
import AliVCSDK_Standard
#endif

public func onCallBegin() {
    let rtc = self.engine.getRTCInstance() as? AliRtcEngine
    // 调用rtc的方法
}

步骤二:实现AliRtcEngine.AliRtcAudioFrameObserver

AliRtcAudioFrameObserver类有不同阶段的音频数据回调,您可以选择适合业务需求的回调,示例代码如下:

Android

public class AUIAICallInCallActivity extends AppCompatActivity implements AliRtcEngine.AliRtcAudioFrameObserver{

     @Override
    public boolean onCapturedAudioFrame(AliRtcEngine.AliRtcAudioFrame frame) {
        //处理采集的音频数据(对应的类型是AliRtcAudioSourceCaptured)
        return false;
    }
    @Override
    public boolean onProcessCapturedAudioFrame(AliRtcEngine.AliRtcAudioFrame frame){
        //处理3A后的音频数据(对应的类型是AliRtcAudioSourceProcessCaptured)
        return false;
    }
    @Override
    public boolean onPublishAudioFrame(AliRtcEngine.AliRtcAudioFrame frame){
        //处理推流的音频数据(对应的类型是AliRtcAudioSourcePub)
        return false;
    }
    @Override
    public boolean onPlaybackAudioFrame(AliRtcEngine.AliRtcAudioFrame frame) {
        //处理播放的音频数据(对应的类型是AliRtcAudioSourcePlayback)
        return false;
    }
    @Override
    public boolean onMixedAllAudioFrame(AliRtcEngine.AliRtcAudioFrame frame){
        //处理推流和播放混音后的音频数据(对应的类型是AliRtcAudioSourceMixedAll)
        return false;
    }
    @Override
    public boolean onRemoteUserAudioFrame(String uid, AliRtcEngine.AliRtcAudioFrame frame){
        //处理拉流的远端音频数据 (对应的类型是AliRtcAudioSourceRemoteUser)
        return false;
    }
}

iOS

extension AUIAICallViewController: AliRtcAudioFrameDelegate {
    
    public func onCapturedAudioFrame(_ frame: AliRtcAudioFrame) -> Bool {
        // 这里处理返回的音频采集裸数据(对应的类型是AliRtcAudioSourceCaptured)
        return true
    }

    public func onProcessCapturedAudioFrame(_ frame: AliRtcAudioFrame) -> Bool {
        //处理3A后的音频数据(对应的类型是AliRtcAudioSourceProcessCaptured)
        return false
    }

    public func onPublishAudioFrame(_ frame: AliRtcAudioFrame) -> Bool {
        //处理推流的音频数据(对应的类型是AliRtcAudioSourcePub)
        return false
    }

    public func onPlaybackAudioFrame(_ frame: AliRtcAudioFrame) -> Bool {
        //处理播放的音频数据(对应的类型是AliRtcAudioSourcePlayback)
        return false
    }

    public func onMixedAllAudioFrame(_ frame: AliRtcAudioFrame) -> Bool {
        //处理推流和播放混音后的音频数据(对应的类型是AliRtcAudioSourceMixedAll)
        return false
    }

    public func onRemoteUserAudioFrame(_ uid: String?, frame: AliRtcAudioFrame) -> Bool {
        //处理拉流的远端音频数据 (对应的类型是AliRtcAudioSourceRemoteUser)
        return false
    }

}

步骤三:注册音频PCM数据回调接口

AliRtcEngine引擎提供registerAudioFrameObserver注册音频裸数据回调,使用enableAudioFrameObserver控制回调的开启和关闭。

Android

@Override
public void onCallBegin() {
    AliRtcEngine rtcEngine = mARTCAICallEngine.getRtcEngine();
    if (rtcEngine != null) {
        //设置音频裸数据回调
        rtcEngine.registerAudioFrameObserver(AUIAICallInCallActivity.this);
        //设置不同的类型,得到不同阶段的音频PCM数据
        //AliRtcAudioSourceCaptured:采集的音频数据,AliRtcAudioSourceProcessCaptured:3A后的音频数据,AliRtcAudioSourcePub:推流的音频数据
        //AliRtcAudioSourcePlayback:播放的音频数据,AliRtcAudioSourceMixedAll:推流和播放混音后的音频数据,AliRtcAudioSourceRemoteUser:拉流的远端音频数据
        rtcEngine.enableAudioFrameObserver(true, AliRtcAudioSourceCaptured, null);
    }
 }

iOS

// 确保你的工程所在的模块已经依赖了AliVCSDK_***相关的SDK,否则这里import会失败
#if canImport(AliVCSDK_ARTC)
import AliVCSDK_ARTC
#elseif canImport(AliVCSDK_InteractiveLive)
import AliVCSDK_InteractiveLive
#elseif canImport(AliVCSDK_Standard)
import AliVCSDK_Standard
#endif

public func onCallBegin() {
    let rtc = self.controller.currentEngine.getRTCInstance() as? AliRtcEngine
    // 添加音频帧数据回调
    rtc?.registerAudioFrameObserver(self)
    // 监听采集到的裸数据,监听对应的类型,则需要实现它的回调接口并返回true,例如onCapturedAudioFrame
    rtc?.enableAudioFrameObserver(true, audioSource: .captured, config: nil)
}