全部產品
Search
文件中心

ApsaraVideo VOD:編輯視頻

更新時間:Aug 20, 2025

短視頻SDK提供視頻編輯與匯出功能,可使用視訊圖片素材混合匯入、提供濾鏡、配音、時間特效等豐富的編輯效果。

版本支援

版本

是否支援

專業版

支援所有功能。

標準版

部分支援,支援除了字幕、動態貼紙、MV以外的其他功能。

基礎版

不支援。

相關類功能

操作

類名

功能

初始化

AliyunIEditor

視頻編輯核心類。

AliyunEditorFactory

工廠類。

視頻管理

AliyunIClipConstructor

視頻來源管理員。

AliyunImageClip

圖片片段,支援JPG、PNG、GIF格式。

AliyunVideoClip

視頻片段,支援MP4、MOV、FLV格式。

設定視頻特效

EffectBean

濾鏡及MV的Model。

EffectFilter

動效濾鏡Model。

TransitionBase

轉場Model。

設定畫中畫

AliyunIPipManager

畫中畫管理類,負責畫中畫的增刪改查。

AliyunIPipController

畫中畫控制器,設定畫中畫的開始時間,結束時間。

AliyunIPipTrack

軌道資訊擷取。

AliyunILayoutController

布局控制器,對畫中畫移動、縮放、旋轉、透明度等設定。

AliyunIAnimationController

動畫控制器,可以對畫中畫做幀動畫。

AliyunIAudioController

聲音控制器,控制畫中畫音量,降噪、音效、淡入淡出等。

AliyunIAugmentationController

畫面調節控制器,可以調節飽和度、亮度、對比等。

設定字幕及動態貼紙

AliyunPasterManager

字幕及動態貼紙管理器。

AliyunPasterControllerCompoundCaption

字幕控制器。

AliyunPasterController

動態貼紙控制器。

草稿箱

AliyunEditorProject

工程配置。

AliyunDraftManager

草稿管理。

AliyunDraft

草稿。

AliyunDraftResourceLoader

資源載入器。

AliyunDraftResourceUploader

資源上傳器。

AliyunDraftResourceDownloader

資源下載器。

AliyunDraftResTask

草稿資源處理任務。

編輯視頻流程

階段

流程

說明

範例程式碼

基礎

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濾鏡、靜態濾鏡和動效濾鏡。

    • lut濾鏡:使用Lookup Table方式進行像素替換。

    • 靜態濾鏡:通過編寫著色語言方式進行像素計算,不支援帶動畫效果。Bean為EffectBean,介面參數請參考EffectBean

    • 動效濾鏡:通過編寫著色語言方式進行像素計算,帶動畫效果。Bean為EffectFilter,介面參數請參考EffectFilter

  • 目前短視頻SDK提供的轉場效果包括:TransitionCircle(圓形開啟)、TransitionFade(淡入淡出)、TransitionFiveStar(五角星)、TransitionShutter(百葉窗)、TransitionTranslate(平移)。

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支援對每路音頻流設定音效,目前提供的音效包括如下:

  • AudioEffectType.EFFECT_TYPE_LOLITA(蘿莉)

  • AudioEffectType.EFFECT_TYPE_REVERB(混響)

  • AudioEffectType.EFFECT_TYPE_UNCLE(大叔)

  • AudioEffectType.EFFECT_TYPE_ECHO(回聲)

  • AudioEffectType.EFFECT_TYPE_ROBOT(機器人)

  • AudioEffectType.EFFECT_TYPE_BIG_DEVIL(大魔王)

  • AudioEffectType.EFFECT_TYPE_MINIONS(小黃人)

  • AudioEffectType.EFFECT_TYPE_DIALECT(方言)

//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);

浮水印

浮水印分為普通浮水印及片尾浮水印。普通浮水印會貫穿整個視頻流時間長度,而片尾浮水印會在視頻流結尾處添加浮水印。

//浮水印例子 浮水印的大小為 :浮水印圖片的寬高和顯示地區的寬高比,注意保持圖片的比例,不然顯示不完全
//浮水印的位置為 :以浮水印圖片中心點為基準,顯示地區寬高的比例為位移量,0,0為左上方,1,1為右下角

//普通浮水印
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)完成。

  • 畫板:塗鴉對應的UI互動View,可以添加到UI互動的ViewGroup。

  • 畫筆:一個android.graphics.Paint對象,開發人員可以從外部設定,也可以使用預設畫筆。

// 擷取塗鴉控制器
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();