涂图

  • 首页
  • 解决方案
    • 拍照和图片编辑
    • 视频录制和后期编辑
    • 模板视频
    • 人像美颜
    • 人脸特效
    • 滤镜特效
    • 贴纸特效
  • API服务
    • 人像服务
    • 视频融合
    • 人脸云
    • 在线滤镜
  • 客户案例
  • 下载
  • 文档
  • 关于我们
  • 控制台
  • 一、新手上路
  • 控制台操作说明
    • 控制台使用说明
    • 自定义资源上传说明
  • 二、SDK 文档
  • 图像 SDK
    • 产品说明
      • 产品指南
      • 性能测试报告
    • iOS 文档
      • 快速开始
      • 安装与更新
      • 集成向导
      • 相机组件的使用
      • 相册组件的使用
      • 照片美化组件的使用
      • 主题包基础使用
      • 自定义滤镜
      • 自定义贴纸
      • 自定义界面
      • 自定义 ProgressHUD 提示框(2.0.0~3.2.7)
      • 自定义 ProgressHUD 提示框
      • API 文档
      • 致谢
    • Android 文档
      • 快速开始
      • 安装与更新
      • 集成向导
      • 相机组件的使用
      • 照片美化组件的使用
      • 头像设置组件的使用
      • 多选相册组件的使用
      • 主题包基础使用
      • 自定义贴纸
      • 自定义滤镜
      • 自定义界面
      • 自定义进度信息提示框
      • 自定义 Activity 打开相机
      • API 文档
      • 致谢
    • iOS 技术问题
      • 「Incorrenct app key」
      • 更换滤镜效果图
      • 导航栏与状态栏
      • 组件中使用部分滤镜
      • Cocoapods 相关问题
      • 图片尺寸变化
      • Photos.framework 相关错误
      • 多包名发布
      • GPUImage 的相关错误
      • TuSDKTSALAsset 转换系统对象
      • 滤镜无法显示名称
      • 获取相机的点击事件
    • Android 技术问题
      • Incorrenct app key
      • 重复引用包
      • Recyclerview 库缺失
      • 方法数超出 65536 限制
      • 传入图片路径
      • 指定裁剪比例
      • 指定相册每行列数
      • 禁用相册自动跳转
      • 如何使用部分滤镜?
      • 代码混淆
      • TuSDK 使用的依赖库
      • 多渠道打包
      • 设置相机输出尺寸
      • 相机横屏设置
      • 自定义照片美化组件各功能模块效果默认参数值
    • 拼图设计
      • 拼图模板导出
    • 版本更新日志
      • iOS 版本更新日志
      • Android 更新日志
  • 视频剪辑 SDK
    • 产品说明
      • 产品指南
    • iOS文档
      • TuSDK Video Editor iOS 接入文档
    • Android文档
      • TuSDK Video Editor Android 接入文档
    • 版本更新日志
      • iOS 版本更新日志
      • Android 版本更新日志
  • 流处理(特效相机) SDK
    • 产品说明
      • 产品指南
    • iOS 文档
      • TuSDK特效相机接入文档-iOS
      • TuSDK直播特效接入说明-iOS
    • Android 文档
      • TuSDK特效相机接入文档-Android
      • TuSDK直播特效接入说明-Android
    • 版本更新日志
      • iOS 版本更新日志
      • Android 版本更新日志
  • 视频融合 SDK
    • 产品说明
      • 产品指南
      • 模板管理
    • iOS 文档
      • 快速开始
      • 安装与更新
      • TuSDK EVA 接入说明 2.0
      • API文档
    • Android 文档
      • 快速开始
      • 安装与更新
      • TuSDK EVA 接入说明 (2.0.0+)
      • API 文档
    • 模板设计
      • (新)标准模板设计规范
      • (旧)标准模板设计规范
      • 支持的 AE 功能和属性
      • 动态模板设计规范
    • 模板导出
      • (新)模板导出插件安装
      • (新)模板导出插件使用
      • (旧)模板导出插件安装
      • (旧)模板导出插件使用
      • (旧)模板效果查看器
      • (旧)模板打包规范
    • 版本更新日志
      • iOS 版本更新日志
      • Android 版本更新日志
      • 导出插件版本更新日志
      • 效果查看器更新日志
  • 短视频 SDK
    • 产品说明
      • 产品指南
      • 性能测试报告
    • iOS 文档
      • 快速开始
      • 集成向导
      • 录制相机的使用
      • 视频编辑器的使用
      • 功能 API 的使用
      • API 文档
    • Android 文档
      • 快速开始
      • 集成向导
      • 录制相机的使用
      • 视频编辑器的使用
      • 功能 API 的使用
      • API 文档
    • iOS 技术问题
      • 常见问题
    • Android 技术问题
      • 常见问题
    • 版本更新日志
      • iOS 版本更新日志
      • Android 版本更新日志
  • 三、云服务文档
  • 人像服务
    • 使用文档
      • 快速入门
      • 核心功能
    • API概述
      • API 概述
      • API 文档
    • 常见问题
      • 常见问题
  • 视频融合(云渲染)
    • 使用文档
      • 快速入门
      • 模板管理
    • API概述
      • API概述
      • API 文档
    • 模板设计
      • (新)标准模板设计规范
      • (旧)标准模板设计规范
      • 支持的 AE 功能和属性
      • 动态模板设计规范
    • 模板导出
      • (新)模板导出插件安装
      • (新)模板导出插件使用
      • (旧)模板导出插件安装
      • (旧)模板导出插件使用
      • (旧)模板效果查看器
      • (旧)模板打包规范
    • 常见问题
    • 版本更新日志
      • 导出插件版本更新日志
      • 效果查看器更新日志
  • 人脸云
    • 使用文档
      • 快速入门
      • 核心功能
    • API 概述
      • API 概述
    • 常见问题
      • 常见问题
  • 在线滤镜
    • 使用文档
      • 快速入门
      • 核心功能
      • FILTER API
      • API 错误码表
    • API概述
      • API 概述
    • 常见问题
      • 常见问题
  • 四、综合
  • 涂图隐私协议
  • 用户退出机制
  • 动态贴纸设计规范
  • 美妆贴纸设计规范
  • 云服务账单说明
  • 应用包名与密钥
  • 基础服务开发者升级流程
  • 五、常见问题
  • 常见问题
  • 遇到问题,怎么办?
  • 如何使用贴纸管理、滤镜管理?

