TRTC 實時音視頻啤它,兼容騰訊、ZEGO內(nèi)核

新年好呀网棍。本來應(yīng)該在放假前寫完這篇的兼蜈,比較忙,年前要發(fā)一個小版本序宦,所以推遲到了年后了睁壁。
新的一年,新的開始互捌,新的征程潘明。

??做為一個多年娛樂社交軟件開發(fā)者,接觸最多的就是接入各種SDK秕噪,包括什么友盟钳降、極光、創(chuàng)藍(lán)腌巾、騰訊云遂填、阿里云铲觉、網(wǎng)易云、亞馬遜等等吓坚。其中和項目掛鉤比較緊的撵幽,比如直播、實時語音礁击、實時視頻等也比較多盐杂,從開始接觸到現(xiàn)在,直播接觸過七牛云客税、阿里云况褪、騰訊云、網(wǎng)宿更耻,實時音視頻接觸過騰訊云测垛、聲網(wǎng)、zego秧均。各家的sdk接入方面形形色色食侮,也大同小異。前這段時間項目說需要更換sdk目胡,后續(xù)又說可能需要兼容之前的sdk锯七,本來想著換個就換下,反正之前也接觸過誉己,后來仔細(xì)思考了一下眉尸,還是做一個集合工具,兼容兩家sdk巨双。
??具體的思路是之前在尋找視頻播放器時噪猾,他們有播放內(nèi)核替換的方案,所以在做該功能時筑累,也是借鑒了這個方案袱蜡,同時也參考了工廠模式和單例模式。

??1.根據(jù)業(yè)務(wù)需要慢宗,我們可以先定義一個單例坪蚁,用來初始化sdk,以及提供業(yè)務(wù)需要使用的sdk的方法镜沽,比如推拉流敏晤、開閉麥克風(fēng)、開閉揚聲器缅茉、調(diào)節(jié)聲音等茵典,提供這些方法給業(yè)務(wù)層邏輯調(diào)用。
 /**
     * 初始化
     */
    public void initSDKApi() {
        if (mTRTCInterface == null) {
            synchronized (TxTRTCController.class) {
                if (mTRTCInterface == null) {
                    mTRTCInterface = new TxTRTCZego();
                }
            }
        }
    }
   /**
     * 開始播放音樂
     */

    public void startPlayMusic(int id, String path) {
        getSDKEngine().startAudioPlay(id, path);
    }

    /**
     * 恢復(fù)播放音樂
     */
    public void resumePlayMusic(int id) {
        getSDKEngine().resumeAudioPlay(id);
    }

    /**
     * 暫停播放音樂
     */
    public void pausePlayMusic(int id) {
        getSDKEngine().pauseAudioPlay(id);
    }

    /**
     * 停止播放音樂
     */
    public void stopPlayMusic(int id) {
        getSDKEngine().stopAudioPlay(id);
    }
 /**
     * 是否靜音
     */
    public void setMuteAllAudio(boolean mute) {
        getSDKEngine().setMuteAllAudio(mute);
    }

    /**
     * 發(fā)布流
     *
     * @param streamId
     */
    public void startPublishing(String streamId, boolean openMic) {
        getSDKEngine().startPublishingStream(streamId, openMic);
    }

    /**
     * 停止發(fā)布
     */
    public void stopPublishing(String streamId) {
        getSDKEngine().stopPublishingStream(streamId);
    }

與業(yè)務(wù)層相關(guān)聯(lián)的只有這個單例宾舅,不管sdk如何改變统阿,都不會影響到業(yè)務(wù)層的代碼邏輯,也不用修改業(yè)務(wù)層的邏輯筹我,我只需要在這個單例中修改可以了扶平。
具體代碼如下:

public class TxTRTCController {
    private static TxTRTCController instance;
    public int mBGMId = 1024;//背景音樂ID
    public int mSoundEffectId = 1025;//音效ID
    private TxTRTCInterface mTRTCInterface;

    public TxTRTCController() {
    }

    public static TxTRTCController getInstance() {
        if (instance == null) {
            synchronized (TxTRTCController.class) {
                if (instance == null) {
                    instance = new TxTRTCController();
                }
            }
        }
        return instance;
    }

    /**
     * 初始化
     */
    public void initSDKApi() {
        if (mTRTCInterface == null) {
            synchronized (TxTRTCController.class) {
                if (mTRTCInterface == null) {
                    mTRTCInterface = new TxTRTCZego();
                }
            }
        }
    }


    public TxTRTCInterface getSDKEngine() {
        initSDKApi();
        return mTRTCInterface;
    }

