短视频 SDK Android(快速接入)

这篇将介绍三种 UIKit 如何快速显示预览。三者共用依赖、SDK 初始化和 License 设置,完成公共准备后,按需选择对应组件;不需要将三个组件放在同一页面。

相关产品
短视频 SDK 产品页,含版本规格、价格与购买入口。
场景 组件 预览内容
编辑 TAVEditorUIKit 已有视频或图片。
剪同款 TAVTemplateEditUIKit 模板与已填入素材的预览。
录制 TAVRecorderUIKit 相机实时画面。

一、1. 引入依赖

将同版本交付包中的 tavmagic_x.x.x.x.aar 与 tavmagicuikit_x.x.x.x.aar 拷贝到 app/libs。三种 UIKit 已包含在同一个 UIKit AAR 中,均需同时引入底层 SDK AAR。

在 app/build.gradle 中配置依赖。

dependencies { implementation fileTree(dir: 'libs', include: ['*.aar', '*.jar']) implementation "com.tencent.tav:libpag:4.4.35-harfbuzz"}

二、2. 初始化 SDK 和设置 License

三种组件共用 TAVMagicBase.initSDK()。在进入页面前,按 快速接入 完成资源安装、SDK 初始化和 License 鉴权,不要为每个组件重复初始化。

初始化参数传 light_assets 的父目录,与资源安装路径保持一致。完整 AAR 随 APK 加载 SO;使用独立动态库目录时,先加载 SO 成功,再设置 License。

String sdkAssetPath = context.getFilesDir().getAbsolutePath();boolean loaded = TAVMagicBase.initSDK(context, sdkAssetPath);if (!loaded) { return;}TELicenseCheck.getInstance().setTELicense(context, TAV_MAGIC_LICENSE, TAV_MAGIC_KEY, (errorCode, message) -> { if (errorCode == 0) { // 通知业务层授权就绪,再允许进入对应页面 } else { Log.e("TAVMagicInit", "license failed: " + errorCode + ", " + message); } });

以上示例在资源安装成功后执行,TAV_MAGIC_LICENSE 和 TAV_MAGIC_KEY 替换为申请到的 URL 和 Key。initSDK 成功不代表鉴权成功;License 需包含所用能力的授权,剪同款需模板能力授权。鉴权回调中若操作 UI,应切换到主线程。

三、3. 配置宿主和主题

三个示例分别使用独立的 AppCompatActivity,组件创建和初始化在主线程执行。不要用 Application 或自行包装的 Context 创建 UIKit。

在 res/values/styles.xml 配置共用主题:

<resources> <style name="Theme.PreviewHost" parent="TAVMagicUIKitStyle" /></resources>

在 AndroidManifest.xml 的 application 节点中声明页面:

<activity android:name=".EditPreviewActivity" android:theme="@style/Theme.PreviewHost" /><activity android:name=".TemplatePreviewActivity" android:theme="@style/Theme.PreviewHost" /><activity android:name=".RecordPreviewActivity" android:theme="@style/Theme.PreviewHost" />

下面示例使用应用私有目录中的已有文件,不需要为编辑或剪同款预览申请公共存储读取权限。若素材来自外部存储或相册,先由业务方处理权限和文件读取,再提供 SDK 可读取的本地路径。

四、1. 添加组件

在 res/layout/activity_edit_preview.xml 中声明:

<com.tencent.tavmagic.uikit.TAVEditorUIKit xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/editor_ui" android:layout_width="match_parent" android:layout_height="match_parent" />

五、2. 加载素材并处理生命周期

将 video.mp4 提前放入应用的 files 目录,路径列表须非空且文件可读取。示例设置3分钟的最大编辑时长,可按业务需求调整。

import android.os.Bundle;import androidx.appcompat.app.AppCompatActivity;import com.tencent.tavmagic.uikit.TAVEditorUIKit;import java.util.Collections;public class EditPreviewActivity extends AppCompatActivity { private TAVEditorUIKit editor; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_edit_preview); editor = findViewById(R.id.editor_ui); editor.setMaxEditDuration(180_000_000L); editor.initWithClipPath(Collections.singletonList( getFilesDir() + "/video.mp4")); } @Override protected void onResume() { super.onResume(); editor.onResume(true); } @Override protected void onPause() { editor.onPause(); super.onPause(); } @Override protected void onDestroy() { editor.onDestroy(); super.onDestroy(); } @Override public void onBackPressed() { if (!editor.onBackPressed()) { super.onBackPressed(); } }}

组件内部完成预览初始化和素材刷新。已有草稿也可通过 initWithDraft() 加载,与 initWithClipPath() 二选一。

仅预览已准备好的本地素材,无需设置素材提供器或素材面板。需要后续相册、BGM 选择和权限请求时,再按编辑 UIKit API 文档接入 setMaterialProvider、setPermissionProvider 等接口。

六、1. 准备模板和组件

提前准备可读取的本地模板目录,不能传模板 URL 或压缩包路径。素材类型、数量和时长须满足模板要求,并按坑位顺序排列;下面使用一个需要两个视频素材的模板作为示例。

在 res/layout/activity_template_preview.xml 中声明:

<com.tencent.tavtemplate.uikit.TAVTemplateEditUIKit xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/template_ui" android:layout_width="match_parent" android:layout_height="match_parent" />

七、2. 加载模板并处理生命周期

import android.os.Bundle;import androidx.appcompat.app.AppCompatActivity;import com.tencent.tavtemplate.uikit.TAVTemplateEditUIKit;import com.tencent.uikit.base.data.resource.TAVAlbumResource;import com.tencent.uikit.base.data.resource.TAVBaseResource;import java.util.Arrays;import java.util.List;public class TemplatePreviewActivity extends AppCompatActivity { private TAVTemplateEditUIKit templateEditor; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_template_preview); templateEditor = findViewById(R.id.template_ui); List<TAVAlbumResource> clips = Arrays.asList( new TAVAlbumResource(getFilesDir() + "/a.mp4", TAVBaseResource.TYPE.VIDEO), new TAVAlbumResource(getFilesDir() + "/b.mp4", TAVBaseResource.TYPE.VIDEO)); templateEditor.init(getFilesDir() + "/templates/project1", clips); } @Override protected void onResume() { super.onResume(); templateEditor.onResume(); } @Override protected void onPause() { templateEditor.onPause(); super.onPause(); } @Override protected void onDestroy() { templateEditor.onDestroy(); super.onDestroy(); } @Override public void onBackPressed() { if (!templateEditor.onBackPressed()) { super.onBackPressed(); } }}