第三方推流SDK接入指南

接入准备

  • 使用美颜 sdk 之前需要拿到功能授权文件,以及与授权文件对应的素材
  • 将我们的jar包与so库加入项目,并将对 sdk 的一些封装代码拷贝到项目中,这些代码一般存在于 TuSDKFilterEngineModule 项目中的org.lasque.tubeautysetting下。

腾讯云直播接入指南

回调接口

首先需要调用TXLivePusher对象setVideoProcessListener()方法设置 TXLivePusher.VideoCustomProcessListener接口接收纹理回调

    private TXLivePusher.VideoCustomProcessListener mTuSDKVideoCustomProcessListener = new TXLivePusher.VideoCustomProcessListener() {
        @Override
        public int onTextureCustomProcess(final int textureId, final int width, final int height) {
            if (!LivePipeMediator.getInstance().isReady()){
                // 初始化渲染管线
                    final EGLContext currentContext = EGL14.eglGetCurrentContext();

                    LivePipeMediator pipeMediator = LivePipeMediator.getInstance();
                    pipeMediator.requestInit(this,currentContext);
            }
            if (mResult != null) mResult.release();

            // 纹理处理
            Image out = LivePipeMediator.getInstance().process(textureId,width,height,System.currentTimeMillis());
            mResult = out;
            // 返回处理后的纹理
            return mResult.getGLTexture();
        }

        @Override
        public void onDetectFacePoints(float[] floats) {

        }

        @Override
        public void onTextureDestoryed() {
            // 释放渲染管线
                    LivePipeMediator pipeMediator = LivePipeMediator.getInstance();
                    pipeMediator.release();
                    Engine.getInstance().release();
        }
    };

七牛直播接入指南

通过实现com.qiniu.pili.droid.streaming.StreamingPreviewCallback与com.qiniu.pili.droid.streaming.SurfaceTextureCallback接口,进行TuSDK与七牛SDK之间的纹理信息交互