    /**
     * 登錄
     *
     * @param roomId
     */
    public void setLoginRoom(String roomId, boolean video, String quality) {
        if (getSDKEngine() == null) return;
        if(TxNetConstants.SERVER_IS_TEST){
            getSDKEngine().loginRoom(roomId+"dev", video, quality);
        }else {
            getSDKEngine().loginRoom(roomId, video, quality);
        }

    }

    /**
     * 上麥
     */
    public void setUpSeat(String roomId) {
        getSDKEngine().setUpSeat(roomId);
    }

    /**
     * 下麥
     */
    public void setDownSeat(String roomId) {
        getSDKEngine().setDownSeat(roomId);
    }

    /**
     * 退出房間
     */
    public void setLogoutRoom(String roomId) {
        getSDKEngine().logoutRoom(roomId);
    }

    /**
     * 銷毀SDK
     */
    public void destroyEngine(String roomId) {
        TxRoomJoinGroupUtil.getInstence().quitGroup(roomId);
        if(mTRTCInterface!=null) {
            getSDKEngine().destroyEngine(roomId);
        }
        mTRTCInterface = null;
    }


    //###########################################################   調(diào)用的方法start  #####################################################################################################


    /**
     * 設(shè)置監(jiān)聽
     *
     * @param musicListener
     */
    public void setAudioEffectListener(TxTRTCMusicListener musicListener) {
        if(mTRTCInterface instanceof TxTRTCTencent){
            getSDKEngine().setAudioEffectListener(TxTRTCInterface.Audio_BGMId,musicListener);
            getSDKEngine().setAudioEffectListener(TxTRTCInterface.Audio_SoundEffectId,musicListener);
        }else {
            getSDKEngine().setAudioEffectListener(TxTRTCInterface.Audio_BGMId,musicListener);
        }

    }

    /**
     * 開始播放音樂
     */

    public void startPlayMusic(int id, String path) {
        getSDKEngine().startAudioPlay(id, path);
    }

    /**
     * 恢復(fù)播放音樂
     */
    public void resumePlayMusic(int id) {
        getSDKEngine().resumeAudioPlay(id);
    }

    /**
     * 暫停播放音樂
     */
    public void pausePlayMusic(int id) {
        getSDKEngine().pauseAudioPlay(id);
    }

    /**
     * 停止播放音樂
     */
    public void stopPlayMusic(int id) {
        getSDKEngine().stopAudioPlay(id);
    }

    /**
     * 設(shè)置人聲
     */
    public void setAudioVoiceCaptureVolume(int progress) {
        getSDKEngine().setAudioVoiceCaptureVolume(progress);
    }

    /**
     * 設(shè)置背景音樂音量
     *
     * @param progress
     */
    public void setAudioMusicVolume(int id, int progress) {
        getSDKEngine().setAudioMusicVolume(id, progress);
    }

    /**
     * 設(shè)置監(jiān)聽
     *
     * @param listener
     */
    public void setCallSDKListener(TxTRTCListener listener) {
        getSDKEngine().setCallSDKListener(listener);
    }


    /**
     * 是否關(guān)閉麥克風(fēng)
     */
    public void setMicMute(boolean isMute) {
        getSDKEngine().setMicMute(isMute);
    }

    /**
     * 是否使用揚聲器
     * 揚聲器還是聽筒
     *
     * @param isHandsFree
     */
    public void setHandsFree(boolean isHandsFree) {
        getSDKEngine().setHandsFree(isHandsFree);
    }

    /**
     * 是否靜音
     */
    public void setMuteAllAudio(boolean mute) {
        getSDKEngine().setMuteAllAudio(mute);
    }

    /**
     * 發(fā)布流
     *
     * @param streamId
     */
    public void startPublishing(String streamId, boolean openMic) {
        getSDKEngine().startPublishingStream(streamId, openMic);
    }

    /**
     * 停止發(fā)布
     */
    public void stopPublishing(String streamId) {
        getSDKEngine().stopPublishingStream(streamId);
    }

    /**
     * 停止拉取視頻流(所有流)
     */
    public void stopPlayAllVideo(boolean open) {
        getSDKEngine().stopPlayAllVideo(open);
    }


    /**
     * 開啟音量回調(diào)
     *
     * @param enable
     */
    public void enableAudioSoundLevelMonitor(boolean enable) {
        getSDKEngine().enableAudioSoundLevelMonitor(enable);
    }
??2.既然sdk的邏輯調(diào)用抽取出來了,那我們怎么進行內(nèi)核替換呢蔬蕊。這時我想到了工廠模式结澄,提取出一些抽象方法,將不同的sdk作為工廠對象岸夯,這樣在單例中麻献,我只需要初始化相應(yīng)的工廠,獲取到相應(yīng)的對象就行猜扮。
public abstract class TxTRTCInterface {
    public static final int Audio_BGMId = 1024;//背景音樂ID
    public static final int Audio_SoundEffectId = 1025;//音效ID

