**注意:即構新版需要進行模塊級替換,即使用美顏Demo里的CustomVideoCapture模塊替換即構Demo的同名模塊。**
**1.初始化MHSDK**
**找到ZegoApplication.java文件,在****onCreate****方法中添加以下代碼:**
```
MHSDK.getInstance().init(this," ");
```
**2.****?初始化美顏界面**
**找到MHCaptureRenderActivity.java文件,繼承****DefaultBeautyEffectListener****接口,添加以下變量:**
```
private Handler mHandler;
private AlertDialog dialog;
private RelativeLayout beautyContainer;
private MHBeautyManager mhBeautyManager;
private BaseBeautyViewHolder beautyViewHolder;
private boolean isResume;
private int retryCount;
private Thread beautyThread;
private boolean isRended;
private int mDeviceLevel;
private ProgramTextureOES mProgramTextureOES;
private ProgramTexture2d mProgramTexture2d;
private ProgramTexture2d mProgramTexture2d1;
private int[] bindingFrameBuffer = new int[1];
private int[] bindingRenderBuffer = new int[1];
private int[] viewPoint = new int[4];
private int vertexAttribEnableArraySize = 5;
private ArrayList vertexAttribEnableArray;
```
**添加以下****方法****:**
```
private void initBeautyView() {
????beautyContainer = findViewById(R.id.beauty_view_container);
????mHandler = new Handler(getMainLooper());
????try {
????????mDeviceLevel = ThemisUtil.judgeDeviceLevel(this);
????}catch (Exception e){
????????e.printStackTrace();
????????Log.e(TAG, "judgeDeviceLevel error");
????}
????if (MHSDK.getInstance().isVerEnd()) {
????????setBeautyView();
????} else {
????????if (beautyThread != null) {
????????????beautyThread.interrupt();
????????????beautyThread = null;
????????}
????????beautyThread = new BeautyThread(this);
????????beautyThread.start();
????}
}
private void initMHBeautyManager(){
????if (mhBeautyManager == null) {
????????mhBeautyManager = new MHBeautyManager(this,true);
????????mhBeautyManager.setMinFaceSize(120);
????????mhBeautyManager.setBeautyDataModel(BeautyDataModel.getInstance());
????????if (beautyViewHolder != null) {
????????????beautyViewHolder.setMhBeautyManager(mhBeautyManager);
????????}
????}
}
private void setBeautyView() {
????LogManager.getInstance().writeData("MainActivity_setBeautyView_SDKVersion=" + MHSDK.getInstance().getVer());
????if (!MHSDK.getInstance().isVerifyAccess()) {
????????if (retryCount < 10) {
????????????showRetryDialog();
????????} else {
????????????showExitDialog();
????????????return;
????????}
????}
????if (beautyViewHolder != null) {
????????beautyViewHolder.release();
????????beautyViewHolder = null;
????}
????beautyViewHolder = BeautyViewHolderFactory.getBeautyViewHolder(getApplicationContext(), beautyContainer);
????beautyViewHolder.show();
????beautyViewHolder.setEffectListener(this);
????beautyViewHolder.setVisibleListener(new IBeautyViewHolder.VisibleListener() {
????????@Override
????????public void onVisibleChanged(boolean visible) {
????????????if (!visible) {
????????????????beautyViewHolder.show();
????????????}
????????}
????});
????initMHBeautyManager();
}
static class DiaLogListener implements DialogInterface.OnClickListener {
????WeakReference activityWeakReference;
????DiaLogListener(MHCaptureRenderActivity activity) {
????????this.activityWeakReference = new WeakReference<>(activity);
????}
????@Override
????public void onClick(DialogInterface dialog, int which) {
????????MHCaptureRenderActivity activity = activityWeakReference.get();
????????if (activity == null) return;
????????switch (which) {
????????????case -1:
????????????????dialog.cancel();
????????????????activity.finish();
????????????????break;
????????????case -2:
????????????????dialog.cancel();
????????????????break;
????????}
????}
}
static class SDKDialogListener implements DialogInterface.OnClickListener {
????WeakReference activityWeakReference;
????SDKDialogListener(MHCaptureRenderActivity activity) {
????????this.activityWeakReference = new WeakReference<>(activity);
????}
????@Override
????public void onClick(DialogInterface dialog, int which) {
????????MHCaptureRenderActivity activity = activityWeakReference.get();
????????if (activity == null) return;
????????switch (which) {
????????????case -1:
????????????????activity.retryCount++;
????????????????MHSDK.getInstance().clearVerNote();
????????????????MHSDK.getInstance().verify("");
????????????????activity.initBeautyView();
????????????????dialog.cancel();
????????????????break;
????????????case -2:
????????????????dialog.cancel();
????????????????break;
????????}
????}
}
```
//由于demo進入應用直接進入美顏界面,為了防止授權校驗未完成而一直顯示標準版界面,需要等授權校驗完成后初始化對應的美顏界面(延遲1秒或者按下面處理)
```
static class BeautyThread extends Thread {
????WeakReference mainActivityWeakReference;
????BeautyThread(MHCaptureRenderActivity MHCaptureRenderActivity) {
????????this.mainActivityWeakReference = new WeakReference<>(MHCaptureRenderActivity);
????}
????@Override
????public void run() {
????????while (mainActivityWeakReference.get() != null && !MHSDK.getInstance().isVerEnd()) {
????????????if (isInterrupted()) return;
????????????try {
????????????????Thread.sleep(200);
????????????} catch (InterruptedException e) {
????????????????e.printStackTrace();
????????????}
????????}
????????final MHCaptureRenderActivity activity = mainActivityWeakReference.get();
????????if (activity != null) {
????????????activity.mHandler.post(new Runnable() {
????????????????@Override
????????????????public void run() {
????????????????????activity.setBeautyView();;
????????????????}
????????????});
????????}
????}
}
private void showRetryDialog() {
????if (dialog != null) {
????????dialog.cancel();
????}
????SDKDialogListener diaLogListener = new SDKDialogListener(this);
????dialog = new AlertDialog.Builder(this)
????????????.setTitle("提示")
????????????.setMessage("資源獲取失敗,請檢查網絡")
????????????.setCancelable(false)
????????????.setPositiveButton("確定", diaLogListener)
????????????.create();
????dialog.show();
}
private void showExitDialog() {
????if (dialog != null) {
????????dialog.cancel();
????}
????DiaLogListener diaLogListener = new DiaLogListener(this);
????dialog = new AlertDialog.Builder(this)
????????????.setTitle("提示")
????????????.setMessage("資源獲取失敗,請檢查網絡并退出重試")
????????????.setCancelable(false)
????????????.setPositiveButton("確定", diaLogListener)
????????????.create();
????dialog.show();
}
@Override
public void onFilterChanged(FilterBean filterBean) {
????if (mhBeautyManager == null) {
????????return;
????}
????FilterEnum filterEnum = filterBean.getFilterEnum();
????if (filterEnum == FilterEnum.PRO_FILTER) {
????????mhBeautyManager.changeDynamicFilter(filterBean.getmFilterName());
????} else {
????????Bitmap lookupBitmap = BitmapUtil.getFilterBitmap(this,filterEnum);
????????mhBeautyManager.setFilter(lookupBitmap);
????}
}
@Override
public void onMeiBaiChanged(int progress) {
????if (mhBeautyManager != null) {
????????mhBeautyManager.setSkinWhiting(progress);
????}
}
@Override
public void onMoPiChanged(int progress) {
????if (mhBeautyManager != null) {
????????mhBeautyManager.setSkinSmooth(progress);
????}
}
@Override
public void onFengNenChanged(int progress) {
????if (mhBeautyManager != null) {
????????mhBeautyManager.setSkinTenderness(progress);
????}
}
@Override
public void onBeautyOrigin() {
????if (mhBeautyManager != null) {
????????mhBeautyManager.setSkinWhiting(0);
????????mhBeautyManager.setSkinSmooth(0);
????????mhBeautyManager.setSkinTenderness(0);
????}
}
public void saveOpenGLState() {
????// 獲取當前綁定的FrameBuffer
????glGetIntegerv(GL_FRAMEBUFFER_BINDING, bindingFrameBuffer, 0);
????// 獲取當前綁定的RenderBuffer
????glGetIntegerv(GL_RENDERBUFFER_BINDING, bindingRenderBuffer, 0);
????// 獲取viewpoint
????glGetIntegerv(GL_VIEWPORT, viewPoint, 0);
????// 獲取頂點數據
????if (vertexAttribEnableArray == null){
????????vertexAttribEnableArray = new ArrayList<>();
????}
????vertexAttribEnableArray.clear();
????for (int x = 0; x < vertexAttribEnableArraySize; x++) {
????????int[] vertexAttribEnable = new int[1];
????????glGetVertexAttribiv(x, GL_VERTEX_ATTRIB_ARRAY_ENABLED, vertexAttribEnable, 0);
????????if (vertexAttribEnable[0] != 0) {
????????????vertexAttribEnableArray.add(x);
????????}
????}
}
public void restoreOpenGLState() {
????// 還原當前綁定的FrameBuffer
????glBindFramebuffer(GL_FRAMEBUFFER, bindingFrameBuffer[0]);
????// 還原當前綁定的RenderBuffer
????glBindRenderbuffer(GL_RENDERBUFFER, bindingRenderBuffer[0]);
????// 還原viewpoint
????glViewport(viewPoint[0], viewPoint[1], viewPoint[2], viewPoint[3]);
????// 還原頂點數據
????for (int x = 0; x < vertexAttribEnableArray.size(); x++) {
????????glEnableVertexAttribArray(vertexAttribEnableArray.get(x));
????}
}
```
**在OnCreate調用initBeautyView()方法**
```
initBeautyView();
```
**設置ZegoCustomVideoCaptureConfig的****bufferType****為ZegoVideoBufferType.GL_TEXTURE_2D;**
```
videoCaptureConfig.bufferType = ZegoVideoBufferType.GL_TEXTURE_2D;
mSDKEngine.enableCustomVideoCapture(true, videoCaptureConfig, ZegoPublishChannel.MAIN);
```
**在doPublish()里面設置碼率為****1500**
```
zegoVideoConfig.setVideoBitrate(1500);
```
**在****onResume****里面調用****initMHBeautyManager****方法**
```
initMHBeautyManager();
```
**重要,自定義onDrawFrame方法,代碼如下**
```
@Override
public int onDrawFrame(byte[] nv21Byte, int texId, int cameraWidth, int cameraHeight, int cameraRotation, float[] mvpMatrix, float[] texMatrix, long timeStamp) {
????saveOpenGLState();
????int tex2D = texId;
????if (mProgramTextureOES == null) {
????????mProgramTextureOES = new ?ProgramTextureOES();
????}
????tex2D = mProgramTextureOES.getTexId(tex2D,cameraWidth,cameraHeight);
????if(mProgramTexture2d==null){
????????mProgramTexture2d = new ProgramTexture2d().setAngle(90).init();
????????mProgramTexture2d1 = new ProgramTexture2d().setAngle(90).init();
????}
????int ?newTex2D = mProgramTexture2d.getTexId(tex2D,cameraHeight,cameraWidth);
????if (mhBeautyManager!=null) {
????????newTex2D = ?mhBeautyManager.render(newTex2D,cameraHeight,cameraWidth,4,1);
????}
????long now;
????if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
????????now = SystemClock.elapsedRealtime();
????} else {
????????now = TimeUnit.MILLISECONDS.toMillis(SystemClock.elapsedRealtime());
????}
????mSDKEngine.sendCustomVideoCaptureTextureData(newTex2D,cameraHeight,cameraWidth,now);
????newTex2D = mProgramTexture2d1.getTexId(newTex2D,cameraWidth,cameraHeight);
????restoreOpenGLState();
????return newTex2D;
}
```
**在****onSurfaceDestroy****方法里銷毀****MHBeautyManager**
```
@Override
public void onSurfaceDestroy() {
????if (mhBeautyManager != null) {
????????mhBeautyManager.destroy();
????????mhBeautyManager = null;
????}
}
```
- 一、產品簡介
- 1.功能說明
- 2.平臺支持
- 3.官方鏈接
- 二、集成指引
- android集成指引
- 1.概述
- 2.接入說明
- 3.詳細步驟
- 4.使用步驟
- 1.騰訊移動直播
- 2.金山云直播
- 3.三體云直播
- 4.阿里云直播
- 5.七牛云直播
- 6.七牛短視頻
- 7.Movieous短視頻
- 8.即構直播
- 9.騰訊實時音視頻
- 10.網易視頻云
- 11.即構實時視頻
- 12.融云視頻通話
- 13.聲網視頻互動直播
- 14.聲網視頻通話
- 15.即構新版實時音視頻
- 16.不同直播SDK設置基礎美顏方式
- 5.新版美狐集成
- iOS集成指引
- 1.申請MH授權Key
- 2.檢查SDK資源
- 3.配置工程
- 4.使用MHUI
- 5. 騰訊直播SDK美顏
- 6.TTT 直播SDK美顏
- 7.TTT 實時互動直播
- 8.金山直播SDK 美顏
- 9.七牛直播SDK 美顏
- 10.七牛短視頻SDK 美顏
- 11.Movieous短視頻
- 12.Zego(即構)直播SDK 美顏
- 13. Zego(即構)實時音視頻SDK 美顏
- 14. 網易直播SDK美顏
- 15. 騰訊互動直播SDK美顏
- 16. 騰訊實時音視頻
- 17.融云實時音視頻
- 18.聲網視頻通話
- 19.聲網直播
- 20. 騰訊短視頻錄制
- 21.阿里直播 SDK 美顏
- 22.阿里音視頻
- 2.4.X版本安卓集成指引
- 1.詳細步驟
- 2.云直播平臺具體接入
- 1.騰訊移動直播
- 2.阿里云音視頻
- 三、MHSDK美顏相關接口部分
- andorid美顏相關接口文檔說明
- 美顏相關接口說明文檔
- 設置濾鏡
- 設置貼紙
- iOS美顏相關接口說明文檔
- 1.初始化
- 2.美顏相關接口說明文檔
- 3.美顏功能說明
- 四、常見問題
- android常見問題
- 1.認證失敗原因
- 2.調用美型、貼紙、特效、哈哈鏡沒有效果
- 3.MHBeautyManager的特別聲明
- 4.使用MHUI的注意事項
- 5.卡頓問題
- 6.閃退問題
- 7. 貼紙無法下載
- 8.andriodX(騰訊云)環境集成問題:
- 9.導入新的sdk出現亂碼
- 10.彈出的UI有陰影效果
- 11.安卓10出現獲取網絡資源失敗請檢查網絡
- 12.美狐可以記錄設置的各種參數嗎?
- 13.(七牛云)替換sdk畫面上下顛倒
- 14.貼紙可以自定義嗎
- 15.您這邊可以短視頻錄制嗎
- 16.MHSDK必須本地依賴嗎
- 17.找不到某個方法
- 18.環信不顯示自己的頭像框
- 19.如何取消特效
- 20.水印沒有找到
- 21.聲網視頻通話大小屏切換問題
- iOS常見問題
- 1.iOS認證失敗原因
- 2.美顏無效果
- 3.貼紙下載失敗
- 4.貼紙可下載,無效果
- 5. IPA processing failed/上架打包失敗
- 6.存儲美顏默認數據
- 7.如果遇到了Failed to create IOSurface image (texture)
- 8.opencv.framework沖突
- 五、聯系方式