实时音视频
  • iOS
  • Android : Java
  • macOS
  • Windows
  • HarmonyOS
  • Linux
  • Web
  • 小程序
  • Flutter
  • Electron
  • Unreal Engine
  • Unity3D
  • uni-app
  • React Native
  • Cocos Creator
  • 产品简介
  • 下载
  • 体验 App
  • 快速开始
    • 跑通示例源码
    • 集成 SDK
    • 实现视频通话
    • 场景化音视频配置
  • 通信能力
  • 房间能力
  • 音频能力
  • 视频能力
  • 直播能力
  • 其他能力
  • 最佳实践
  • 客户端 API
  • 服务端 API
  • 常见错误码
  • 常见问题
  • 文档中心
  • 实时音视频
  • 其他能力
  • 播放透明礼物特效

播放透明礼物特效

更新时间:2024-01-02 18:48

功能简介

在语聊房和直播等场景中,礼物是主播与观众互动的重要环节。精致的礼物效果,可以增强互动感,提升观看体验。随着行业的蓬勃发展,礼物效果也从静态到动态、从不透明到透明逐步进化。

通过播放 MP4 的礼物视频来实现动态礼物效果,是比较常见的方式。由于 MP4 不支持 Alpha 通道,在全屏播放礼物特效时,会挡住直播间的内容,从而影响用户体验。因此 ZEGO Express SDK 媒体播放器提供透明渲染能力,可以实现播放透明动态礼物的功能。

ZEGO Express SDK 媒体播放器提供 RGB 通道与 Alpha 通道分离播放 MP4 素材(RGB 与 Alpha 拼接后的 MP4 素材)的功能,实现播放透明礼物的动态效果,即播放礼物特效时,不会挡住直播间内容,大大提升用户体验。

功能优势

  • 开发成本低

    开发者不需要学习复杂的动画实现方案,只需要使用设计师处理好的素材,即可实现播放透明礼物特效,提升开发效率和效果。

  • 动画还原度高

    帮助设计师实现输出素材所见即所得,即设计师在设计动效时,无需担心开发人员使用的技术栈能否还原动效复杂的 3D 效果、描边、粒子效果等。

  • 兼容性好

    规避 Lottie、Cocos2d-X 等半透明动效实现方式复杂、性能不高,以及部分机型的兼容问题较大、后期维护难度较高的问题。

实现原理

如下图所示,图中上半部分为一段进行了 Alpha 通道分离的素材的部分像素点,左侧使用 RGB 通道存储了礼物素材的 RGB 通道的信息,右侧使用 RGB 通道存储了礼物素材的 Alpha 通道的信息。

客户端播放时,会将右侧的视频的 R 通道提取出来,作为左侧对应像素点的 Alpha 通道的值。

渲染时,将 Alpha 通道的值除以 255,进行归一化处理,得到 0 ~ 1 之间的 Alpha 取值,最后根据 RGBA 值将每个像素点渲染到屏幕上,实现半透明效果。

/Pics/Express/RGBtoRGBA.jpeg

前提条件

在使用媒体播放器播放 MP4 动态效果,即实现播放透明礼物特效之前,请确保:

实现流程

1 输出素材

以在 AE 软件中输出素材为例。

  1. 在 AE 中正常制作带透明效果的视频,并分别输出 RGB 及 Alpha 通道视频。
    • 输出 RGB 通道的视频。
    • 输出 Alpha 通道的视频。
  1. 在 AE 中,将输出的 RGB 及 Alpha 通道视频拼接为一个视频。

    ZEGO 媒体播放器支持以下三种拼接方式,拼接出的视频越接近正方形,性能越好。开发者可以根据源素材的比例,选择合适的拼接方式:

    • Alpha 通道在下方。
    • Alpha 通道在左侧。
    • Alpha 通道在右侧。

2 对 view 进行特殊设置

在播放透明礼物特效前,需要提前设置用于播放器渲染透明特效的 view,目前支持 TextureView 和 SurfaceView 两种。

  • 若 view 为 TextureView 类型,需要调用 setOpaque,将 opaque 属性设置为 false。