    public abstract void initSDK();//初始化SDK
    public abstract void loginRoom(String roomId, boolean video, String quality);//登錄房間
    public abstract void logoutRoom(String roomId);//退出房間
    public abstract  void setUpSeat(String roomId);//上麥
    public abstract  void setDownSeat(String roomId);//下麥
    public abstract  void destroyEngine(String roomId);//銷毀引擎
    public abstract  void setAudioEffectListener(int id,TxTRTCMusicListener musicListener);//設(shè)置BGM監(jiān)聽
    public abstract  void startAudioPlay(int id,String path);//播放BGM
    public abstract  void resumeAudioPlay(int id);//恢復(fù)播放BGM
    public abstract  void pauseAudioPlay(int id);//暫停播放BGM
    public abstract  void stopAudioPlay(int id);//停止播放BGM
    public abstract  void setAudioVoiceCaptureVolume(int progress);//設(shè)置人聲
    public abstract  void setAudioMusicVolume(int id,int progress);//設(shè)置背景音樂聲音
    public abstract  void setCallSDKListener(TxTRTCListener listener);//設(shè)置SDK回調(diào)

    public abstract void setMicMute(boolean isMute);//是否關(guān)閉麥克風(fēng)
    public abstract void setHandsFree(boolean isHandsFree) ;//是否使用揚聲器. 揚聲器還是聽筒
    public abstract void setMuteAllAudio(boolean mute);//是否靜音
    public abstract void startPublishingStream(String streamId, boolean openMic);//發(fā)布流
    public abstract void stopPublishingStream(String streamId) ;//停止發(fā)布
    public abstract void stopPlayAllVideo(boolean open);//  停止拉取流(所有流)
    public abstract void enableAudioSoundLevelMonitor(boolean enable) ;// 開啟音量回調(diào)
}

抽取的方法大部分sdk都是一樣的勉吻,當(dāng)然也有一些sdk有不同的區(qū)別,這個就需要單獨做一些處理了旅赢。
騰訊sdk:

public class TxTRTCTencent extends TxTRTCInterface {

    private TRTCCloud mTRTCCloud;
    private TXAudioEffectManager mAudioManager;

    public TxTRTCTencent() {
        initSDK();
    }

    @Override
    public void initSDK() {
        if (mTRTCCloud == null) {
            synchronized (TxTRTCTencent.class) {
                if (mTRTCCloud == null) {
                    mTRTCCloud = TRTCCloud.sharedInstance(TxBaseApplication.getContext());
                }
                if (mAudioManager == null) mAudioManager = mTRTCCloud.getAudioEffectManager();
            }
        }
    }

    private TRTCCloud getSDKEngine() {
        initSDK();
        return mTRTCCloud;
    }

    @Override
    public void loginRoom(String roomId, boolean video, String quality) {
        if (getSDKEngine() == null) return;
        TRTCCloudDef.TRTCParams tRTCParams = new TRTCCloudDef.TRTCParams((int) TxNetConstants.getTencentImAppid(),
                TxUserControl.getInstance().getUserId(),
                TxPrefUtils.getString(TxNetConstants.User.USER_IMSIG, ""), roomId, "", "");
        tRTCParams.role = TRTCCloudDef.TRTCRoleAnchor;
        setHandsFree(true);
        getSDKEngine().enterRoom(tRTCParams, TRTCCloudDef.TRTC_APP_SCENE_AUDIOCALL);
    }

    @Override
    public void logoutRoom(String roomId) {
        getSDKEngine().exitRoom();
    }

    @Override
    public void setUpSeat(String roomId) {
        getSDKEngine().switchRole(TRTCCloudDef.TRTCRoleAnchor);
        startLocalAudio();
    }

    /**
     * 開啟音頻預(yù)覽
     */
    private void startLocalAudio() {
        getSDKEngine().startLocalAudio(TRTCCloudDef.TRTC_AUDIO_QUALITY_SPEECH);
    }

    private void stopLocalAudio() {
        getSDKEngine().stopLocalAudio();
    }

    @Override
    public void setDownSeat(String roomId) {
        getSDKEngine().stopLocalAudio();
        stopAudioPlay(Audio_BGMId);
        getSDKEngine().switchRole(TRTCCloudDef.TRTCRoleAudience);

    }

    @Override
    public void destroyEngine(String roomId) {

        if (mTRTCCloud!= null) {
            stopPlayAllVideo(false);
            getSDKEngine().stopLocalAudio();
            stopPublishingStream(roomId);
            logoutRoom(roomId);
        }
        if (mAudioManager != null) {
            mAudioManager.setMusicObserver(Audio_BGMId, null);
            mAudioManager.setMusicObserver(Audio_SoundEffectId, null);
        }
        TRTCCloud.destroySharedInstance();

        mTRTCCloud = null;
        mAudioManager = null;
    }

