* 音频数据回调观察者:因为RTC引擎底层使用弱引用持有观察者需要应用层自己管理观察者的生命周期
private IAudioFrameObserver mAudioFrameObserver;
public void startSuccentorAudioMixing() {
IMediaPlayer mediaPlayer = mRTCVideo.getMediaPlayer(0);
MediaPlayerCustomSource source = new MediaPlayerCustomSource(null, MediaPlayerCustomSourceMode.PUSH, MediaPlayerCustomSourceStreamType.RAW);
mediaPlayer.openWithCustomSource(source, new MediaPlayerConfig(AudioMixingType.AUDIO_MIXING_TYPE_PLAYOUT_AND_PUBLISH, 1));
mAudioFrameObserver = new IAudioFrameObserver() {
public void onRemoteUserAudioFrame(RemoteStreamKey streamInfo, IAudioFrame audioFrame) {
if (audioFrame.data_size() > 0) {
AudioFrame frame = new AudioFrame();
int size = audioFrame.data_size();
frame.buffer = new byte[size];
ByteBuffer originalBuffer = audioFrame.getDataBuffer();
originalBuffer.get(frame.buffer);
frame.channel = audioFrame.channel();
frame.sampleRate = audioFrame.sample_rate();
frame.samples = size / frame.channel.value() / 2;
mediaPlayer.pushExternalAudioFrame(frame);
mRTCVideo.enableAudioFrameCallback(AUDIO_FRAME_CALLBACK_REMOTE_USER, new AudioFormat(AudioSampleRate.AUDIO_SAMPLE_RATE_AUTO, AudioChannel.AUDIO_CHANNEL_AUTO));
mRTCVideo.registerAudioFrameObserver(mAudioFrameObserver);
public void stopSuccentorAudioMixing() {
mRTCVideo.disableAudioFrameCallback(AUDIO_FRAME_CALLBACK_REMOTE_USER);
* @param streamKey 远端流信息
* @param streamType 媒体流类型
public void onStreamSyncInfoReceived(RemoteStreamKey streamKey, StreamSycnInfoConfig.SyncInfoStreamType streamType, ByteBuffer data) {
super.onStreamSyncInfoReceived(streamKey, streamType, data);
Charset charset = StandardCharsets.UTF_8;
CharsetDecoder decoder = charset.newDecoder();
CharBuffer charBuffer = null;
charBuffer = decoder.decode(data);
} catch (CharacterCodingException e) {
String progressStr = charBuffer != null ? charBuffer.toString() : null;
if (progressStr != null) {
StreamSycnInfoConfig config = new StreamSycnInfoConfig(StreamIndex.STREAM_INDEX_MAIN, 0, StreamSycnInfoConfig.SyncInfoStreamType.SYNC_INFO_STREAM_TYPE_AUDIO);
mRTCEngine.sendStreamSyncInfo(progressStr.getBytes(StandardCharsets.UTF_8), config);
syncLocalLyricsProgress(progressStr);