短视频SDK提供视频编辑与导出功能,支持视频图片素材混合导入、提供滤镜、配音、时间特效等丰富的编辑效果。
版本支持
版本 | 是否支持 |
专业版 | 支持所有功能,其中,字幕、动态贴纸、MV等增值功能需要单独付费。 |
标准版 | 部分支持,支持除了字幕、动态贴纸、MV以外的其他功能。 |
基础版 | 不支持。 |
相关类功能
操作 | 类名 | 功能 |
初始化 | 视频编辑核心类。 | |
工厂类。 | ||
视频管理 | 视频源管理器。 | |
图片片段。 | ||
视频片段。 | ||
设置视频特效 | 滤镜及MV的Model。 | |
动效滤镜Model。 | ||
转场Model。 | ||
设置画中画 | 画中画管理类,负责画中画的增删改查。 | |
画中画控制器,设置画中画的开始时间,结束时间。 | ||
轨道信息获取。 | ||
布局控制器,对画中画移动、缩放、旋转、透明度等设置。 | ||
动画控制器,可以对画中画做帧动画。 | ||
声音控制器,控制画中画音量,降噪、音效、淡入淡出等。 | ||
画面调节控制器,可以调节饱和度、亮度、对比度等。 | ||
设置字幕及动态贴纸 | 字幕及动态贴纸管理器。 | |
字幕控制器。 | ||
动态贴纸控制器。 | ||
草稿箱 | 工程配置。 | |
草稿管理。 | ||
草稿。 | ||
资源加载器。 | ||
资源上传器。 | ||
资源下载器。 | ||
草稿资源处理任务。 |
编辑视频流程
阶段 | 流程 | 说明 | 示例代码 |
基础 | 1 | 创建并初始化编辑器。 | |
2 | 在编辑过程中动态裁剪视频、动态更换视频源、动态调整视频转场时间及转场效果。编辑核心类是AliyunIEditor类。 | ||
3 | 设置编辑器的预览播放。 | ||
进阶 | 4 | 设置滤镜、转场及MV特效。 | |
5 | 设置背景音乐、配音及音效。 | ||
6 | 设置画中画。 | ||
7 | 设置字幕、花字、文字气泡及动态贴纸。 | ||
8 | 支持编辑草稿箱中的视频、或将编辑完成的视频保存至草稿箱。 | ||
9 | 设置时间特效、水印及涂鸦。 |
初始化
创建并初始化编辑器。代码中需要使用的参数详情,请参考接口文档。接口链接请参见相关类功能。
//1. 实例化
//configPath为导入视频的地址,为草稿箱地址或者AliyunIImport.generateProjectConfigure()重新生成后的地址
Uri uri = Uri.parse(configPath);
AliyunIEditor editor = AliyunEditorFactory.creatAliyunEditor(uri, null);
//2. 初始化
//初始化并设置预览窗口
editor.init(surfaceView, context);
//3. 销毁,当不再使用时需要调用销毁接口
editor.onDestroy()
视频管理
视频编辑器里的视频或图片最终由视频源管理器AliyunIClipConstructor统一管理,通过AliyunIClipConstructor修改编辑器里的视频或图片后,需要手动调用AliyunIEditor.applySourceChange()应用更新的视频或图片。
代码中需要使用的参数详情,请参考接口文档。接口链接请参见相关类功能。
视频源管理操作
//1.获取视频源管理器
AliyunIClipConstructor contructor = AliyunIEditor.getSourcePartManager();
//[可选] 2.添加视频或图片
//在时间轴最后添加视频或图片,其中视频用AliyunVideoClip,图片用AliyunImageClipAliyunImageClip
contructor.addMediaClip(AliyunClip clip);
//在指定位置的添加视频或图片,其中视频用AliyunVideoClip,图片用AliyunImageClipAliyunImageClip
contructor.addMediaClip(int index, AliyunClip clip);
//[可选] 3.删除视频或图片
//删除最后一个视频或图片
contructor.deleteMediaClip();
//删除某一个指定的视频或图片
contructor.deleteMediaClip(int index);
//[可选] 4.替换视频或图片
//替换指定位置视频或图片
contructor.updateMediaClip(int index, AliyunClip clip);
//替换所有的视频或图片
contructor.updateAllClips(List<AliyunClip> clips);
//5.应用更新源:视频源操作完成后,要调用该方法应用更新,操作才会生效
AliyunIEditor.applySourceChange();
其他相关操作
//交换视频源顺序
contructor.swap(int pos1, int pos2);
//获取当前视频源个数
contructor.getMediaPartCount();
//获取当前视频源列表
contructor.getAllClips();
预览控制
在视频编辑过程中,提供一系列对当前视频的播放控制操作,如播放、暂停、获取当前时长等。代码中需要使用的参数详情,请参考接口文档。接口链接请参见相关类功能。
//开始播放
AliyunIEditor.play();
//继续播放
AliyunIEditor.resume();
// 暂停播放
AliyunIEditor.pause();
// 跳转到指定位置
AliyunIEditor.seek(long time);
// 设置静音播放
AliyunIEditor.setAudioSilence(boolean silence);
// 设置音量
AliyunIEditor.setVolume(int volume);
// 设置视频显示模式
AliyunIEditor.setDisplayMode(VideoDisplayMode mode);
// 填充模式下设置填充背景色
AliyunIEditor.setFillBackgroundColor(int color);
//获取当前流的位置 - 不受时间特效影响
AliyunIEditor.getCurrentStreamPosition();
// 获取当前播放的位置 - 受时间特效影响
AliyunIEditor.getCurrentPlayPosition();
// 获取流时长 - 不受时间特效影响
AliyunIEditor.getStreamDuration();
// 获取播放总时长 - 受时间特效影响
AliyunIEditor.getDuration();
设置视频特效
目前支持设置的视频特效包括滤镜、转场和MV,支持自定义制作,制作方法请参见滤镜及转场和MV。代码中需要使用的参数详情,请参考接口文档。接口链接请参见相关类功能。
lut滤镜
LUTEffectBean bean = new LUTEffectBean();
bean.setPath("image_01.png");
bean.setIntensity(1.f);
//添加lut滤镜
mAliyunIEditor.applyLutFilter(bean);
//删除lut滤镜
mAliyunIEditor.applyLutFilter(null);
静态滤镜
EffectBean effect = new EffectBean();
effect.setId(id)
effect.setSource(new Souce(filePath));
//添加滤镜
AliyunIEditor.applyFilter(effect);
//删除滤镜
AliyunIEditor.applyFilter(new EffectBean());
动效滤镜
EffectFilter effectFilter = new EffectFilter(new Souce(filePath));
effectFilter.setStartTime(startTime);
effectFilter.setDuration(duration);
//添加动效滤镜
AliyunIEditor.addAnimationFilter(effectFilter);
//删除指定动效滤镜
AliyunIEditor.removeAnimationFilter(effectFilter);
//删除所有动效滤镜
AliyunIEditor.clearAllAnimationFilter();
转场
//1.设置转场
//设置一个转场,index为转场位置,从0开始记,取消转场的话,transition传null即可
AliyunEditor.setTransition(int index, TransitionBase transition);
//设置批量转场,取消转场的话,transition传null即可
AliyunEditor.setTransition(Map<Integer, TransitionBase> transitions); //设置多个转场
//2.更新转场
//从某个转场更新成另一个转场,transition不允许为null
AliyunEditor.updateTransition(int index, TransitionBase transition);
MV
支持自定义MV,MV的制作规范请参见MV。
//添加MV
AliyunIEditor.applyMV(EffectBean effect);
//删除MV
AliyunIEditor.applyMV(null);
设置音乐及音效
音乐
音乐分为背景音乐和配音。背景音乐不受时间特效影响(变速、重复、倒放等),而配音会受到时间特效的影响。代码中需要使用的参数详情,请参考接口文档。接口链接请参见相关类功能。
EffectBean musicBean = new EffectBean();
musicBean.setId(effectInfo.id);
musicBean.setSource(effectInfo.getSource());
//切换音乐seek到0清音乐缓存,避免响一声
musicBean.setStartTime(startTime);
musicBean.setDuration(Integer.MAX_VALUE);//设置为最大时长
musicBean.setStreamStartTime(streamStartTime);
musicBean.setStreamDuration(streamDuration);
int audioSteamId;
//1.添加背景音乐/配音
audioSteamId = AliyunIEditor.applyMusic(musicBean);//音乐
AliyunIEditor.applyDub(EffectBean effect);//配音
//2.删除背景音乐/配音
AliyunIEditor.removeMusic(EffectBean effect);//音乐
AliyunIEditor.removeDub(EffectBean effect);//配音
//3.调整背景音乐/配音与原音的比重
AliyunIEditor.applyMusicMixWeight(int audioSteamId, int weight);
//4.调整指定音频流音量
//背景音乐、配音、原音,详细请查看API文档
AliyunIEditor.applyMusicWeight(int audioSteamId, int weight);
//5.指定音频流降噪
AliyunIEditor.denoise(int audioSteamId, boolean needDenoise);
音效
短视频SDK支持对每路音频流设置音效,目前提供的音效包括如下:
//1. 设置音效
//AudioEffectType的更多内容请查看API文档
int audioEffect(int audioSteamId, AudioEffectType type, int weight);
//2. 删除音效
//音效支持叠加操作,想要切换音效需要先删除上次设置的音效。
int removeAudioEffect(int audioSteamId, AudioEffectType type);
设置画中画
画中画功能允许在现用主轨道的基础上,添加一个或者多个画中画。
短视频SDK对画中画的个数未做限制,但建议同一时刻画面中最好不要超过3个画中画,具体限制个数由业务方自己做决定。
代码中需要使用的参数详情,请参考接口文档。接口链接请参见相关类功能。
//从编辑主接口获取画中画管理类
AliyunIPipManager pipManager = mAliyunIEditor.getPipManager();
//增加画中画
mAliyunIEditor.puase(); //先暂停
long current = mAliyunIEditor.getCurrentPlayPosition(); //获取当前的播放时间点
AliyunIPipManager pipManager = mAliyunIEditor.getPipManager();
AliyunIPipController pipController = pipManager.createNewPip("流文件地址");
pipController.setTimelineStartTime(current) //从轨道当前时间点开始
.setClipStartTime(0) //画中画视频本身开始时间
.apply(); //应用生效
//删除画中画
mAliyunIEditor.puase(); //先暂停
AliyunIPipManager pipManager = mAliyunIEditor.getPipManager();
pipManager.removePip(pipController);
//修改布局:AliyunILayoutController
mAliyunIEditor.puase(); //先暂停
AliyunILayoutController layoutController = pipController.getLayoutController(); // 获取布局控制器
layoutController.setRotation(3.14) //设置旋转弧度 0~3.14
.setScale(0.3) //设置缩放
.setPosition(0.5, 0.5) //设置位置居中
.apply();
//获取画中画画布中的位置
RectF rectf = pipController.getPipRectFInCurrentScreen(); //获得画中画所在的矩形区域
int width = mSurfaceView.getWidth() * rectf.width(); //画中画在画布中的实际宽度
int height = mSurfaceView.getWidth() * rectf.height(); //画中画在画布中的实际高度
//修改声音相关:AliyunIAudioController
mAliyunIEditor.puase(); //先暂停
AliyunIAudioController audioController = pipController.getAudioController(); //获取声音控制器
audioController.setVolume(100) //设置音量最大
.setAudioEffect(AudioEffectType.EFFECT_TYPE_LOLITA) //设置声音特效为萝莉音
.apply(); //应用
//设置画中画帧动画:AliyunIAnimationController
mAliyunIEditor.puase(); //先暂停
AliyunIAnimationController animationController = pipController.getAnimationController();
if (mActionTranslate == null) { //添加位移动画
mActionTranslate = new ActionTranslate();
mActionTranslate.setFromPointX(-1);
mActionTranslate.setFromPointY(-1);
mActionTranslate.setToPointX(1);
mActionTranslate.setToPointY(1);
mActionTranslate.setStartTime(pipController.getTimeLineStartTimeInMillis() * 1000);
mActionTranslate.setDuration(pipController.getClipDurationInMillis() * 1000);
animationController.addFrameAnimation(mActionTranslate);
} else { //删除位移动画
animationController.removeFrameAnimation(mActionTranslate);
mActionTranslate = null;
}
//画面调节:AliyunIAugmentationController
mAliyunIEditor.puase(); //先暂停
AliyunIAugmentationController augmentationController = pipController.getAugmentationController(); //获取画面调节控制器
augmentationController.setVignette(0~1) //设置暗角
.setSharpness(0~1) //设置锐化程度
.setSaturation(0~1) //设置保护度
.apply(); //应用
//获取轨道信息:AliyunIPipTrack
//方式一: 从管理类获取所有轨道
AliyunIPipManager pipManager = mAliyunIEditor.getPipManager();
List<AliyunIPipTrack> pipTrackList = pipManager.getPipTracks(); //获取所有画中画轨道
//方式二: 获取当前控制器所在轨道
AliyunIPipTrack pipTrack = pipController.getOwnerTrack();
List<AliyunIPipController> pipControllers = pipTrack.getPipClips(); //获取当前轨道下所有画中画片段控制器
设置字幕及动态贴纸
字幕及动态贴纸统一通过AliyunPasterManager进行管理,通过AliyunPasterManager获取到对应的AliyunIPasterController进行相应的操作。代码中需要使用的参数详情,请参考接口文档。接口链接请参见相关类功能。
基于字幕,短视频SDK还提供了花字及气泡文字的特效。花字、气泡文字及动态贴纸的制作请参见花字和动图。
字幕
添加/删除字幕
Source fontSouce = null;
long startTime = 0L;
long duration = 20000L;
//1. 添加字幕
AliyunPasterControllerCompoundCaption captionController = pasterManager.addCaptionWithStartTime('输入文字', null, fontSouce, startTime,duration);
//2. 删除字幕
controller.remove()
更新字幕属性
AliyunPasterControllerCompoundCaption包含了字幕的所有操作,详细请查看接口说明。每次更新完字幕属性后,必须调用AliyunPasterControllerCompoundCaption.apply()。
//设置颜色
captionController.setColor(AliyunColor color);
//设置字体
captionController.setFontPath(ISouce fontPath);
//应用以上更新
captionController.apply();
花字
Source fontEffectSource(fontEffectFolder);
//1. 应用花字
captionController.setFontEffectTemplate(fontEffectSource)
//2. 取消花字
captionController.setFontEffectTemplate(null)
文字气泡
Source bubbleEffectSource(bubbleEffectFolder);
//1. 应用气泡
captionController.setBubbleEffectTemplate(bubbleEffectSource)
//2. 取消气泡
captionController.setBubbleEffectTemplate(null)
动态贴纸
添加动态贴纸
AliyunPasterController pasterController = pasterManager.addPasterWithStartTime(Source path, long startTime, long duration);
设置动态贴纸属性
动态贴纸使用与字幕有所差异,动态贴纸是Android去展示的动画效果,因此设置贴纸的属性需要在Android实现UI(AliyunPasterBaseView),定义动态贴纸的大小、宽高、旋转角度等属性。由于是在平台层也同时实现了AliyunPasterBaseView,因此,提供了从渲染层展示、隐藏动态贴纸的操作,避免两者重叠。
//必须调用
pasterController.setPasterView(AliyunPasterBaseView pasterView);
//显示贴纸
pasterController.editCompleted();
//隐藏贴纸
pasterController.editStart();
贴纸效果图预览
//设置预览
pasterController.createPasterPlayer(TextureView view);
//同时手动触发播放/停止预览效果
protected void playPasterEffect() {
TextureView pv = new TextureView(mPasterView.getContext());
animPlayerView = mController.createPasterPlayer(pv);
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
ViewGroup vg = (ViewGroup) mPasterView.getContentView();
vg.addView(pv, 0, lp);
}
protected void stopPasterEffect() {
ViewGroup vg = (ViewGroup) mPasterView.getContentView();
vg.removeViewAt(0);
animPlayerView = null;
}
删除动态贴纸
pasterController.removePaster();
草稿箱
代码中需要使用的参数详情,请参考接口文档。接口链接请参见相关类功能。
工程配置信息获取
//初始化
AliyunIEditor.init(SurfaceView surfaceView, Context context);
//获取配置信息
AliyunEditorProject project = AliyunIEditor.getEditorProject();
初始化草稿管理器
AliyunDraftManager draftManager = AliyunDraftManager.getInstance(context);
获取草稿列表
//异步获取草稿列表
AliyunDraftManager.getInstance(getContext())
.getDraftListByAsync(new AliyunDraftListCallback() {
@Override
public void onFailure(final String msg) {
//获取列表异常
}
@Override
public void onSuccess(final List<AliyunDraft> draftList) {
//草稿列表回调
}
});
根据草稿ID删除草稿
//删除草稿,draft为草稿列表单个item(草稿列表通过草稿列表接口获取)
AliyunDraftManager.getInstance(v.getContext()).deleteDraft(draft.getId());
草稿重命名
//重命名,draft为草稿列表单个item(草稿列表通过草稿列表接口获取)
AliyunDraftManager.getInstance(v.getContext()).rename(draft.getId(), newName);
草稿复制
//复制后会返回新草稿,draft为草稿列表单个item(草稿列表通过草稿列表接口获取)
AliyunDraft newDraft = AliyunDraftManager.getInstance(v.getContext()).copy(draft.getId());
草稿加载
//draft为草稿列表单个item(草稿列表通过草稿列表接口获取)
AliyunDraftManager.getInstance(v.getContext()).preLoadDraft(draft, new AliyunDraftResourceLoader() {
@Override
public void onHandleResourceTasks(final List<AliyunDraftResTask> tasks) {
//缺少相关资源,返回需要处理的资源任务,必须对任务进行处理,可选项:修复、忽略、删除
HashMap<String, List<AliyunDraftResTask>> map = new HashMap<>();
for (AliyunDraftResTask task : tasks) {
if (task.getSource() != null && !StringUtils.isEmpty(task.getSource().getURL())) {
if (map.containsKey(task.getSource().getURL())) {
map.get(task.getSource().getURL()).add(task);
} else {
List<AliyunDraftResTask> list = new ArrayList<>();
list.add(task);
map.put(task.getSource().getURL(), list);
}
} else {
//必须对任务进行处理,可选项:修复、忽略、删除
if (task.getResModuleType() == AliyunResModuleType.MAIN_VIDEO) {
task.getSource().setPath(EditorCommon.SD_DIR + "svideo_res/image/aliyun_svideo_failed.jpg");
task.onHandleCallback(task.getSource());
} else if(task.getResModuleType() == AliyunResModuleType.TRANSITION) {
//删除
task.onRemove();
} else {
//忽略
task.onIgnore();
}
}
for (final Map.Entry<String, List<AliyunDraftResTask>> entry : map.entrySet()) {
//key为资源地址,Value为对应资源地址需要处理的任务
final List<AliyunDraftResTask> list = entry.getValue();
try {
final String url = entry.getKey();
//判断是否是平台资源
if (url.startsWith(AlivcResUtil.SCHEME)) {
//平台资源加载回调封装
AlivcResUtil.LoadCallback callback = new AlivcResUtil.LoadCallback() {
@Override
public void onSuccess(String path) {
for (AliyunDraftResTask task : list) {
Source source = task.getSource();
source.setPath(path);
task.onHandleCallback(source);
}
}
@Override
public void onFailure(String type, String msg) {
Log.d("CloudDraft", "loadRes>Failure>type>" + type + ">msg>" + msg);
for (AliyunDraftResTask task : list) {
task.onIgnore();
}
}
};
//加载平台资源,具体代码看demo
AlivcResUtil.loadRes(context, url, callback);
} else {
//下载用户资源,具体代码看demo
downloadRes(url, new File(item.getEditorProjectUri()).getParent(), list);
}
} catch (Exception e) {
//出错
for (AliyunDraftResTask item : list) {
item.onIgnore();
}
}
}
}
}
@Override
public void onFailure(final String msg) {
//预加载失败
Toast.makeText(v.getContext(), "预加载失败", Toast.LENGTH_SHORT).show();
}
@Override
public void onSuccess() {
//预加载处理成功即可进入编辑界面,draft为草稿列表单个item(草稿列表通过草稿列表接口获取),通过draft.getEditorProjectUri()来加载草稿
EditorActivity.startEdit(v.getContext(), draft);
}
});
上传草稿
上传草稿需配合草稿服务端,服务端简单代码示例下载。
//draft为草稿列表单个item(草稿列表通过草稿列表接口获取)
AliyunDraftManager.getInstance(context)
.uploadDraft(draft, new AliyunDraftResourceUploader() {
@Override
public void onHandleResourceTasks(final List<AliyunDraftResTask> tasks) {
//需要处理的上传资源任务
HashMap<String, List<AliyunDraftResTask>> map = new HashMap<>();
//过滤重复资源
for (AliyunDraftResTask task : tasks) {
if (task.getSource() == null) {
task.onIgnore();
continue;
}
//URL为空或者不以alivc_resource开头需要做上传处理
String url = task.getSource().getURL();
if (StringUtils.isEmpty(url) || !url.startsWith("alivc_resource")) {
if (map.containsKey(task.getSource().getPath())) {
map.get(task.getSource().getPath()).add(task);
} else {
List<AliyunDraftResTask> list = new ArrayList<>();
list.add(task);
map.put(task.getSource().getPath(), list);
}
} else {
//忽略出错
task.onIgnore();
}
}
for (Map.Entry<String, List<AliyunDraftResTask>> entry : map.entrySet()) {
try {
for (AliyunDraftResTask task : tasks) {
Source source = task.getSource();
//上传成功后回调远程地址
source.setURL();
task.onHandleCallback(source);
}
} catch (Exception e) {
//忽略出错
List<AliyunDraftResTask> list = entry.getValue();
for (AliyunDraftResTask item:list){
item.onIgnore();
}
}
}
}
@Override
public void onSuccess(final String projectPath, String coverUrl) {
//资源全部上传成功后,返回工程配置地址和封面地址
//可自行处理上传到云端,其他用户就可以通过工程配置地址恢复草稿到编辑状态
}
@Override
public void onFailure(final String msg) {
Toast.makeText(context,"备份失败",Toast.LENGTH_SHORT).show();
}
});
下载草稿
下载草稿需配合草稿服务端,服务端简单代码示例下载。
//根据草稿工程配置下载草稿相关资源,file为工程配置文件(草稿备份后从服务器下载下来的)
AliyunDraftManager.getInstance(context).downloadDraft(file, new AliyunDraftResourceDownloader() {
@Override
public void onHandleResourceTasks(final String projectDir, final List<AliyunDraftResTask> tasks) {
//待处理的草稿资源任务,需要下载草稿里面包含的资源
HashMap<String, List<AliyunDraftResTask>> map = new HashMap<>();
//过滤重复资源
for (AliyunDraftResTask task : tasks) {
if (task.getSource() == null || StringUtils.isEmpty(task.getSource().getURL())) {
task.onIgnore();
} else if (map.containsKey(task.getSource().getURL())) {
map.get(task.getSource().getURL()).add(task);
} else {
List<AliyunDraftResTask> list = new ArrayList<>();
list.add(task);
map.put(task.getSource().getURL(), list);
}
}
for (final Map.Entry<String, List<AliyunDraftResTask>> entry : map.entrySet()) {
final List<AliyunDraftResTask> list = entry.getValue();
try {
final String url = entry.getKey();
//这里需要根据url下载草稿资源
for (AliyunDraftResTask task : list) {
Source source = task.getSource();
//下载完成后回调资源本地地址
source.setPath(path);
//如果是MV则解压出ID赋值给Source供显示还原
if (task.getResModuleType() == AliyunResModuleType.MV) {
try {
source.setId(Uri.parse(url).getQueryParameter("gid"));
}catch (Exception ignored){
}
}
task.onHandleCallback(source);
}
} catch (Exception e) {
//出错
for (AliyunDraftResTask item : list) {
item.onIgnore();
}
}
}
}
@Override
public void onSuccess(final AliyunDraft draft) {
//资源全部下载完成后设置服务端ProjectID到本地草稿用来关联云端草稿
AliyunDraftManager.getInstance(context).setProjectId(draft.getId(), projectId);
Toast.makeText(context,"成功恢复到本地",Toast.LENGTH_SHORT).show();
//恢复成功后就可以在本地草稿列表查看
}
@Override
public void onFailure(final String msg) {
Toast.makeText(context,"恢复到本地失败",Toast.LENGTH_SHORT).show();
}
});
其他设置
代码中需要使用的参数详情,请参考接口文档。接口链接请参见相关类功能。
时间特效
// 1.变速
//3.7.0版本开始变速接口可以针对多段视频/图片添加
int effectId;
effectId = AliyunIEditor.rate(float rate, long startTime, long duration, boolean needOriginDuration);
// 2.反复
effectId = AliyunIEditor.repeat(int times, long startTime, long duration, boolean needOriginDuration);
//3.倒放
//特别注意:对于GOP大于5的视频需要先转码,否则将无法倒播。对于视频GOP的检查可以用NativeParser.getMaxGopSize()来获取。转码时将GOP SIZE设置为1,即CropParam.setGop(1);
effectId = AliyunIEditor.invert();
// 删除时间特效
AliyunIEditor.deleteTimeEffect(effectId);
水印
水印分为普通水印及片尾水印。普通水印会贯穿整个视频流时长,而片尾水印会在视频流结尾处添加水印。
//普通水印
AliyunIEditor.applyWaterMark(String imgPath, float sizeX, float sizeY, float posX, float posY);
//片尾水印
AliyunIEditor.addTailWaterMark(String imagePath, float sizeX, float sizeY, float posX, float posY, long durationUs);
涂鸦
短视频SDK封装了一套涂鸦接口,包含画板、画笔等,整个涂鸦操作由涂鸦控制器(AliyunICanvasController)完成。
// 获取涂鸦控制器
int width = 600;
int height = 800
AliyunICanvasController controller = AliyunIEditor.obtainCanvasController( context, width, height);
// 获取涂鸦画板
View canvasView = controller.getCanvas();
// 进行涂鸦
// 应用涂鸦
controller.applyPaintCanvas();
// 释放资源
controller.release();
//*******
//其他操作
//*******
// 撤销上一笔
controller.undo();
// 清除画布
controller.clear();
// 移除涂鸦
controller.removeCanvas();
// 判断是否由涂鸦
controller.hasCanvasPath();