    /**
     * 獲取背景音樂管理器
     *
     * @return
     */
    private TXAudioEffectManager getAudioManager() {
        if (mAudioManager == null) {
            synchronized (TxTRTCTencent.class) {
                if (mAudioManager == null) mAudioManager = getSDKEngine().getAudioEffectManager();
            }
        }
        return mAudioManager;
    }

    @Override
    public void setAudioEffectListener(int id, TxTRTCMusicListener musicListener) {
        getAudioManager().setMusicObserver(id, null);
        getAudioManager().setMusicObserver(id, new TXAudioEffectManager.TXMusicPlayObserver() {
            @Override
            public void onStart(int id, int errCode) {
                if (errCode != 0) {
                    if (Audio_SoundEffectId == id) {
                        if (musicListener != null) musicListener.playEnd(id);
                    } else {
                        if (musicListener != null) musicListener.playError(id);
                    }
                    return;
                }
                if (musicListener != null) musicListener.playing(id);
            }

            @Override
            public void onPlayProgress(int id, long curPtsMS, long durationMS) {
                if (Audio_BGMId == id) {
                    if (musicListener != null)
                        musicListener.playProgress(curPtsMS, durationMS);
                }
            }

            @Override
            public void onComplete(int id, int errCode) {
                if (errCode != 0) {
                    if (Audio_SoundEffectId == id) {
                        if (musicListener != null) musicListener.playEnd(id);
                    } else {
                        if (musicListener != null) musicListener.playError(id);
                    }
                    return;
                }
                if (musicListener != null) musicListener.playEnd(id);
            }
        });
    }

    @Override
    public void startAudioPlay(int id, String path) {
        TXAudioEffectManager.AudioMusicParam audioMusicParam = new TXAudioEffectManager.AudioMusicParam(id, path);
        audioMusicParam.publish = true; //上行
        getAudioManager().startPlayMusic(audioMusicParam);
    }

    @Override
    public void resumeAudioPlay(int id) {
        getAudioManager().resumePlayMusic(id);
    }

    @Override
    public void pauseAudioPlay(int id) {
        getAudioManager().pausePlayMusic(id);
    }

    @Override
    public void stopAudioPlay(int id) {
        getAudioManager().stopPlayMusic(id);
    }

    @Override
    public void setAudioVoiceCaptureVolume(int progress) {
        getAudioManager().setVoiceCaptureVolume(progress);
    }

    @Override
    public void setAudioMusicVolume(int id, int progress) {
        getAudioManager().setMusicPlayoutVolume(id, progress);
        getAudioManager().setMusicPublishVolume(id, progress);
    }

    @Override
    public void setCallSDKListener(TxTRTCListener listener) {
        getSDKEngine().setListener(null);
        getSDKEngine().setListener(new TRTCCloudListener() {

            @Override
            public void onError(int code, String s, Bundle bundle) {
                super.onError(code, s, bundle);
                if (listener != null) listener.error(code, s);
            }

            @Override
            public void onEnterRoom(long result) {
                super.onEnterRoom(result);
                if (listener != null) listener.enterRoom(result);
            }

            @Override
            public void onExitRoom(int i) {
                super.onExitRoom(i);
            }

            @Override
            public void onRemoteUserEnterRoom(String userId) {
                super.onRemoteUserEnterRoom(userId);

            }

            @Override
            public void onRemoteUserLeaveRoom(String userId, int reason) {
                super.onRemoteUserLeaveRoom(userId, reason);

            }

            @Override
            public void onStartPublishing(int errCode, String errMsg) {
                super.onStartPublishing(errCode, errMsg);
                if (listener != null) listener.publishStreamStateUpdate("",errCode,errMsg);
            }

            @Override
            public void onUserVoiceVolume(ArrayList<TRTCCloudDef.TRTCVolumeInfo> userVolumes, int i) {
                super.onUserVoiceVolume(userVolumes, i);
                if (listener != null) listener.soundLevelUpdateTencent(userVolumes, i);
            }

            @Override
            public void onUserAudioAvailable(String userId, boolean isVideoAvailable) {
                super.onUserAudioAvailable(userId, isVideoAvailable);
                /**
                 * 遠(yuǎn)端用戶開啟/關(guān)閉了麥克風(fēng)
                 * userId 遠(yuǎn)端用戶ID
                 * isVideoAvailable true:遠(yuǎn)端用戶打開麥克風(fēng)  false:遠(yuǎn)端用戶關(guān)閉麥克風(fēng)
                 */
            }

            @Override
            public void onNetworkQuality(TRTCCloudDef.TRTCQuality trtcQuality, ArrayList<TRTCCloudDef.TRTCQuality> arrayList) {
                super.onNetworkQuality(trtcQuality, arrayList);
                if (TRTCCloudDef.TRTC_QUALITY_Bad == trtcQuality.quality
                        || TRTCCloudDef.TRTC_QUALITY_Vbad == trtcQuality.quality
                        || TRTCCloudDef.TRTC_QUALITY_Down == trtcQuality.quality) {
                    if (TRTCCloudDef.TRTC_QUALITY_Down == trtcQuality.quality) {
                        if (listener != null) listener.networkQuality(true);
                    } else {
                        if (listener != null) listener.networkQuality(false);
                    }
                }
            }
        });
    }