TextureView mediaPlayerView;//用于播放的 view
mediaPlayerView.setOpaque(false);
  • 若 view 为 SurfaceView 类型,需要调用 setFormat,将 PixelFormat 属性设置为 TRANSLUCENT,并且需要把 view 置于显示窗口的最顶层。
SurfaceView mediaPlayerView;//用于播放的 view
mediaPlayerView.getHolder().setFormat(PixelFormat.TRANSLUCENT)
mediaPlayerView.setZOrderOnTop(true)//把 SurfaceView 置于显示窗口的最顶层

3 创建媒体播放器

调用 createMediaPlayer 创建媒体播放器,并调用 setPlayerCanvas 设置媒体播放器 canvas 的 alphaBlend 属性为 true。

mediaPlayer = engine.createMediaPlayer();
ZegoCanvas canvas = new ZegoCanvas(mediaPlayerView);
canvas.alphaBlend = true;//支持 Alpha 通道渲染
mediaPlayer.setPlayerCanvas(canvas);

4 加载素材

调用 createMediaPlayer 创建媒体播放器后,通过 loadResourceWithConfig 接口,通过文件路径二进制内存数据,播放拼接后的特效素材。

虽然 loadResourceWithConfig 接口支持通过版权音乐资源 ID 加载多媒体资源,但是版权音乐目前不支持视频,因此无法通过版权音乐资源 ID 加载方式来加载礼物特效。

通过文件路径加载 通过二进制内存数据加载
ZegoMediaPlayerResource resource = new ZegoMediaPlayerResource();
resource.loadType = ZegoMultimediaLoadType.FILE_PATH; // 加载方式选择文件路径加载
resource.filePath = "path";//文件路径
resource.alphaLayout = ZegoAlphaLayoutType.LEFT; // 根据实际资源选择 Alpha 通道布局
mediaPlayer.loadResourceWithConfig(resource, new IZegoMediaPlayerLoadResourceCallback() {
    @Override
    public void onLoadResourceCallback(int errorCode) {
        //资源加载结果
        // 可执行更新 UI 等逻辑
        if (errorCode == 0){
            //加载文件成功,此时可以开始播放媒体资源
            mediaPlayer.start();
        }
    }
});
ZegoMediaPlayerResource resource = new ZegoMediaPlayerResource();
resource.loadType = ZegoMultimediaLoadType.MEMORY; // 加载方式选择二进制内存数据
resource.alphaLayout = ZegoAlphaLayoutType.LEFT; // 根据实际资源选择 Alpha 通道布局

File file = new File(path); // 资源文件
int fileLength = (int)file.length();

resource.memory = ByteBuffer.allocateDirect(fileLength); // ByteBuffer 类型二进制内存数据
resource.memoryLength = bufferLength; // 二进制内存数据长度

// 将资源加载到内存中
try {
    BufferedInputStream stream = new BufferedInputStream(new FileInputStream(file));
    int data_byte=0;
    while((data_byte = stream.read()) != -1){
        resource.memory.put((byte)data_byte);
    }
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

mediaPlayer.loadResourceWithConfig(resource, new IZegoMediaPlayerLoadResourceCallback() {
    @Override
    public void onLoadResourceCallback(int errorCode) {
        // 资源加载结果
        // 可执行更新 UI 等逻辑
        if (errorCode == 0){
            //加载文件成功,此时可以开始播放媒体资源
            mediaPlayer.start();
        }
    }    
});

5 播放素材

在调用 loadResourceWithConfig 加载文件成功后,可调用 startpauseresumestop 来启停播放。一旦播放器的内部状态改变,ZegoMediaPlayeronMediaPlayerStateUpdate 回调将会被触发。

用户也可通过调用 getCurrentState 随时获取播放器的当前状态。

如果 enableRepeat 设置为 YES,则播放器会在播放完文件后自动重播。

// 开始播放,播放之前需要先调用接口加载媒体文件
mediaPlayer.start();
// 暂停
mediaPlayer.pause();
// 恢复
mediaPlayer.resume();
// 停止
mediaPlayer.stop();
本篇目录