Android阿里云RTC使用集锦

625 阅读3分钟

1. 某些设备上音频录制失败,或音频录制断断续续

解决方案:使用外部音频输入模式替代sdk内部的音频采集, 并配置使用aec、ans、agc模块;

1.1 调用setExternalAudioSource启用外部音频输入,并调用setMixedWithMic设置外部音频输入是否与麦克风混合。

JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("user_specified_use_external_audio_record", "TRUE");

jsonObject.addProperty("user_specified_aec", "TRUE");
jsonObject.addProperty("user_specified_ans", "TRUE");
jsonObject.addProperty("user_specified_agc", "TRUE");
//获取mAliRtcEngine
AliRtcEngine mAliRtcEngine = AliRtcEngine.getInstance(getApplicationContext(), jsonObject.toString());
//设置开启外部音频输入源
mAliRtcEngine.setExternalAudioSource(true,16000,1);
//完全替代麦克风采集
mAliRtcEngine.setMixedWithMic(false);

1.2 调用pushExternalAudioFrameRawData输入音频数据。

mAliRtcEngine.pushExternalAudioFrameRawData(buffer,buffer.length,0);

2. extras参数配置后,无法切换听筒/扬声器问题

解决方案: 使用外部音频播放模块,替代sdk内部的音频播放模块

2.1 关闭音频播放,启用外部AudioTrack组件播放音频

//使用外部播放器
mEngine.muteAllRemoteAudioPlaying(true);
initAudioPlayer();
doAudioPlay();

/**
*单声道配置
*/
private void initAudioPlayer() {
        int bufferSizeInBytes = AudioTrack.getMinBufferSize(16000, AudioFormat.CHANNEL_OUT_MONO, ENCODING_PCM_16BIT);
        AudioAttributes attributes = new AudioAttributes.Builder().setContentType(CONTENT_TYPE_SPEECH)
//        AudioAttributes attributes = new AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                .setUsage(USAGE_VOICE_COMMUNICATION)
//                .setUsage(AudioAttributes.USAGE_MEDIA)
                .build();
        AudioFormat audioFormat = new AudioFormat.Builder().setSampleRate(16000)
                .setEncoding(ENCODING_PCM_16BIT)
                .setChannelMask(AudioFormat.CHANNEL_OUT_MONO)
                .build();
        audioTrack = new AudioTrack(attributes, audioFormat, bufferSizeInBytes, AudioTrack.MODE_STREAM , AudioManager.AUDIO_SESSION_ID_GENERATE);
    }
    
private void doAudioPlay() {
    if (audioTrack != null) {
        audioTrack.play();
    }
}

2.2 初始化引擎时配置远端订阅音频输出参数,订阅远端音频,播放远端音频

//配置远端传入音频参数,单声道
mAliRtcEngine.setSubscribeAudioNumChannel(AliRtcEngine.AliRtcAudioNumChannel.AliRtcMonoAudio);
mAliRtcEngine.setSubscribeAudioSampleRate(AliRtcEngine.AliRtcAudioSampleRate.AliRtcAudioSampleRate_16000);