    @Override
    public void setMicMute(boolean isMute) {
        getSDKEngine().muteLocalAudio(isMute);
    }

    @Override
    public void setHandsFree(boolean isHandsFree) {
        if (isHandsFree) {
            getSDKEngine().setAudioRoute(TRTCCloudDef.TRTC_AUDIO_ROUTE_SPEAKER);
        } else {
            getSDKEngine().setAudioRoute(TRTCCloudDef.TRTC_AUDIO_ROUTE_EARPIECE);
        }
    }

    @Override
    public void setMuteAllAudio(boolean mute) {
        getSDKEngine().muteAllRemoteAudio(mute);
    }

    @Override
    public void startPublishingStream(String streamId, boolean openMic) {
        startLocalAudio();
        getSDKEngine().startPublishing(streamId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG);
        setMicMute(!openMic);
    }

    @Override
    public void stopPublishingStream(String streamId) {
        stopLocalAudio();
        getSDKEngine().stopPublishing();
    }

    @Override
    public void stopPlayAllVideo(boolean open) {
        if (open) {

        } else {
            getSDKEngine().stopAllRemoteView();
        }
    }

    @Override
    public void enableAudioSoundLevelMonitor(boolean enable) {
        getSDKEngine().enableAudioVolumeEvaluation(enable ? 400 : 0);
    }
}

ZEGOsdk:

public class TxTRTCZego extends TxTRTCInterface {
    private final String Zego_Login_RoomId = "Zego_Login_RoomId";//登錄房間的ID
    private ZegoMediaPlayer mBGMMediaPlayer, mSoundEffectMediaPlayer;
    private int mBGMMediaPlayerIndex = -1, mSoundEffectMediaPlayerIndex = -1;
    private TxTRTCMusicListener mMusicListener;
    private TxTRTCListener mTRTCListener;

    public TxTRTCZego() {
        initSDK();
    }

    @Override
    public void initSDK() {
        if (0 == TxUserControl.getInstance().getUserZegoAppID()
                || TextUtils.isEmpty(TxUserControl.getInstance().getUserZegoSign())) return;
        if (ZegoExpressEngine.getEngine() == null) {
            ZegoEngineConfig engineConfig = new ZegoEngineConfig();
            engineConfig.advancedConfig.put("audio_device_mode", "4");
            engineConfig.advancedConfig.put("init_domain_name", TxUserControl.getInstance().getUserZegoAppUrl());
            engineConfig.advancedConfig.put("prep_high_pass_filter", "false");//高通濾波器
            ZegoExpressEngine.setEngineConfig(engineConfig);

            ZegoEngineProfile profile = new ZegoEngineProfile();
            profile.appID = TxUserControl.getInstance().getUserZegoAppID();
            profile.application = (Application) TxUiUtils.getContext();
            profile.appSign = TxUserControl.getInstance().getUserZegoSign();
            profile.scenario = ZegoScenario.GENERAL;
            ZegoExpressEngine.createEngine(profile, new IZegoEventHandler() {
                @Override
                public void onRoomStreamUpdate(String roomID, ZegoUpdateType updateType, ArrayList<ZegoStream> streamList, JSONObject extendedData) {
                    super.onRoomStreamUpdate(roomID, updateType, streamList, extendedData);
                    if (updateType == ZegoUpdateType.ADD) {
                        for (ZegoStream zegoStream : streamList) {
                            startPlayingStream(zegoStream.streamID, roomID);
                            TxWriteLogSDCard.writeLog("即構(gòu)Zego--", "開始拉流:" + roomID + "-------" + zegoStream.streamID, null);
                        }
                    } else if (updateType == ZegoUpdateType.DELETE) {// callback in UIThread
                        for (ZegoStream zegoStream : streamList) {
                            stopPlayingStream(zegoStream.streamID);
                            TxWriteLogSDCard.writeLog("即構(gòu)Zego--", "停止拉流:" + roomID + "-------" + zegoStream.streamID, null);
                        }
                    }

                }


                @Override
                public void onPublisherStateUpdate(String streamID, ZegoPublisherState state, int errorCode, JSONObject extendedData) {
                    super.onPublisherStateUpdate(streamID, state, errorCode, extendedData);
                    if (mTRTCListener != null)
                        mTRTCListener.publishStreamStateUpdate(streamID, errorCode, "");

                }

                @Override
                public void onCapturedSoundLevelUpdate(float soundLevel) {
                    super.onCapturedSoundLevelUpdate(soundLevel);
                    if (mTRTCListener != null) mTRTCListener.soundLevelUpdateZegoMine(soundLevel);
                }

                @Override
                public void onRemoteSoundLevelUpdate(HashMap<String, Float> soundLevels) {
                    super.onRemoteSoundLevelUpdate(soundLevels);
                    if (mTRTCListener != null) mTRTCListener.soundLevelUpdateZegoOther(soundLevels);

                }

                @Override
                public void onRoomStateUpdate(String roomID, ZegoRoomState state, int errorCode, JSONObject extendedData) {
                    super.onRoomStateUpdate(roomID, state, errorCode, extendedData);
                    if (mTRTCListener != null)
                        mTRTCListener.roomStateUpdateZego(roomID, state, errorCode);
                }
            });
            if (ZegoExpressEngine.getEngine() != null) {
                ZegoExpressEngine.getEngine().enableAEC(true);//開/關(guān)回聲消除
                ZegoExpressEngine.getEngine().enableHeadphoneAEC(false);//是否在使用耳機時開啟回聲消除
                ZegoExpressEngine.getEngine().enableAGC(false);//音頻采集自動增益
                ZegoExpressEngine.getEngine().enableANS(true);//音頻采集噪聲抑制
            }
        }
    }