图片素材使用 TAVBaseResource.TYPE.PHOTO。调用 init() 后,组件内部加载模板、填入素材并自动播放预览,无需额外调用底层编辑器的刷新或播放接口。首次预览不需要配置素材替换和导出监听器。

八、1. 提前申请权限

在 AndroidManifest.xml 中声明:

<uses-permission android:name="android.permission.CAMERA" /><uses-permission android:name="android.permission.RECORD_AUDIO" />

在入口页申请并确认权限,再打开新的 RecordPreviewActivity。相机预览需要 CAMERA,后续带麦克风录制需要 RECORD_AUDIO;以下示例按两项已授权处理,不为首次预览申请额外存储权限。

不要在已经恢复的 Activity 的权限回调中先创建组件、再设置配置:组件可能已开始准备相机,导致配置设置过晚。按下面流程在新 Activity 的 onCreate 中创建并立即配置。

九、2. 创建组件并设置预览参数

import android.Manifest;import android.content.pm.PackageManager;import android.os.Bundle;import androidx.appcompat.app.AppCompatActivity;import androidx.core.content.ContextCompat;import com.tencent.tavmagic.model.TAVRecorderConfig;import com.tencent.tavmagic.model.TAVRecorderConstants;import com.tencent.tavrecorder.uikit.TAVRecorderUIKit;public class RecordPreviewActivity extends AppCompatActivity { private TAVRecorderUIKit recorderUi; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { finish(); return; } recorderUi = new TAVRecorderUIKit(this); recorderUi.setRecorderConfig(new TAVRecorderConfig.Builder() .setResolution(TAVRecorderConstants.TAVResolution.RESOLUTION_720) .setAspectRatio(TAVRecorderConstants.TAVAspectRatio.RATIO_16_9) .setFps(30) .build()); setContentView(recorderUi); } @Override public void onBackPressed() { if (recorderUi == null || !recorderUi.onBackPressed()) { super.onBackPressed(); } }}

setRecorderConfig() 必须在相机准备前设置。录制 UIKit 自动绑定宿主生命周期,页面进入前台后自动开始预览,暂停和销毁时自动处理相机资源;不要仿照编辑组件调用不存在的 onResume/onPause/onDestroy 方法,也无需调用 startPreview()。

仅显示相机画面不需要设置美颜、滤镜素材面板或 BGM 提供器。相机权限与 License 授权是独立条件,授权失败也会导致预览无法启动;错误监听见录制 UIKit API 文档。