//经过3A处理后的本地音频数据
mAliRtcEngine.registerAudioObserver(AliRtcEngine.AliRtcAudioType.AliRtcPubObserver, new AliRtcEngine.AliRtcAudioObserver() {
    /**
     * 本地采集音频数据
     * @param aliRtcAudioSample
     */
    @Override
    public void onCaptureRawData(AliRtcEngine.AliRtcAudioSample aliRtcAudioSample) {
        Log.d("D_tag", "Raw data local3A AliRtcAudioSample: dataPtr:" + aliRtcAudioSample.dataPtr +
                "==numSamples:" + aliRtcAudioSample.numSamples + "===bytesPerSample: " + aliRtcAudioSample.bytesPerSample +
                "=== data length:" + aliRtcAudioSample.data.length + "===sampleRate: " + aliRtcAudioSample.sampleRate +
                "===numChannels: " + aliRtcAudioSample.numChannels + "===samplesPerSec: " + aliRtcAudioSample.samplesPerSec);
    }

    /**
     * 本地推流数据
     * @param aliRtcAudioSample
     */
    @Override
    public void onCaptureData(AliRtcEngine.AliRtcAudioSample aliRtcAudioSample) {
        Log.d("D_tag", "push data local3A AliRtcAudioSample: dataPtr:" + aliRtcAudioSample.dataPtr +
                "==numSamples:" + aliRtcAudioSample.numSamples + "===bytesPerSample: " + aliRtcAudioSample.bytesPerSample +
                "=== data length:" + aliRtcAudioSample.data.length + "===sampleRate: " + aliRtcAudioSample.sampleRate +
                "===numChannels: " + aliRtcAudioSample.numChannels + "===samplesPerSec: " + aliRtcAudioSample.samplesPerSec);
    }

    /**
     * 本地订阅的远端音频数据
     * @param aliRtcAudioSample
     */
    @Override
    public void onRenderData(AliRtcEngine.AliRtcAudioSample aliRtcAudioSample) {
        Log.d("D_tag", "render data local3A AliRtcAudioSample: dataPtr:" + aliRtcAudioSample.dataPtr +
                "==numSamples:" + aliRtcAudioSample.numSamples + "===bytesPerSample: " + aliRtcAudioSample.bytesPerSample +
                "=== data length:" + aliRtcAudioSample.data.length + "===sampleRate: " + aliRtcAudioSample.sampleRate +
                "===numChannels: " + aliRtcAudioSample.numChannels + "===samplesPerSec: " + aliRtcAudioSample.samplesPerSec);

        //播放远端音频
        if (audioTrack != null && audioTrack.getState() == STATE_INITIALIZED && audioTrack.getPlayState() == PLAYSTATE_PLAYING ) audioTrack.write(aliRtcAudioSample.data, 0, aliRtcAudioSample.data.length);
    }

    @Override
    public void onPlaybackAudioFrameBeforeMixing(String s, AliRtcEngine.AliRtcAudioSample aliRtcAudioSample) {

    }
});

2.3 切换听筒/扬声器播放音频

2.3.1 初始化audiomanager

private  void initAudioManager() {
    audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    //设置通话最大音量
    int volume = audioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL);
    audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, volume, 0);
}

2.3.2 开启/关闭扬声器

/**
 * 开启扬声器
 */
private void openSpeaker() {
    if (audioManager != null && !audioManager.isSpeakerphoneOn()) {
        audioManager.setSpeakerphoneOn(true);
    }
}

/**
 * 关闭扬声器
 */
private void closeSpeaker() {
    if (audioManager != null && audioManager.isSpeakerphoneOn()) {
        audioManager.setSpeakerphoneOn(false);
    }
}

3. 音量控制相关

3.1 录制时增大录制音量

//取值范围[0, 400]
mAliRtcEngine.setRecordingVolume(400);

3.2 播放时增大音量

//取值范围[0, 400]
mAliRtcEngine.setPlayoutVolume(400);

4. 阿里、腾讯RTC使用总结

  1. 阿里云RTC在非手机的特定设备上的使用心得
    1. 阿里云RTC通信sdk在设备通用性兼容性方面并不好,在语言通话场景下,录音及播放方面,设备兼容性问题太多;
    2. 在使用外部音频源输入情况下,正常音频采集会受到影响;例如A和B两方通话,A是非手机的特定设备,音频采集不兼容无法使用,需使用外部音频输入源,B端手机端可以正常使用sdk音频采集;这种情况下,B端音频采集竟然也会受到影响,无法正常采集音频;
  2. 腾讯云TRTC使用测试心得
    1. 诚然,腾讯RTC在非手机的特定设备上音频采集也无法使用;
    2. 比阿里优秀的是,设备端采用外部音频输入源时,不会影响手机端sdk音频采集功能的正常使用。只需要做好设备端外部音频源的aec处理就好。