    public ZegoExpressEngine getSDKEngine() {
        initSDK();
        return ZegoExpressEngine.getEngine();
    }

    @Override
    public void loginRoom(String roomId, boolean video, String quality) {
        if (getSDKEngine() == null) return;
        try {
            ZegoAudioConfig audioConfig = new ZegoAudioConfig();
            if ("1".equals(quality)) {
                audioConfig.bitrate = 192;
            } else {
                audioConfig.bitrate = 128;
            }
            audioConfig.channel = ZegoAudioChannel.STEREO;
            audioConfig.codecID = ZegoAudioCodecID.NORMAL2;
            getSDKEngine().setAudioConfig(audioConfig);

            TxWriteLogSDCard.writeLog("Zego--", "LoginRoom--" + roomId, null);
            String lastRoomId = null;
            if (Hawk.contains(Zego_Login_RoomId)) {
                lastRoomId = Hawk.get(Zego_Login_RoomId, "");
            }
            if (!TextUtils.isEmpty(lastRoomId) && !lastRoomId.equals(roomId)) {
                getSDKEngine().logoutRoom(lastRoomId);
            }

            ZegoRoomConfig config = new ZegoRoomConfig();
            config.isUserStatusNotify = true;
            Hawk.put(Zego_Login_RoomId, roomId);

            getSDKEngine().loginRoom(roomId, new ZegoUser(TxUserControl.getInstance().getUserId(),
                    TxUserControl.getInstance().getUserName()), config);
        } catch (Exception e) {

        }
    }

    @Override
    public void logoutRoom(String roomId) {
        if (getSDKEngine() == null) return;
        getSDKEngine().logoutRoom();
        Hawk.delete(Zego_Login_RoomId);

        stopPublishingStream(roomId);
        getSDKEngine().stopPreview();
    }

    @Override
    public void setUpSeat(String roomId) {
//        startPublishingStream(roomId,false);
    }

    @Override
    public void setDownSeat(String roomId) {
        setMicMute(true);
        stopAudioPlay(Audio_BGMId);
        stopPublishingStream(roomId);

    }

    @Override
    public void destroyEngine(String roomId) {
        if (ZegoExpressEngine.getEngine() != null) {
            if (!TextUtils.isEmpty(roomId)) {
                logoutRoom(roomId);
                stopPublishingStream(roomId);
                getSDKEngine().stopPreview();
            }
            if (mBGMMediaPlayer != null) {
                getSDKEngine().destroyMediaPlayer(mBGMMediaPlayer);
            }
            if (mSoundEffectMediaPlayer != null) {
                getSDKEngine().destroyMediaPlayer(mSoundEffectMediaPlayer);
            }
        }
        Hawk.delete(Zego_Login_RoomId);
        setAudioEffectListener(0, null);
        setCallSDKListener(null);
        ZegoExpressEngine.destroyEngine(new IZegoDestroyCompletionCallback() {
            @Override
            public void onDestroyCompletion() {

            }
        });
    }