核心处理

    @Override
    public void onSurfaceCreated() {

        // 初始化渲染管线

        EGLContext currentContext = EGL14.eglGetCurrentContext();

        boolean hasContext = currentContext != EGL14.EGL_NO_CONTEXT;

        mPipe = LivePipeMediator.getInstance();
        mPipe.requestInit(this,hasContext ? currentContext : null);
        mModuleFragment.setFilterPipe(mPipe);


        mRenderPool.submit(new Runnable() {
            @Override
            public void run() {
                mPipe.getGLContext().makeCurrent();
            }
        });
    }

    @Override
    public int onDrawFrame(final int texId, final int texWidth, final int texHeight, final float[] transformMatrix) {
        boolean enable = mEnableProcess;

        mCount++;
        long startTime = System.currentTimeMillis();

        Future<Image> res = mRenderPool.submit(new Callable<Image>() {
            @Override
            public Image call() throws Exception {
                //初始化OES转Texture2D纹理渲染器
                if (mTextureRender == null){
                    mTextureRender = new TextureRender(true);
                    mTextureRender.create(texHeight,texWidth);
                }

                // 初始化Texture2D纹理旋转输出器
                if (mOutputTextureRender == null){
                    mOutputTextureRender = new TextureRender(false);
                    mOutputTextureRender.create(texWidth,texHeight);
                }

                mTextureRender.setSTMatrix(transformMatrix);
                mTextureRender.drawFrame(texId,texHeight,texWidth);
                Image output = mPipe.process(mTextureRender.getTextureID(),texHeight,texWidth,System.currentTimeMillis());
                float[] stMatrixInvert = new float[16];
                Matrix.invertM(stMatrixInvert,0,transformMatrix,0);
                mOutputTextureRender.setSTMatrix(stMatrixInvert);
                mOutputTextureRender.drawFrame(output.getGLTexture(),texWidth,texHeight);
                Image finalOutput = new Image(mOutputTextureRender.getTextureID(),texWidth,texHeight,System.currentTimeMillis());
                output.release();
                return finalOutput;
            }
        });

        try {
            synchronized(this){
                if (mResult != null) mResult.release();
                mResult = res.get();
                mCurrentBuffer = mResult.getBuffer(mCurrentFormat == PLFourCC.FOURCC_I420 ? Image.Format.I420 : Image.Format.NV21);
            }

        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long duration = System.currentTimeMillis() - startTime;
        sum += duration;
        count++;
        return mResult.getGLTexture();
    }


    @Override
    public boolean onPreviewFrame(final byte[] bytes, final int width, final int height, int rotation, final int fmt, long tsInNanoTime) {
        if (mPipe == null &&!mEnableProcess) return false;

        if (mCurrentBuffer == null) return false;

        boolean enable = mEnableProcess;
        if (mPipe != null && enable) {
            if (mCurrentBuffer != null) {
                // 获取处理后的YUV数据
                byte[] bufferClone = mCurrentBuffer.clone();
                System.arraycopy(bufferClone,0,bytes,0,bytes.length);
                return true;
            }
        }
        return false;
    }

声网推流接入指南

目前Android端接入声网推流,无法使用正常的声网采集流程,需要使用自采集模式配合声网旁路推流模式进行实现 详细自采集实现需参照Demo 渲染与推流

public void onDrawFrame()
    {


        if (mSurfaceTexture == null) return;

        // 预备纹理池

        if (isNeedCreateTextures){
            GLES20.glGenTextures(mTexCount, mTextures, 0);

            for (int idx = 0; idx < mTexCount; idx++) {

                GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[idx]);

                GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
                        GLES20.GL_LINEAR);
                GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
                        GLES20.GL_LINEAR);
                GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
                        GLES20.GL_CLAMP_TO_EDGE);
                GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
                        GLES20.GL_CLAMP_TO_EDGE);
                GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D,
                        0,
                        GLES20.GL_RGBA,
                        mPreviewSize.height, mPreviewSize.width,
                        0,
                        GLES20.GL_RGBA,
                        GLES20.GL_UNSIGNED_BYTE,
                        null);
            }

            mTextureRender.create(mPreviewSize.height,mPreviewSize.width);

            isNeedCreateTextures = false;
        }

        mTexture = mTextures[mTexIdx];
        mTexIdx = (mTexIdx + 1) % mTexCount;

        // 更新帧
        mSurfaceTexture.updateTexImage();
        mSurfaceTexture.getTransformMatrix(mMTX);

        // OES纹理转Texture2D纹理

        int drawRes = mOutputSurface.drawImageTo(mTexture,mPreviewSize.height,mPreviewSize.width);
        if (drawRes < 0) return;


        // 处理送入纹理 获取处理结果
        Image output = mPipe.process(mTexture,mPreviewSize.height,mPreviewSize.width,System.currentTimeMillis());

        // 预览处理后结果
        mLocalVideoSurfaceView.updateImage(output);

    // 旋转处理后结果 为推流做准备
                    mTextureRender.drawFrame(output.getGLTexture(),mPreviewSize.height,mPreviewSize.width);

        Image out = new Image(mTextureRender.getTextureID(),mPreviewSize.height,mPreviewSize.width,System.currentTimeMillis());

    // 获取推流数据

        pushExternalVideoYuv(out.getBuffer(Image.Format.RGBA8888));

//      pushExternalVideoFrame(output.getGLTexture());
    // 释放单次资源
        out.release();
        output.release();

    }

阿里云推流SDK新版本接入指南

目前阿里云推流SDK的三方美颜接入需通过自行实现AlivcLivePushCustomFilter接口来进行实现

阿里云SDK自定义滤镜实现

/**
* 美颜回调
**/

