文件名称 | 文件 | 资源说明 | 使用位置 |
---|---|---|---|
EffectResource | transitions.bundle | 转场资源 | 轨道编辑转场 |
ModelResource.bundle | 模型资源 | 各个特效依赖的模型 | |
tone.bundle | 变声资源 | 预览编辑变声面板 | |
sound.bundle | 音效资源 | 轨道编辑添加音效 | |
sticker.bundle | 信息化贴纸资源 | 预览编辑信息化贴纸面板 | |
ve_effect.bundle | 特效资源 | 预览编辑特效面板 | |
ComposeMakeup.bundle | 美颜资源 | 拍摄美颜面板 | |
StickerResource.bundle | 人脸贴纸资源 | 拍摄贴纸面板、预览编辑人脸贴纸面板 | |
fonts.bundle | 字体资源 | 预览编辑文字面板 | |
music.bundle | 音乐资源 | 拍摄、预览编辑、轨道编辑音乐面板 | |
filter.bundle | 滤镜资源 | 拍摄、预览编辑滤镜面板 | |
Resource_icons | 素材相关icon | 所有资源对应的icon,面板展示时使用 | |
Panel_configs | 配置文件 | 各个面板层级关系配置,面板展示时使用 | |
RemoteResource | 客户自行部署按需下载时使用 | 用于服务器部署,素材内置时不需要关注 | |
License | 鉴权文件 | 用于应用鉴权 |
场景:点击某个功能项时才下载对应资源
优点:减小包体;避免一次下载所有资源带来的长耗时问题
资源包 EffectResource 无需内置到 App 工程
在使用任何工程之前,配置EOResourceConfig,完成网络相关初始化
参数名 | 类型 | 含义 | 建议值 | 备注 |
---|---|---|---|---|
resourceSavePath | String | 素材下载后本地路径 | EOUtils.pathUtil.internalResource() | |
sysLanguage | String | 素材展示名称的语言,默认支持简体中文(zh)和英文(en),其他语言需要自行在config中适配 | Locale.getDefault().language | |
netWorker | INetWorker | 网络请求代理 | DefaultNetWorker() | DefaultNetWorker,实现在EOQuickInithelper中,使用OKHTTP去发起网络请求 |
requestBuilder | IRequestBuilder | 构建网络请求的代理 | 根据客户自己的场景来实现:
| interface IRequestBuilder { fun buildDownloadResourceRequest(relativePath: String, isModel: Boolean, node: Any?): RequestInfo fun getIconUrl(buildInIcon: String): String? |
通过IRequestBuilder来定义获取config/素材zip/预览图的相关请求
在配置各个页面的面板时,使用OnlineResourceLoader代替EOQuickInitHelper中的DefaultLocalResourceLoader,示例代码如下
class EOQuickInitHelper { ... fun initApplication(application: Application) { ... // 指定素材文件保存目录、素材使用语言 val config = EOResourceConfig.Builder() .setResourceSavePath(EOUtils.pathUtil.internalResource()) .setSysLanguage(Locale.getDefault().language) .setNetWorker(DefaultNetWorker()) // 使用在线素材时需要该配置 .setRequestBuilder(object: IRequestBuilder) // .setDomainConfig(EORemoteAddressConfig()) //已废弃,如果以前使用了该接口,可以改成使用下方的setRequestBuilder(EORemoteAddressConfig()) // .setRequestBuilder(DomainRequestBuilder(EORemoteAddressConfig())) .build() // 素材sdk初始化 EOResourceManager.init(config) ... } private fun initConfigs() { //拍摄模块整体配置 EffectOneConfigList.configure(RecorderInitConfig()) { it.finishAction = { activity, list, musicItem -> val options = ActivityOptionsCompat.makeCustomAnimation(activity, 0, 0) EditorMainActivity.startEditorActivityFromRecord(activity, list.map { resourceItem -> com.volcengine.easyeditor.api.MediaItem( path = resourceItem.path, type = if (resourceItem.type == RecordMediaType.VIDEO) MediaType.VIDEO else MediaType.IMAGE, duration = resourceItem.duration, speed = resourceItem.speed ) } as ArrayList<com.volcengine.easyeditor.api.MediaItem>, options.toBundle(), musicItem) } it.albumConfig = AlbumConfig( allEnable = true, imageEnable = true, videoEnable = true, maxSelectCount = EffectOneSdk.albumMaxSelectedCount, //maxDuration Unit:ms maxDuration = 60 * 60 * 1000L, finishClazz = StartEditorFinishImpl::class.java ) } val loader = OnlineResourceLoader() //编辑和拍摄通用面板配置 //滤镜面板 EffectOneConfigList.configure(FilterUIConfig()) { it.resourceLoader = loader } //人脸特效面板 EffectOneConfigList.configure(EOBaseStickerUIConfig()) { it.resourceLoader = loader } //音乐面板 EffectOneConfigList.configure(EOBaseMusicUIConfig()) { it.resourceLoader = loader } //拍摄专用面板配置 //美颜面板 EffectOneConfigList.configure(BeautyUIConfig()) { it.resourceLoader = loader it.defaultBeautyAction = { EOResourceManager.syncLoadConfigByPanelKey(EOResourcePanelKey.RECORDER_BEAUTY.value, true).tabs } } //合拍面板 EffectOneConfigList.configure((RecorderDuetUIConfig())) { it.resourceLoader = loader it.defaultDuetAction = { EOResourceManager.syncLoadConfigByPanelKey(EOResourcePanelKey.RECORDER_DUET.value, true).tabs } } //编辑专用面板配置 //信息贴纸面板 EffectOneConfigList.configure(InfoStickerUIConfig()) { it.resourceLoader = loader } //文字面板 EffectOneConfigList.configure(TextStickerUIConfig()) { it.resourceLoader = loader } //视频特效面板 EffectOneConfigList.configure(EffectPanelUIConfig()) { it.resourceLoader = loader } //音频特效面板 EffectOneConfigList.configure(AudioFilterUIConfig()) { it.resourceLoader = loader } //转场面板 EffectOneConfigList.configure(TransitionUIConfig()) { it.resourceLoader = loader } } }
部署配置文件
基于RequestBuilder的配置,从客户端的请求中,获取 panel_key 字段信息,得到请求的配置文件名。
fun buildPanelConfigRequest(panelKey: String): RequestInfo
参数含义:
所有的配置文件位于 交付文档中的Panel_configs 文件夹内
请求行为行为在DefaultNetWorker.execute(requestInfo: RequestInfo)中实现
示例请求如下
data class RequestInfo( val domain: String? = "https://your panel host address", val path: String? = "/recorder_beauty", val requestType: RequestType = RequestType.GET,//对应api请求 val headerMap: Map<String, String>? = null, val body: ByteArray? = null, val contentType: String? = null ) //返回示例 { "data": { "tabs": [ { "uniqueId": "d0001", "titleDict": { "en": "2D", "zh": "2D" }, "subItems": [ { "uniqueId": "d0002", "titleDict": { "en": "Autumn Leaves", "zh": "金秋叶舞" }, "builtInIcon": "eo_resource_jinqiuyewu_7048762992175349791.png", "md5": "F18FDFFD6DB904FFBE465909F0867959", "relativePath": "StickerResource.bundle/jinqiuyewu_7048762992175349791.zip", "param": { "path": "StickerResource.bundle/jinqiuyewu_7048762992175349791" }, "requirements": [ { "relativePath": "ttfacemodel/algo_ggl1pqh_v11.1.model", "md5": "F7360859FEB0EA5DF58DA9860EF9738F" }, { "relativePath": "ttfacemodel/algo_ggl1pqhlhmg7p_v14.0.model", "md5": "D342795D110E4230666FB41B413AA638" }, { "relativePath": "ttfaceattrmodel/algo_ggl1pqhl4hpkg6_v5.0.model", "md5": "194F4C038CD35A4E07FF378DE97B8709" }, { "relativePath": "ttfaceattrmodel/algo_ggl1pqhlpgg754kgh_v8.0.model", "md5": "8CDD9000E4DE6111E21B148B3BFA2D5B" }, { "relativePath": "ttfaceattrmodel/algo_ggl1pqhlpgg754kghlgt4_v7.0.model", "md5": "4FFDB764F2EC8876B615A6865330E96C" }, { "relativePath": "ttfaceattrmodel/algo_ggl1pqhlpgg754kghlhmg7p_v3.0.model", "md5": "EA8D1F0BCEE6B8DC4DE8AC2693C85FE2" }, { "relativePath": "ttfaceattrmodel/algo_ggl1pqhlpgg754kghlhmi_v1.0.model", "md5": "93BB53B5394184A0495A278F7A801C3A" }, { "relativePath": "ttfaceattrmodel/algo_ggl1pqhlpgg754kghlpah_v2.0.model", "md5": "9EB2F0B32B36C71220AE4645144596DA" }, { "relativePath": "ttfaceattrmodel/algo_ggl4hpkg6lpgg7e_v2.0.model", "md5": "2C2DC971E4F7567D09D26F870965043B" }, { "relativePath": "handmodel/algo_ggl0pcvl4tml7ha_v12.0.model", "md5": "9D85DE071360FDF2EF16BB89D7153B6C" }, { "relativePath": "handmodel/algo_ggl0pcvl75ca_v1.1.model", "md5": "1588A926866EF9A5367F23ADD9F0C2A5" }, { "relativePath": "handmodel/algo_ggl0pcvl97_v3.2.model", "md5": "A55AFDBBD45B1C84E33E2EA3A6859368" }, { "relativePath": "handmodel/algo_ggl0pcvlahugk7h_v11.0.model", "md5": "D5B8890589D61D738EB3AC050AC3716A" }, { "relativePath": "handmodel/algo_ggl0pcvlahugk7hlgt4_v11.2.model", "md5": "068E6D58EE05EA0250C2E96852DEBAA7" }, { "relativePath": "handmodel/algo_ggl0pcvlsi_v6.0.model", "md5": "130183E2A6880A627AFF4E86874E580B" }, { "relativePath": "handmodel/algo_ggl0pcvlsibv_v2.0.model", "md5": "97807B3D18A6D77D86E8DF96CEA386C7" }, { "relativePath": "handmodel/algo_ggl0pcvluha_v2.0.model", "md5": "DDDC9206CD2C70310C803E226E0F0A02" }, { "relativePath": "handmodel/algo_ggl0pcvlvhg_v11.0.model", "md5": "208FF7DC0FE017C029D32D38646AC4F2" } ], "tipsDict": { "en": "Take out your hand", "zh": "伸出手掌" } } ] } ] } }
部署特效和模型资源
基于RequestBuilder的配置,从客户端的请求中,得到需要下载的文件的相对路径,并将文件流式返回给客户端供其下载
fun buildDownloadResourceRequest(relativePath: String, ext: panelKey: Sting, isModel: Boolean, node: Any?): RequestInfo
参数含义
relativePath:对应上一条,PanelConfigRequest中服务端返回的PanelConfig里每个素材item对应的相对路径。接入方可以根据该路径,将素材zip包部署到服务器或cdn上。
isModel:是否是模型
node:对应每个item的详细属性,无需关注
需要部署的所有资源位于 RemoteResource 文件夹内
下载行为行为在DefaultNetWorker.execute(requestInfo: RequestInfo)中实现
示例请求如下:
data class RequestInfo( val domain: String? = "https://your resource host address", val path: String? = "/StickerResource.bundle/jinqiuyewu_7048762992175349791.zip",//对应config.json中的一个item的relativepath val requestType: RequestType = RequestType.FILE,//对应下载 val headerMap: Map<String, String>? = null, val body: ByteArray? = null, val contentType: String? = null ) //返回对应zip包的下载数据
下载行为在DefaultNetWorker.execute(requestInfo: RequestInfo)中实现
部署 icon
基于RequestBuilder的配置,获取图标地址
fun getIconUrl(buildInIcon: String, panelKey: Sting): String?
需要部署的 icon 位于 Resource_icons 文件夹内
示例如下:如config中的builtInIcon为"eo_resource_jinqiuyewu_7048762992175349791.png",返回对应的图标在线地址:http://your icon host/eo_resource_jinqiuyewu_7048762992175349791.png
图片的具体下载行为,在EOQuickInitHelper中的DefaultImageLoader中利用Glide完成
部署预览video(若需要)
基于RequestBuilder的配置,获取预览视频地址
fun getVideoUrl(builtInVideo: String, panelKey: String): String
需要部署的 视频 位于 Resource_videos 文件夹内
示例如下:如config中的builtInVideo为"eo_resource_mengwa.mp4",返回对应的视频在线地址:http://your icon host/eo_resource_mengwa.mp4
交付后,不要进行任何资源包的改动、解压、压缩等操作,否则会导致下载失败
为了方便理解,下方提供一个简单的mock server 和 RequestBuilder,用来演示如何部署在线素材(环境为mac系统,python3,保证测试手机和电脑在相同的wifi环境下)
~/Downloads/fd9d70fc2b743113eb1cf40f9cc4093c
cd ~/Downloads/fd9d70fc2b743113eb1cf40f9cc4093c //进入到解压后的资源目录 python3 -m http.server 8000 //在本机的ip上8000端口,启动SimpleHttpServer
ipconfig getifaddr en0 //或者使用ifconfig 查看电脑的ip
到此,完成了server数据的mock
之后,在EO的demo中,配置一个对应的RequestBuilder,domain = "http://10.78.55.150:8000/Android"
//domain为你本地的ip:port/文件地址,参考上文的server,domain="http://10.78.55.150:8000/Android" class MockOnlineRequestBuilder(private var domain: String?): IRequestBuilder { init { domain = domain?.removeSuffix("/") } private val panelPathFormat = "/EffectResource/Panel_configs/%s.json" // 面板json路径 private val iconPathFormat = "/EffectResource/Resource_icons/%s" // 图标路径 private val videoPathFormat = "/EffectResource/Resource_videos/%s" // 视频路径 private val resourceFormat = "/RemoteResource/%s" // 素材资源路径 private val modelFormat = "/RemoteResource/ModelResource.bundle/%s" // 模型资源路径 override fun buildDownloadResourceRequest( relativePath: String, isModel: Boolean, node: Any?, panelKey: String ): RequestInfo { return if (isModel) { RequestInfo(domain, modelFormat.format(relativePath), RequestType.FILE) } else { RequestInfo(domain, resourceFormat.format(relativePath), RequestType.FILE) } } override fun getIconUrl(buildInIcon: String, panelKey: String): String { return domain + iconPathFormat.format(buildInIcon) } override fun getVideoUrl(builtInVideo: String, panelKey: String): String { //使用 mock server时,需要关闭播放缓存,否则无法正确加载视频 val cutsameConfig = InnerEffectOneConfigList.getConfig<CutSameConfig>(null) cutsameConfig?.usePlayCacheServer = false return domain + videoPathFormat.format(builtInVideo) } override fun buildPanelConfigRequest(panelKey: String): RequestInfo { val newPanelKey = if (panelKey == EOResourcePanelKey.CUTSAME_TEMPLATES.value) { "eo_cutsame" } else { panelKey } return RequestInfo(domain, panelPathFormat.format(newPanelKey)) } }
并在RequetBuilder配置给EO,具体方法如下:
在EOQuickInitHelper中,修改initApplication方法
override fun initApplication(application: Application) { ... resourceLoader = OnlineResourceLoader.instance //使用在线素材加载 val config = EOResourceConfig.Builder() .setResourceSavePath(EOUtils.pathUtil.internalResource()) .setSysLanguage(Locale.getDefault().language) .setNetWorker(DefaultNetWorker()) // 使用在线素材时需要该配置 .setRequestBuilder(MockOnlineRequestBuilder("your mock server domain")) //使用自定义的RequestBuilder .build() ... }
运行Demo App,并清除app的缓存,避免之前有离线加载的素材影响测试。然后可以根据之前运行python 服务器的terminal输出的日志,来判断是否访问了mock server上的资源。Server端日志大概如下:
场景:客户端一次性将资源、模型、icon、配置文件下载
优点:减小包体;服务端部署简单;网络交互少
客户端自行进行下载,在使用任何 SDK 工程之前,确保所有资源下载完成并解压到了自定义目录TARGET_PATH
进行如下代码配置
// 需要在EOQuickInitHelper initConfigs()里添加读取面板配置文件的实现,参考如下: DefaultLocalResourceLoader.instance.localConfigsLoader = object : LocalConfigsLoader { private val configsPathMap : Map<String, String> = mutableMapOf<EOResourcePanelKey, String>().apply { put(EOResourcePanelKey.PREVIEW_EDITOR_EFFECT, "${TARGET_PATH}/preview_editor_effect.json") put(EOResourcePanelKey.PREVIEW_EDITOR_FILTER, "${TARGET_PATH}/preview_editor_filter.json") put(EOResourcePanelKey.PREVIEW_EDITOR_FONT, "${TARGET_PATH}/preview_editor_font.json") put(EOResourcePanelKey.PREVIEW_EDITOR_INFO_STICKER, "${TARGET_PATH}/preview_editor_info_sticker.json") put(EOResourcePanelKey.PREVIEW_EDITOR_MUSIC, "${TARGET_PATH}/eo_music.json") put(EOResourcePanelKey.PREVIEW_EDITOR_STICKER, "${TARGET_PATH}/preview_editor_sticker.json") put(EOResourcePanelKey.PREVIEW_EDITOR_VOICE, "${TARGET_PATH}/preview_editor_tone.json") put(EOResourcePanelKey.RECORDER_BEAUTY, "${TARGET_PATH}/recorder_beauty.json") put(EOResourcePanelKey.RECORDER_FILTER, "${TARGET_PATH}/recorder_filter.json") put(EOResourcePanelKey.RECORDER_MUSIC, "${TARGET_PATH}/eo_music.json") put(EOResourcePanelKey.RECORDER_STICKER, "${TARGET_PATH}/recorder_sticker.json") put(EOResourcePanelKey.TRACK_EDITOR_MUSIC, "${TARGET_PATH}/eo_music.json") put(EOResourcePanelKey.TRACK_EDITOR_SOUND, "${TARGET_PATH}/track_editor_sound.json") put(EOResourcePanelKey.TRACK_EDITOR_TRANSITION, "${TARGET_PATH}/track_editor_transition.json") }.map { it.key.value to it.value }.toMap() override fun loadConfigs(panelKey: String, type: String): String? { val value = configsPathMap.getValue(panelKey) ?: return null // 从下载的配置文件中读取面板配置文件内容 return EOUtils.fileUtil.readJsonFile("${TARGET_PATH}/${value}") } } val config = EOResourceConfig.Builder() .setResourceSavePath(${TARGET_PATH}) // 配置资源保存路径,用户可自定义 .build() // 素材sdk初始化 EOResourceManager.init(config) // 拉取面板配置时localOnly设置为true (一次性下载对素材sdk来讲也是属于离线资源) EOResourceManager.syncLoadConfigByPanelKey(id, localOnly) // 下载素材 EOResourceManager.syncLoadResourceByItem(item)
建议资源包下载格式为:直接将 EffectResource 压缩成 zip,作为下载的资源
场景:资源包均内置到工程中
优点:离线使用,无需服务器部署
把Resource_icons中的图标全部拷贝到res/drawable-xxhdpi
在使用任何 SDK 特效之前,做好如下配置
// 需要在EOQuickInitHelper initConfigs()里添加读取面板配置文件的实现,参考如下: DefaultLocalResourceLoader.instance.localConfigsLoader = object : LocalConfigsLoader { private val configsPathMap : Map<String, String> = mutableMapOf<EOResourcePanelKey, String>().apply { put(EOResourcePanelKey.PREVIEW_EDITOR_EFFECT, "Panel_configs/preview_editor_effect.json") put(EOResourcePanelKey.PREVIEW_EDITOR_FILTER, "Panel_configs/preview_editor_filter.json") put(EOResourcePanelKey.PREVIEW_EDITOR_FONT, "Panel_configs/preview_editor_font.json") put(EOResourcePanelKey.PREVIEW_EDITOR_INFO_STICKER, "Panel_configs/preview_editor_info_sticker.json") put(EOResourcePanelKey.PREVIEW_EDITOR_MUSIC, "Panel_configs/eo_music.json") put(EOResourcePanelKey.PREVIEW_EDITOR_STICKER, "Panel_configs/preview_editor_sticker.json") put(EOResourcePanelKey.PREVIEW_EDITOR_VOICE, "Panel_configs/preview_editor_tone.json") put(EOResourcePanelKey.RECORDER_BEAUTY, "Panel_configs/recorder_beauty.json") put(EOResourcePanelKey.RECORDER_FILTER, "Panel_configs/recorder_filter.json") put(EOResourcePanelKey.RECORDER_MUSIC, "Panel_configs/eo_music.json") put(EOResourcePanelKey.RECORDER_STICKER, "Panel_configs/recorder_sticker.json") put(EOResourcePanelKey.TRACK_EDITOR_MUSIC, "Panel_configs/eo_music.json") put(EOResourcePanelKey.TRACK_EDITOR_SOUND, "Panel_configs/track_editor_sound.json") put(EOResourcePanelKey.TRACK_EDITOR_TRANSITION, "Panel_configs/track_editor_transition.json") }.map { it.key.value to it.value }.toMap() override fun loadConfigs(panelKey: String, type: String): String? { val value = configsPathMap.getValue(panelKey) ?: return null // 从assets读取面板配置文件内容 return EOUtils.fileUtil.readJsonFromAssets(AppSingleton.instance, "${EOUtils.pathUtil.assetsResourcePath}/${value}") } } val config = EOResourceConfig.Builder() .setResourceSavePath(EOUtils.pathUtil.internalResource()) // 配置资源保存路径 .build() // 素材sdk初始化 EOResourceManager.init(config) // 拉取面板配置时localOnly设置为true EOResourceManager.syncLoadConfigByPanelKey(id, localOnly) // 下载素材 EOResourceManager.syncLoadResourceByItem(item)
场景:部分资源内置,来加快资源加载速度;其余资源部署到线上,减小包体
优点:实现加载速度和包体之间的平衡
参考「内置」场景,将需要内置的资源包放置到工程中打包
设置网络相关参数、内置资源包路径、下载资源包路径
// 需要在EOQuickInitHelper initConfigs()里添加读取面板配置文件的实现,参考如下: DefaultLocalResourceLoader.instance.localConfigsLoader = object : LocalConfigsLoader { private val configsPathMap : Map<String, String> = mutableMapOf<EOResourcePanelKey, String>().apply { put(EOResourcePanelKey.PREVIEW_EDITOR_EFFECT, "Panel_configs/preview_editor_effect.json") put(EOResourcePanelKey.PREVIEW_EDITOR_FILTER, "Panel_configs/preview_editor_filter.json") put(EOResourcePanelKey.PREVIEW_EDITOR_FONT, "Panel_configs/preview_editor_font.json") put(EOResourcePanelKey.PREVIEW_EDITOR_INFO_STICKER, "Panel_configs/preview_editor_info_sticker.json") put(EOResourcePanelKey.PREVIEW_EDITOR_MUSIC, "Panel_configs/eo_music.json") put(EOResourcePanelKey.PREVIEW_EDITOR_STICKER, "Panel_configs/preview_editor_sticker.json") put(EOResourcePanelKey.PREVIEW_EDITOR_VOICE, "Panel_configs/preview_editor_tone.json") put(EOResourcePanelKey.RECORDER_BEAUTY, "Panel_configs/recorder_beauty.json") put(EOResourcePanelKey.RECORDER_FILTER, "Panel_configs/recorder_filter.json") put(EOResourcePanelKey.RECORDER_MUSIC, "Panel_configs/eo_music.json") put(EOResourcePanelKey.RECORDER_STICKER, "Panel_configs/recorder_sticker.json") put(EOResourcePanelKey.TRACK_EDITOR_MUSIC, "Panel_configs/eo_music.json") put(EOResourcePanelKey.TRACK_EDITOR_SOUND, "Panel_configs/track_editor_sound.json") put(EOResourcePanelKey.TRACK_EDITOR_TRANSITION, "Panel_configs/track_editor_transition.json") }.map { it.key.value to it.value }.toMap() override fun loadConfigs(panelKey: String, type: String): String? { val value = configsPathMap.getValue(panelKey) ?: return null // 从assets读取面板配置文件内容 return EOUtils.fileUtil.readJsonFromAssets(AppSingleton.instance, "${EOUtils.pathUtil.assetsResourcePath}/${value}") } } //配置网络下载,参考上文在线&按需下载 // 指定素材文件保存目录、素材使用语言 val config = EOResourceConfig.Builder() .setResourceSavePath(EOUtils.pathUtil.internalResource()) .setSysLanguage(Locale.getDefault().language) .setNetWorker(DefaultNetWorker()) // 使用在线素材时需要该配置 .setRequestBuilder(object: IRequestBuilder) .build() // 素材sdk初始化 EOResourceManager.init(config) // 拉取面板配置时localOnly设置为false EOResourceManager.syncLoadConfigByPanelKey(id, localOnly) // 下载素材 EOResourceManager.syncLoadResourceByItem(item)
EffectOne支持客户使用三方信息贴纸,参考如下文档EffectOne支持第三方信息贴纸
EffectOneSdk需要使用素材来完成贴纸、特效、滤镜等效果,为了方便使用提供了素材SDK(EOResourceManager),方便接入方管理和配置素材。对于绝大部分场景,接入方直接使用ResourceManager来管理素材即可。
EOResourceManager主要提供的能力介绍:
同步/异步拷贝离线素材接口
同步/异步拉取并解析面板配置json接口
同步/异步拉取素材包能力,包含自动拉取依赖模型、自动融合在线/离线素材、单/多组素材一次拉取能力
EffectOne内部,所有功能(如滤镜、贴纸等)都依赖素材实现。IEOResourceItem提供了描述各种素材的通用接口,客户可以根据需求,自定义实现IEOResourceItem,来定制化EffectOneSDK拍摄和编辑页的各面板中可选元素的Tab、顺序、图标、名称等。默认情况下,EOResourceManager会根据各面板的config.json,自动构造对应的ResourceItem,客户无需关注。
参数名 | 类型 | 含义 | 是否必须 |
---|---|---|---|
uniqueId | String | 当前素材唯一ID | 是 |
title | String | 素材的标题(语言类型为用户设置) | 是 |
icon | String | 在线素材图标url | 否 |
builtInIcon | String | 离线素材图标文件名 | 否 |
defaultOn | Int | 素材是否开启 | 否 |
absPath | String | 素材本地保存的绝对路径 | 是 |
subItems | List<IEOResourceItem> | 当前素材的子项结构 | 否 |
params | Map<String, Any>? | 素材使用时需要用的参数 | 否 |
extra | Map<String, String>? | 音乐相关素材需要用到的额外参数 | 否 |
EffectOneSDK的每个面板,都需要接入方在宿主内实现素材加载的逻辑,如果需要使用在线素材,可以参考该OnlineResourceLoader
class OnlineResourceLoader: ResourceLoader { override suspend fun loadResourceList(id: String, type: String): List<IEOResourceItem> { return EOResourceManager.syncLoadConfigByPanelKey(id, false).tabs } override suspend fun loadResourceItem(item: IEOResourceItem): IEOResourceItem? { return if (EOResourceManager.syncLoadResourceByItem(item)?.resValue == 0) { EOResourceManager.syncLoadResourceByItem(item)?.resourceItem } else { null } } override fun checkResourceExist(item: IEOResourceItem): Boolean { return EOResourceManager.resourceLoaded(item) } }
如使用离线素材,可以参考DefaultLocalResourceLoader
/** * 素材SDK加载本地素材的ResourceLoader */ class DefaultLocalResourceLoader : ResourceLoader { var localConfigsLoader = object : LocalConfigsLoader { private val configsPathMap : Map<String, String> = mutableMapOf<EOResourcePanelKey, String>().apply { put(EOResourcePanelKey.PREVIEW_EDITOR_EFFECT, "Panel_configs/preview_editor_effect.json") put(EOResourcePanelKey.PREVIEW_EDITOR_FILTER, "Panel_configs/preview_editor_filter.json") put(EOResourcePanelKey.PREVIEW_EDITOR_FONT, "Panel_configs/preview_editor_font.json") put(EOResourcePanelKey.PREVIEW_EDITOR_INFO_STICKER, "Panel_configs/preview_editor_info_sticker.json") put(EOResourcePanelKey.PREVIEW_EDITOR_MUSIC, "Panel_configs/eo_music.json") put(EOResourcePanelKey.PREVIEW_EDITOR_STICKER, "Panel_configs/preview_editor_sticker.json") put(EOResourcePanelKey.PREVIEW_EDITOR_VOICE, "Panel_configs/preview_editor_tone.json") put(EOResourcePanelKey.RECORDER_BEAUTY, "Panel_configs/recorder_beauty.json") put(EOResourcePanelKey.RECORDER_FILTER, "Panel_configs/recorder_filter.json") put(EOResourcePanelKey.RECORDER_MUSIC, "Panel_configs/eo_music.json") put(EOResourcePanelKey.RECORDER_STICKER, "Panel_configs/recorder_sticker.json") put(EOResourcePanelKey.TRACK_EDITOR_MUSIC, "Panel_configs/eo_music.json") put(EOResourcePanelKey.TRACK_EDITOR_SOUND, "Panel_configs/track_editor_sound.json") put(EOResourcePanelKey.TRACK_EDITOR_TRANSITION, "Panel_configs/track_editor_transition.json") put(EOResourcePanelKey.RECORDER_DUET, "Panel_configs/recorder_duet.json") }.map { it.key.value to it.value }.toMap() override fun loadConfigs(panelKey: String, type: String): String? { val value = configsPathMap.getValue(panelKey) ?: return null return EOUtils.fileUtil.readJsonFromAssets(AppSingleton.instance, "${EOUtils.pathUtil.assetsResourcePath}/${value}") } } companion object { val instance = DefaultLocalResourceLoader() } override suspend fun loadResourceList(id: String, type: String): List<IEOResourceItem> { if (!EOResourceManager.hasLocalConfigJson(id)) { localConfigsLoader.loadConfigs(id, type)?.let { EOResourceManager.setLocalConfigJson(id, it) } } return EOResourceManager.syncLoadConfigByPanelKey(id, true).tabs } override suspend fun loadResourceItem(item: IEOResourceItem): IEOResourceItem? { return EOResourceManager.syncLoadResourceByItem(item)?.resourceItem } override fun checkResourceExist(item: IEOResourceItem): Boolean { return EOResourceManager.resourceLoaded(item) } } interface LocalConfigsLoader { fun loadConfigs(panelKey: String, type: String): String? }
interface IEOResourceItem { val uniqueId: String var title: String var tips: String? var icon: String var builtInIcon: String //0:关闭,1打开 var defaultOn: Int var absPath: String var subItems: List<IEOResourceItem>? var params: Map<String, Any>? var extra: Map<String, String>? }