    /**
     * 獲取背景音樂管理器
     *
     * @return
     */
    private ZegoMediaPlayer getAudioManager(int id) {
        if (Audio_SoundEffectId == id) {
            if (mSoundEffectMediaPlayer == null) {
                synchronized (TxTRTCTencent.class) {
                    if (mSoundEffectMediaPlayer == null)
                        mSoundEffectMediaPlayer = getSDKEngine().createMediaPlayer();
                    mSoundEffectMediaPlayer.muteLocal(false);//可以控制本地靜音播放齿桃。
                    mSoundEffectMediaPlayer.enableAux(true);//可以將文件的聲音混入正在推的流中。
                    mSoundEffectMediaPlayer.setEventHandler(new MyIZegoMediaPlayerEventHandler());
                    mSoundEffectMediaPlayer.setVolume(99);
                    mSoundEffectMediaPlayerIndex = mSoundEffectMediaPlayer.getIndex();
                }
            }
            return mSoundEffectMediaPlayer;
        } else {
            if (mBGMMediaPlayer == null) {
                synchronized (TxTRTCTencent.class) {
                    if (mBGMMediaPlayer == null)
                        mBGMMediaPlayer = getSDKEngine().createMediaPlayer();
                    mBGMMediaPlayer.muteLocal(false);//可以控制本地靜音播放煮盼。
                    mBGMMediaPlayer.enableAux(true);//可以將文件的聲音混入正在推的流中短纵。
                    mBGMMediaPlayer.setEventHandler(new MyIZegoMediaPlayerEventHandler());
                    mBGMMediaPlayerIndex = mBGMMediaPlayer.getIndex();
                }
            }
            return mBGMMediaPlayer;
        }
    }

    @Override
    public void setAudioEffectListener(int id, TxTRTCMusicListener listener) {
        mMusicListener = listener;
    }

    @Override
    public void startAudioPlay(int id, String path) {
        getAudioManager(id).stop();
        getAudioManager(id).loadResource(path, new IZegoMediaPlayerLoadResourceCallback() {
            @Override
            public void onLoadResourceCallback(int errorCode) {
                if (errorCode == 0) {
                    getAudioManager(id).start();
                } else {
                    if (Audio_SoundEffectId == id) {
                        if (mMusicListener != null) mMusicListener.playEnd(Audio_SoundEffectId);
                    } else {
                        if (mMusicListener != null) mMusicListener.playError(Audio_BGMId);
                    }
                }
            }
        });
    }

    @Override
    public void resumeAudioPlay(int id) {
        getAudioManager(id).resume();
    }

    @Override
    public void pauseAudioPlay(int id) {
        getAudioManager(id).pause();
    }

    @Override
    public void stopAudioPlay(int id) {
        getAudioManager(id).stop();
    }

    @Override
    public void setAudioVoiceCaptureVolume(int progress) {
        getSDKEngine().setCaptureVolume(progress * 2);
    }

    @Override
    public void setAudioMusicVolume(int id, int progress) {
        getAudioManager(id).setVolume(progress * 2);
    }

    @Override
    public void setCallSDKListener(TxTRTCListener listener) {
        mTRTCListener = listener;
    }

    @Override
    public void setMicMute(boolean isMute) {
        getSDKEngine().muteMicrophone(isMute);
    }

    @Override
    public void setHandsFree(boolean isHandsFree) {
        getSDKEngine().setAudioRouteToSpeaker(isHandsFree);
    }

    @Override
    public void setMuteAllAudio(boolean mute) {
        getSDKEngine().muteSpeaker(mute);
    }

    @Override
    public void startPublishingStream(String streamId, boolean openMic) {
        setMicMute(!openMic);
        getSDKEngine().startPublishingStream(streamId);
        TxWriteLogSDCard.writeLog("Zego--", "startPublishingStream--" + streamId, null);
    }

    @Override
    public void stopPublishingStream(String streamId) {
        setMicMute(true);
        getSDKEngine().stopPublishingStream();
    }

    @Override
    public void stopPlayAllVideo(boolean open) {
        getSDKEngine().muteSpeaker(!open);
    }

    @Override
    public void enableAudioSoundLevelMonitor(boolean enable) {
        getSDKEngine().startSoundLevelMonitor(enable ? 400 : 0);
    }

    /**
     * 開始拉流
     *
     * @param streamId
     */
    private void startPlayingStream(String streamId, String roomId) {
        try {
            if (!TextUtils.isEmpty(roomId)) {
                ZegoPlayerConfig config = new ZegoPlayerConfig();
                config.roomID = roomId;
                getSDKEngine().startPlayingStream(streamId, config);
            } else {
                getSDKEngine().startPlayingStream(streamId);
            }
        } catch (Exception e) {
        }
    }

    /**
     * 停止拉流
     *
     * @param streamId
     */
    private void stopPlayingStream(String streamId) {
        try {
            getSDKEngine().stopPlayingStream(streamId);
        } catch (Exception e) {
        }
    }