mAlivcLivePusher.setCustomFilter(new AlivcLivePushCustomFilter() {
    @Override
    public void customFilterCreate() {
        Log.d(TAG, "customFilterCreate start");

        // 初始化渲染管线

        EGLContext currentContext = EGL14.eglGetCurrentContext();

        boolean hasContext = currentContext != EGL14.EGL_NO_CONTEXT;

        mPipe = LivePipeMediator.getInstance();
        mPipe.requestInit(this,hasContext ? currentContext : null);

        Log.d(TAG, "customFilterCreate end");
    }

    @Override
    public void customFilterUpdateParam(float fSkinSmooth, float fWhiten, float fWholeFacePink, float fThinFaceHorizontal, float fCheekPink, float fShortenFaceVertical, float fBigEye) {

    }

    @Override
    public void customFilterSwitch(boolean on) {

    }

    @Override
    public int customFilterProcess(int inputTexture, int textureWidth, int textureHeight, long extra) {
        Log.d(TAG, "customFilterProcess start: textureId" + inputTexture + ",width:" + textureWidth + ",height:" + textureHeight);
 if (mResult != null) mResult.release();

            // 纹理处理
            Image out = LivePipeMediator.getInstance().process(textureId,width,height,System.currentTimeMillis());
            mResult = out;
            // 返回处理后的纹理
            return mResult.getGLTexture();
    }

    @Override
    public void customFilterDestroy() {
            // 释放渲染管线
                    LivePipeMediator pipeMediator = LivePipeMediator.getInstance();
                    pipeMediator.release();
                    Engine.getInstance().release();
    }
});

融云RTC接入指南

回调接口

步骤 1:设置视频数据回调

通过 RCRTCVideoOutputStream.setVideoFrameListener 注册要处理的视频流的采集监听:

RCRTCEngine.getInstance().getDefaultVideoStream().setVideoFrameListener(new IRCRTCVideoOutputFrameListener() {
    @Override
    public RCRTCVideoFrame processVideoFrame(RCRTCVideoFrame rtcVideoFrame) {
        // 使用数据进行美颜/录像等处理后,需要把数据再返回给 SDK 做发送。
        if (!LivePipeMediator.getInstance().isReady()){
                // 初始化渲染管线
                    final EGLContext currentContext = EGL14.eglGetCurrentContext();

                    LivePipeMediator pipeMediator = LivePipeMediator.getInstance();
                    pipeMediator.requestInit(this,currentContext);
            }
            if (mResult != null) mResult.release();

            // 纹理处理
            Image out = LivePipeMediator.getInstance().process(textureId,width,height,System.currentTimeMillis());
            mResult = out;
        rtcVideoFrame.setTextureId(mResult.getGLTexture());
        return rtcVideoFrame;
    }
});

流处理SDK释放

// 释放渲染管线
LivePipeMediator pipeMediator = LivePipeMediator.getInstance();
pipeMediator.release();
Engine.getInstance().release();

即构RTC接入指南

回调接口

步骤1 : 启动RTC前处理接口

启动方法可参考自定义视频前处理

接入示例

// 回调方法获取原始数据
// 回调处理
express.setCustomVideoProcessHandler(new IZegoCustomVideoProcessHandler() {
    ...

    // Receive texture from ZegoExpressEngine
    @Override
    public void onCapturedUnprocessedTextureData(int textureID, int width, int height, long referenceTimeMillisecond, ZegoPublishChannel channel) {


        ZegoEffectsVideoFrameParam param = new ZegoEffectsVideoFrameParam();
        param.format = ZegoEffectsVideoFrameFormat.BGRA32;
        param.width = width;
        param.height = height;

        if (!LivePipeMediator.getInstance().isReady()){
                // 初始化渲染管线
                    final EGLContext currentContext = EGL14.eglGetCurrentContext();

                    LivePipeMediator pipeMediator = LivePipeMediator.getInstance();
                    pipeMediator.requestInit(this,currentContext);
         }
         if (mResult != null) mResult.release();

                     // 纹理处理
            Image out = LivePipeMediator.getInstance().process(textureId,width,height,System.currentTimeMillis());
            mResult = out;




        // Send processed texture to ZegoExpressEngine
        express.sendCustomVideoProcessedTextureData(mResult.getGLTexture(), width, height, referenceTimeMillisecond);
    }
}

  • 接入准备
  • 腾讯云直播接入指南
  • 七牛直播接入指南
  • 声网推流接入指南
  • 阿里云推流SDK新版本接入指南
  • 融云RTC接入指南
  • 即构RTC接入指南
  • 在线技术支持
  • 专业售前售后团队
  • 版本定期更新
  • 全方位解决方案

商务合作

  • 177-6716-7529
  • 2969573855
  • sales@tusdk.com
  • 浙江省 杭州市 西湖区 西斗门9号 福地创业园1号楼3楼301室

关注我们

qrcode

©2019-2025 TUTUCLOUD. All Rights Reserved. 杭州元凡视觉智能科技有限公司 | 浙ICP备14040447号-1 | 浙公网安备33010602001649号

  • 177-6716-7529
  • sales@tusdk.com
  • 2969573855