下文的屏幕适配和封面选择器为可选配置,不是首次预览的必要步骤;封面选择器内容针对编辑组件。

十、屏幕适配方案(可选)

TAVMagicUIKit SDK 对外提供默认的屏幕适配方案,只需让 UIKit 所在的 Activity 继承 TAVMagicAdaptActivity 即可。如果业务侧已存在自定义的 BaseActivity,可将以下代码拷贝至 UIKit 所在的 Activity 中使用。

注意:屏幕适配相关代码影响范围仅限调用的页面。

public class TAVMagicAdaptActivity extends AppCompatActivity { private static final String TAG = "TAVMagicAdaptActivity"; private static final float TARGET_WIDTH_DP = 375; private Context mCustomCtx; @Override protected void attachBaseContext(Context newBase) { if (mCustomCtx == null) { mCustomCtx = createCustomContext(newBase); } super.attachBaseContext(mCustomCtx); } private Context createCustomContext(Context context) { final DisplayMetrics systemDM = Resources.getSystem().getDisplayMetrics(); final DisplayMetrics activityDM = context.getResources().getDisplayMetrics(); float targetDensity = activityDM.widthPixels / TARGET_WIDTH_DP; float targetScaledDensity = targetDensity * (systemDM.scaledDensity / systemDM.density); Configuration newConfig = new Configuration(context.getResources().getConfiguration()); Context adaptedContext = context.createConfigurationContext(newConfig); DisplayMetrics newMetrics = adaptedContext.getResources().getDisplayMetrics(); newMetrics.density = targetDensity; newMetrics.scaledDensity = targetScaledDensity; return adaptedContext; } @Override public Resources getResources() { return (mCustomCtx != null && mCustomCtx.getResources() != null) ? mCustomCtx.getResources() : super.getResources(); }}

十一、封面选择器(可选)

TAVMagicUIKit SDK 内置默认封面选择器,支持从已完成编辑的视频内容中选取任意一帧作为封面。

十二、启动配置

TAVCoverRequest

描述

封面生成请求参数模型。用于描述一次封面生成/截取的上下文来源(编辑器实例或草稿)、目标时间点、占位图、最长时长限制以及渲染分辨率等级等信息。

参数

字段名 类型 说明
editorKey String 对应编辑器实例的唯一标识 Key,用于从当前运行中的编辑器中生成封面。
draft TAVDraft 草稿对象,当基于草稿离线生成封面时使用。
position long 打开封面选择器期望展示的视频时间点,单位:微秒(us)。
coverPlaceHolder String 封面占位图路径(可选),用于正式封面生成前展示的占位图片。
maxDuration long 当前封面请求对应的视频最大时长,单位:微秒(us)。用于裁剪封面选择器时长。
renderSizeLevel int 渲染分辨率等级,默认值为 TAVEditorConstants.VIDEO_LEVEL_720P。

十三、选择结果

TAVCoverResult

描述

封面生成/选择结果的数据模型。用于描述某一时间点对应的封面缩略图信息,包括时间戳和本地缓存路径。

参数

字段名 类型 说明
position long 封面对应的视频时间戳,单位:微秒(us)。
thumbPath String 封面图在本地的缓存文件路径。

十四、集成步骤

1. 封面选择器支持两种打开方式

·使用正在编辑的实例打开。通过 TAVEditorUIKit fork 出来一个离屏实例用来导出或配置封面选择器。

String editorKey = editor.forkOffscreenEditor();

·使用草稿打开。通过草稿本地路径创建 TAVDraft 对象。

TAVDraft draft = TAVDraft.createFromJsonPath(draftDir + File.separator + "draft.json");

2. 在 Activity 的 onCreate 方法中初始化 TAVCoverSelector 启动器。

coverLauncher = TAVCoverSelector.registerForResult(this, result -> { if (result != null) { //此处处理封面选择器返回的选择结果TAVCoverResult } });

3. 打开封面选择页面。

// 通过草稿打开 // TAVCoverSelector.TAVCoverRequest request = TAVCoverSelector.TAVCoverRequest.fromDraft(draft); // 通过编辑打开 TAVCoverSelector.TAVCoverRequest request = TAVCoverSelector.TAVCoverRequest.fromKey(editorKey); request.coverPlaceHolder = mThumbPath; request.renderSizeLevel = TAVEditorConstants.VIDEO_LEVEL_720P; request.maxDuration = 20_000_000; request.position = 10_000_000; coverLauncher.launch(request);

赞 (0)
上一篇 4天前
下一篇 4天前