    private class MyIZegoMediaPlayerEventHandler extends IZegoMediaPlayerEventHandler {

        private static final String TAG = "MyIZegoExpressMediaplay";

        @Override
        public void onMediaPlayerStateUpdate(ZegoMediaPlayer mediaPlayer, ZegoMediaPlayerState state, int errorCode) {
            // 本回調(diào)在UI線程被回調(diào), 開發(fā)者可以在此進行UI的變化, 例如播放按鈕的變化
            if (0 == errorCode) {
                if (state == ZegoMediaPlayerState.PLAYING) {//播放中
                    if (mMusicListener != null)
                        mMusicListener.playing(mBGMMediaPlayerIndex == mediaPlayer.getIndex() ? Audio_BGMId : Audio_SoundEffectId);
                } else if (state == ZegoMediaPlayerState.PAUSING) {//暫停播放
                    if (mBGMMediaPlayerIndex == mediaPlayer.getIndex()) {
                        if (mMusicListener != null) mMusicListener.playPause(Audio_BGMId);
                    } else {
                        if (mMusicListener != null) mMusicListener.playEnd(Audio_SoundEffectId);
                    }
                } else if (state == ZegoMediaPlayerState.PLAY_ENDED) {//播放結(jié)束
                    if (mMusicListener != null)
                        mMusicListener.playEnd(mBGMMediaPlayerIndex == mediaPlayer.getIndex() ? Audio_BGMId : Audio_SoundEffectId);
                } else {//不在播放
                    if (mMusicListener != null)
                        mMusicListener.playEnd(mBGMMediaPlayerIndex == mediaPlayer.getIndex() ? Audio_BGMId : Audio_SoundEffectId);
                }
            } else {
                if (mMusicListener != null)
                    mMusicListener.playError(mBGMMediaPlayerIndex == mediaPlayer.getIndex() ? Audio_BGMId : Audio_SoundEffectId);
            }
            TxWriteLogSDCard.writeLog(TAG, "音樂播放回調(diào) onMediaPlayerStateUpdate:" + state + ";" + errorCode);
        }

        @Override
        public void onMediaPlayerNetworkEvent(ZegoMediaPlayer mediaPlayer, ZegoMediaPlayerNetworkEvent networkEvent) {
            // 本回調(diào)在UI線程被回調(diào), 開發(fā)者可以在此進行UI的變化, 例如網(wǎng)絡(luò)不好的情況做友好的提示
        }

        @Override
        public void onMediaPlayerPlayingProgress(ZegoMediaPlayer mediaPlayer, long millisecond) {
            // 本回調(diào)在UI線程被回調(diào), 開發(fā)者可以在此進行UI的變化, 例如進度條的變化
            if (mBGMMediaPlayerIndex == mediaPlayer.getIndex()) {
                if (mMusicListener != null)
                    mMusicListener.playProgress(millisecond, mediaPlayer.getTotalDuration());
            }
        }
    }
}

??3.替換內(nèi)核 ,只需要單例中在初始化sdk的方法做判斷就行
image.png

好了僵控,大致就是這樣了

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末香到,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子报破,更是在濱河造成了極大的恐慌悠就,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件泛烙,死亡現(xiàn)場離奇詭異理卑,居然都是意外死亡,警方通過查閱死者的電腦和手機蔽氨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門藐唠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人鹉究,你說我怎么就攤上這事宇立。” “怎么了自赔?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵妈嘹,是天一觀的道長。 經(jīng)常有香客問我绍妨,道長润脸,這世上最難降的妖魔是什么柬脸? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮毙驯,結(jié)果婚禮上倒堕,老公的妹妹穿的比我還像新娘。我一直安慰自己爆价,他們只是感情好垦巴,可當(dāng)我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著铭段,像睡著了一般骤宣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上序愚,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天憔披,我揣著相機與錄音,去河邊找鬼展运。 笑死活逆,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的拗胜。 我是一名探鬼主播蔗候,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼埂软!你這毒婦竟也來了锈遥?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤勘畔,失蹤者是張志新(化名)和其女友劉穎所灸,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體炫七,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡爬立,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了万哪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片侠驯。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖奕巍,靈堂內(nèi)的尸體忽然破棺而出吟策,到底是詐尸還是另有隱情,我是刑警寧澤的止,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布檩坚,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏匾委。R本人自食惡果不足惜拖叙,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望剩檀。 院中可真熱鬧憋沿,春花似錦、人聲如沸沪猴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽运嗜。三九已至,卻和暖如春悯舟,著一層夾襖步出監(jiān)牢的瞬間担租,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工抵怎, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留奋救,地道東北人。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓反惕,卻偏偏與公主長得像尝艘,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子姿染,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容