【PAG】PAG简介
1 前言
1)简介
PAG (Portable Animated Graphics) 是一套完整的动效工作流解决方案。目标是降低或消除动效相关的研发成本,能够一键将设计师在 AE(Adobe After Effects)中制作的动效内容导出成素材文件,并快速上线应用于几乎所有的主流平台。可应用于直播场景的礼物和点赞动效,以及用户拍摄场景的魔法道具动效。
2)工作流程
PAG 工作流程如下,首先在 AE 中使用 PAGExporter 插件导出 .pag 动画资源,再使用 PAGViewer 桌面预览工具查看导出的 pag 资源,确认无问题后,再结合 PAG SDK 集成到相关平台上。
3)功能特性
- 高效还原动效:PAG 采用高压缩的二进制编码方式,创新地实现了矢量和序列帧的混合导出能力,支持所有 AE 特性的导出。
- 运行时可编辑:PAG 素材可以在运行时动态修改、替换文本和照片、视频素材,极大地简化了多种视频类型模板的生产上线过程。
- 原子组合能力:PAG 支持围绕用户上传的视频内容,对接 AI 的识别能力,生成定制化的模板。模板由多个 PAG 文件有机组合在一起,根据一定的规则匹配得到无数的自适应模板效果。
4)相关链接
- PAG 官网:https://pag.qq.com/
- 官方案例:https://pag.qq.com/case.html
- 官方文档:https://pag.qq.com/docs/home.html
- libpag:https://github.com/Tencent/libpag
- pag-android:https://github.com/libpag/pag-android
- PAG 文件在线预览:https://pag.qq.com/player.html
- 快速接入 SDK:https://pag.qq.com/docs/sdk.html#移动端接入
- SDK API 文档:https://pag.qq.com/docs/apis.html
- SDK 快速接入:https://pag.qq.com/docs/sdk.html
- 常用 API 解读:https://pag.qq.com/docs/api-instructions.html
- PAG 性能优化视频:https://pag.qq.com/docs/pag-training.html
- PAGExporter 面板视频:https://pag.qq.com/docs/pag-training-2.html
2 框架
1)pag 文件框架
Property 是 AE 动效最基本的组成单元。
2)PAG 的渲染树
3)PAG 类图框架
4)TGFX 框架
为替换掉 Skia,取得 PAG 包体和性能的进一步突破,Tecent 自研了 TGFX 绘图引擎。
3 常用接口
1)PAGView、PAGImageView
PAGView 继承 TextureView,运行时实时渲染,矢量渲染,缩放无损;PAGImageView 继承 View,预渲染为位图序列后播放,位图渲染,缩放会模糊。
// 设置 pag 文件路径, 如果 pag 文件在 assets 目录中, path 需要以 "assets://" 开头, 内部会调用 PAGFile.Load 加载文件
public boolean setPath(String path)
// 开始动画
public void play()
// 暂停动画
public void pause()
// 设置PAGComposition
public void setComposition(PAGComposition newComposition)
// 获取动画循环次数
public int repeatCount()
// 设置动画循环次数(小于1时, 表示只播放一次)
public void setRepeatCount(int repeatCount)
// 获取变换矩阵
public Matrix matrix()
// 设置变换矩阵
public void setMatrix(Matrix matrix)
// 立即渲染
public boolean flush()// 以下是PAGView特有的
// 获取动画时长
public long duration()
// 获取进度
public double getProgress()
// 设置进度
public void setProgress(double value)
2)PAGLayer
// 获取变换矩阵
public Matrix matrix()
// 设置变换矩阵
public void setMatrix(Matrix matrix)
// 图层是否可见
public native boolean visible()
// 设置图层可见性
public native void setVisible(boolean value)
// 获取图层的父容器
public native PAGComposition parent()
// 获取图层的动画时长
public native long duration()
// 获取帧率
public native float frameRate()
// 获取动画开始时间
public native long startTime()
// 设置动画开始时间
public native void setStartTime(long time)
// 获取动画进度
public native double getProgress()
// 设置动画进度
public native void setProgress(double value)
// 获取图层透明度
public native float alpha()
// 设置图层透明度
public native void setAlpha(float value)
3)PAGComposition
PAGComposition 继承 PAGLayer,表示一个容器,里面存放的是 PAGComposition 或者 PAGLayer。
// 容器宽度
public native int width()
// 容器高度
public native int height()
// 设置容器尺寸
public native void setContentSize(int width, int height)
// 容器内元素个数
public native int numChildren()
// 根据索引获取元素
public native PAGLayer getLayerAt(int index)
// 根据PAGLayer获取元素的索引
public native int getLayerIndex(PAGLayer layer)
// 设置index位置的元素
public native void setLayerIndex(PAGLayer layer, int index)
// 在容器末尾添加元素
public native void addLayer(PAGLayer pagLayer)
// 在index位置添加元素
public native void addLayerAt(PAGLayer pagLayer, int index)
// 容器内部是否包含PAGLayer元素
public native boolean contains(PAGLayer pagLayer)
// 移除PAGLayer元素
public native PAGLayer removeLayer(PAGLayer pagLayer)
// 移除index位置的PAGLayer
public native PAGLayer removeLayerAt(int index)
// 清空所有元素
public native void removeAllLayers()
// 交换元素
public native void swapLayer(PAGLayer pagLayer1, PAGLayer pagLayer2)
// 交换index1和index2位置的元素
public native void swapLayerAt(int index1, int index2)
4)PAGFile
PAGFile 继承 PAGComposition。
// 加载pag文件
public static PAGFile Load(String path)
// 加载pag文件(assets目录下)
public static PAGFile Load(AssetManager manager, String fileName)
// 加载pag文件 (二进制字节流)
public static PAGFile Load(byte[] bytes)
// 文本个数
public native int numTexts()
// 图片个数
public native int numImages()
// 视频个数
public native int numVideos()
// 获取文本数据
public native PAGText getTextData(int index)
// 替换文本
public native void replaceText(int editableTextIndex, PAGText textData)
// 替换图像
public void replaceImage(int editableImageIndex, PAGImage image)
5)PAGPlayer
// 获取PAGComposition
public native PAGComposition getComposition()
// 设置PAGComposition
public native void setComposition(PAGComposition newComposition)
// 获取PAGSurface
public PAGSurface getSurface()
// 设置PAGSurface
public void setSurface(PAGSurface surface)
// 获取变换矩阵
public Matrix matrix()
// 设置变换矩阵
public void setMatrix(Matrix matrix)
// 获取动画时长
public native long duration()
// 获取动画进度
public native double getProgress()
// 设置动画进度
public native void setProgress(double value)
// 获取当前帧
public native long currentFrame()
// 提交所有的变化, 立即渲染
public boolean flush()
// 释放资源
public void release()
4 环境搭建
1)配置 gradle
implementation 'com.tencent.tav:libpag:4.4.35'
2)配置混淆
需要在混淆列表里面,添加 libpag 的 keep 规则。
-keep class org.libpag.** {*;}
-keep class androidx.exifinterface.** {*;}
5 应用
本节完整资源详见 → 基于Android平台的PAG案例集合。
SimpleActivity.java
package com.zhyan8.pagDemo;import android.os.Bundle;
import android.view.View;
import android.widget.Button;import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;import org.libpag.PAGView;public class SimpleActivity extends AppCompatActivity {private PAGView mPAGView;private Button mPlayingBtn;private boolean isPlaying = true;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_simple);mPAGView = findViewById(R.id.pagView);mPlayingBtn = findViewById(R.id.btn_playing);mPAGView.setPath("assets://fireworks.pag");mPAGView.setRepeatCount(0);mPAGView.play();}public void onClickPlay(View view) {if (isPlaying) {mPAGView.pause();mPlayingBtn.setText("播放");} else {mPAGView.play();mPlayingBtn.setText("暂停");}isPlaying = !isPlaying;}
}
activity_simple.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:gravity="center_horizontal"><org.libpag.PAGViewandroid:id="@+id/pagView"android:layout_width="300dp"android:layout_height="600dp"android:layout_marginTop="50dp"/><Buttonandroid:id="@+id/btn_playing"android:layout_width="wrap_content"android:layout_height="50dp"android:layout_marginBottom="150dp"android:text="暂停"android:textSize="20sp"android:onClick="onClickPlay"/>
</LinearLayout>
运行效果如下。