全部產品
Search
文件中心

ApsaraVideo VOD:使用阿里雲播放器實現全屏秒播

更新時間:Jul 13, 2024

基於阿里雲播放器SDK的預先載入能力和點播設定視頻封面等策略的搭配使用,可實現視頻毫秒級的起播速度,能有效解決短視頻情境中的視頻起播慢,切換視訊卡頓等問題,為使用者呈現無感起播和流暢絲滑的播放體驗。本文介紹如何使用阿里雲播放器SDK實現全屏秒播。

方案原理

播放視頻時,在起播階段因載入視頻需要一定的時間,因此播放可能會出現一段黑屏的時間。一方面,可以通過開啟阿里雲播放器的預先載入功能以及通過預熱視頻資源來提升視頻的起播速度。另一方面,由於圖片的載入速度比視頻載入速度快的更多,此時如果設定了視頻封面圖,則起播階段視頻還未載入出來時,可以由封面圖佔據播放頁面直到視頻載入出來開始播放,從而避免視頻黑屏的視覺效果;而通過將視頻的首幀截圖設定為視頻封面,使使用者感覺不到視頻封面的存在,以達到視頻秒開極快的視覺效果。

通過此方案,在WiFi環境下可以實現使用阿里雲播放器播放視頻達到平均300毫秒左右的起播速度。

使用限制

  • 目前僅支援通過阿里雲Android播放器SDK和iOS播放器SDK實現全屏秒播。

  • 目前僅支援MP4、MP3、FLV、HLS(單碼率視頻流)等單個媒體檔案實現預先載入功能。

  • 預先載入僅支援使用UrlSource方式播放視頻,暫不支援VidAuth、VidSts方式播放視頻。

前提條件

步驟一:開啟阿里雲播放器SDK的預先載入功能

阿里雲播放器SDK的預先載入功能,通過提前將視頻資料載入到本地,來提升視頻的起播速度。

使用限制

  • 目前支援MP4、MP3、FLV、HLS(單碼率視頻流)等單個媒體檔案的載入。

  • 僅支援UrlSource播放方式播放視頻的預先載入,暫不支援VidAuth、VidSts方式播放視頻的預先載入。

Android播放器配置

  1. 開啟本機快取功能。

    /app/src/main/java/com/aliyun/alivcsolution/MutiApplication.java檔案中,通過AliPlayerGlobalSettings.enableLocalCache開啟。

    public class MutiApplication extends Application {
    
        @Override
        protected void attachBaseContext(Context base) {
            super.attachBaseContext(base);
            MultiDex.install(this);
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            //開啟本機快取,本機快取檔案路徑,為絕對路徑,下述樣本為/tmp,下述樣本中10240對應的參數在5.4.7.1及以後版本已廢棄,暫無作用
            AliPlayerGlobalSettings.enableLocalCache(true,10240,"/tmp");
    
          
        }
    
    }
  2. 建立預先載入單例,並在初始化時設定預先載入的回呼函數。

    /AliyunListPlayer/src/main/java/com/aliyun/player/aliyunlistplayer/AliyunListPlayerActivity.java檔案中建立。

    public class AliyunListPlayerActivity extends AppCompatActivity {
    
        private AliyunListPlayerView mListPlayerView;
        private NetWatchdog mNetWatchDog;
        private String mUserToken;
        private boolean mIsLoadMore = false;
        private int mLastVideoId = -1;
        private ImageView mBackImageView;
        
        //建立預先載入單例
        private MediaLoader medialoader=MediaLoader.getInstance();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_aliyun_list_player);
            mUserToken = getIntent().getStringExtra("list_player_user_token");
    
            initView();
            initSts(true);
            initListener();
    
    
            //設定載入狀態回調
            medialoader.setOnLoadStatusListener(new MediaLoader.OnLoadStatusListener() {
                @Override
                public void onError(String url, int code, String msg) {
                    //載入出錯
                }
    
                @Override
                public void onCompleted(String s) {
                    //載入完成
                }
    
                @Override
                public void onCanceled(String s) {
                    //載入取消
                }
            });
        }
        ...
  3. 在請求資料響應時,調用load函數實現預先載入資料存放區到指定磁碟路徑中。

    private void getDatas(int id){
            GetVideoInfomation getVideoInfomation = new GetVideoInfomation();
            getVideoInfomation.getListPlayerVideoInfos(this, "1", mUserToken, id, new GetVideoInfomation.OnGetListPlayerVideoInfosListener() {
                private SparseArray<String> mSparseArray;
                @Override
                public void onGetSuccess(Request request, String result) {
                    //demo列表播放器實現中,僅根據video id請求視頻資料
                    //但是預先載入只能通過url實現,不能通過video id預先載入視頻資料
                    //這裡只是做一個說明,在拿到url後,如何通過medialoader實現預先載入
                    String url="";//假設這裡拿到了視頻url
                    medialoader.load(url,10000);//預先載入資料存放區到指定磁碟路徑中,載入時間長度為10000毫秒
    
                    Gson gson = new Gson();
                    AliyunVideoListBean aliyunVideoListBean = gson.fromJson(result, AliyunVideoListBean.class);
                    
                    ...

iOS播放器配置

  1. 在初始化時,開啟本機快取功能並設定預先載入的回呼函數。

    - (AliPlayer *)aliPlayer{
        if (!_aliPlayer && UIApplicationStateActive == [[UIApplication sharedApplication] applicationState]) {
            _aliPlayer = [[AliPlayer alloc] init];
            _aliPlayer.scalingMode =  AVP_SCALINGMODE_SCALEASPECTFIT;
            _aliPlayer.rate = 1;
            _aliPlayer.delegate = self;
            _aliPlayer.playerView = self.playerView;
    
            //開啟本機快取,本機快取檔案路徑沙箱路徑,maxBufferMemoryKB對應的10240對應的參數在5.4.7.1及以後版本已廢棄,暫無作用
            NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
            [AliPlayerGlobalSettings enableLocalCache:YES maxBufferMemoryKB:10*1024 localCacheDir:[docDir stringByAppendingPathComponent:@"alivcCache"]];
            [AliPlayerGlobalSettings setCacheFileClearConfig:30*60*24 maxCapacityMB:20480 freeStorageMB:0];
            //設定url回調方法,這裡避免預先載入時的url和播放時的url由於參數的變化導致不一致造成預先載入失效
            [AliPlayerGlobalSettings setCacheUrlHashCallback:hashCallback];
            
            //設定回調代理
            [[AliMediaLoader shareInstance] setAliMediaLoaderStatusDelegate:self];
    
        }
        return _aliPlayer;
    }
    
    //設定url回調方法
    NSString* hashCallback(NSString* url){
        NSString *md5Str = [NSString aliyun_MD5:url];
        return md5Str;
    }
    
    //預先載入的回調方法
    #pragma mark -- AliMediaLoaderStatusDelegate
    /**
     @brief 錯誤回調
     @param url 載入url
     @param code 錯誤碼
     @param msg 錯誤描述
     */
    - (void)onError:(NSString *)url code:(int64_t)code msg:(NSString *)msg {
        
    }
    
    /**
     @brief 完成回調
     @param url 載入url
     */
    - (void)onCompleted:(NSString *)url {
        
    }
    
    /**
     @brief 取消回調
     @param url 載入url
     */
    - (void)onCanceled:(NSString *)url {
        
    }

  2. 設定資料來源時,調用load函數實現預先載入資料存放區到指定磁碟路徑。

    NSString *urlString = @"<url地址>";
    AVPUrlSource *urlSource = [[AVPUrlSource alloc] urlWithString:urlString];
    [_aliPlayer setUrlSource:urlSource];
    [[AliMediaLoader shareInstance] load:urlString duration:10000];//預先載入資料存放區到指定磁碟路徑中,載入時間長度樣本為10000毫秒

步驟二:設定視頻首幀截圖為視頻封面

通過將視頻首幀截圖設定為視頻封面,以達到視頻秒開極快的視覺效果。

說明

當使用阿里雲播放器播放視頻時,在列表播放的情境下,您可以結合視頻封面設定如下播放邏輯來達到秒開的視覺效果並節省流量。

  • 當使用者快速滑動切換視訊時,僅僅只請求視頻封面圖。

  • 當使用者切換下一個視頻滑動到一半時,展示預先下載的視頻封面圖。

控制台方式配置

  1. 建立截取視頻首幀的截圖模板。

    1. 登入ApsaraVideo for VOD控制台

    2. 在左側導覽列選擇組態管理 > ApsaraVideo for Media Processing配置 > 截圖模板,進入到截圖模板頁面。

    3. 單擊添加截圖模板,配置截取視頻首幀截圖的模板參數。

      模板名稱請自訂設定,截圖方式選擇普通截圖起始時間點設定為00:00:00,截圖數量設定為1,其餘參數請按需配置,有關截圖模板的參數解釋,詳情請參見截圖模板首幀截圖1.png

    4. 單擊儲存,完成截圖模板的建立。

  2. 發起截取視頻首幀的截圖任務。

    說明
    • 通過控制台方式發起截圖任務時,只能通過工作流程的方式發起,因此,您需要先建立一個包含視頻首幀截圖任務的工作流程(即在工作流程中添加視頻截圖節點,並設定截圖模板為上一步建立的首幀截圖模板)。工作流程的建立方法,請參見工作流程管理

    • 建議您發起截圖任務之前,配置ApsaraVideo for VOD的事件通知,通過設定視頻截圖完成的事件通知,以便在截圖任務完成後,能擷取到截圖任務的狀態及截取的圖片地址等資訊。事件通知的配置方法,請參見回調設定

    • 情境一:上傳視頻時截圖

      1. 在ApsaraVideo for VOD控制台,從左側導覽列選擇媒資庫 > 音/視頻

      2. 單擊上傳音/視頻,單擊添加音/視頻

      3. 按需設定上傳方式、儲存地址並添加上傳的視頻後,選擇用工作流程處理,並選擇預先建立的包含首幀截圖任務的工作流程。

      4. 單擊開始上傳

    • 情境二:上傳視頻後截圖

      1. 在ApsaraVideo for VOD控制台,從左側導覽列選擇媒資庫 > 音/視頻

      2. 在音/視頻列表頁面,單擊目標視頻所在行的ApsaraVideo for Media Processing

      3. 處理類型選擇用工作流程處理工作流程選擇預先建立的包含首幀截圖任務的工作流程。

      4. 單擊確定

    • 擷取截圖結果

      • 如果您已經配置了ApsaraVideo for VOD的視頻截圖完成的事件通知,您可以從回調事件中擷取到截圖任務的狀態及截取的圖片地址等資訊。

      • 如果您未配置事件通知,您可以使用輪詢的方式調用ListSnapshots - 查詢視頻截圖資料介面來查詢截圖任務的狀態及截取的圖片地址等資訊。

  3. 修改視頻封面為視頻首幀截圖。

    說明

    通過控制台方式修改視頻封面,只支援在視頻上傳完成後對視頻封面進行更新。您需要先將步驟2中截圖任務截取到的視頻首幀截圖儲存到本地以便修改封面時上傳。

    1. 在ApsaraVideo for VOD控制台,從左側導覽列選擇媒資庫 > 音/視頻

    2. 在音/視頻列表頁面,單擊目標視頻所在行的管理

    3. 基礎資訊頁簽,單擊編輯視頻資訊

    4. 單擊上傳封面,選擇預先儲存到本地的視頻首幀截圖,單擊開啟

    5. 單擊儲存,完成視頻封面設定。

      設定完成後,您可以在音/視頻列表頁面查看視頻封面是否更新成功。

OpenAPI方式配置

說明

本文以使用Java語言的阿里雲 SDK方式調用ApsaraVideo for VOD的OpenAPI為例進行舉例說明。

操作步驟

  1. 建立截取視頻首幀的截圖模板。

    調用AddVodTemplate - 添加截圖或動圖模板介面,建立截取視頻首幀的截圖模板。調用樣本如下:

    import com.aliyuncs.DefaultAcsClient;
    import com.aliyuncs.exceptions.ClientException;
    import com.aliyuncs.profile.DefaultProfile;
    import com.aliyuncs.vod.model.v20170321.AddVodTemplateRequest;
    import com.aliyuncs.vod.model.v20170321.AddVodTemplateResponse;
    
    
    /**
     * 說明:
     * 1. 本Demo為建立首幀截圖模板樣本,截圖輸出為 1 張圖片。
     * 2. 推薦使用ApsaraVideo for VOD控制台建立截圖模板,更加方便快捷。
     */
    public class AddSnapshotTemplate {
    
        // 阿里雲帳號AccessKey擁有所有API的存取權限,建議您使用RAM使用者進行API訪問或日常營運。
        // 強烈建議不要把AccessKey ID和AccessKey Secret儲存到工程代碼裡,否則可能導致AccessKey泄露,威脅您帳號下所有資源的安全。
        // 本樣本通過從環境變數中讀取AccessKey,來實現API訪問的身分識別驗證。運行程式碼範例前,請配置環境變數ALIBABA_CLOUD_ACCESS_KEY_ID和ALIBABA_CLOUD_ACCESS_KEY_SECRET。
        public static String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
        public static String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
    
        public static void main(String[] args) {
    
            try{
                DefaultAcsClient vodClient = initVodClient(accessKeyId, accessKeySecret);
                AddVodTemplateResponse response = addSnapshotTemplate(vodClient);
                System.out.println("RequestId is:" + response.getRequestId());
                System.out.println("TemplateId is:" + response.getVodTemplateId());
            }catch (Exception e){
    
            }
        }
    
        public static AddVodTemplateResponse addSnapshotTemplate(DefaultAcsClient vodClient) throws ClientException {
            AddVodTemplateRequest request = new AddVodTemplateRequest();
            request.setName("首幀截圖模板");
            request.setTemplateType("Snapshot");
            request.setTemplateConfig("{\"SnapshotType\":\"NormalSnapshot\",\"SnapshotConfig\":{\"FrameType\":\"normal\",\"Count\":1,\"Interval\":1,\"SpecifiedOffsetTime\":0}}");
    
            return vodClient.getAcsResponse(request);
        }
    
        public static DefaultAcsClient initVodClient(String accessKeyId, String accessKeySecret) throws ClientException {
            // 點播服務接入地區
            String regionId = "cn-shanghai";  
            DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
            DefaultAcsClient client = new DefaultAcsClient(profile);
    
            return client;
        }
    }
    
  2. 發起截取視頻首幀的截圖任務。

    調用SubmitSnapshotJob - 提交媒體截圖作業介面,發起截圖任務。調用樣本如下:

    import com.aliyuncs.DefaultAcsClient;
    import com.aliyuncs.exceptions.ClientException;
    import com.aliyuncs.profile.DefaultProfile;
    import com.aliyuncs.vod.model.v20170321.*;
    
    /**
     * 說明:
     * 1. 本Demo為建立首幀截圖模板後,提交首幀截圖任務。
     * 2. 對於新上傳的視頻,建議該步驟放在【音視頻分析完成】事件成功之後,對於存量且狀態正常的視頻,可自行設計。
     * 3. 截圖為非同步任務,需要等到【視頻截圖完成】事件成功之後(推薦),可擷取截圖地址。
     * 4. 根據回調事件中的SnapshotRegular,可推測出截圖輸出地址。詳情請參見【視頻截圖完成】文檔中的截圖地址建置規則說明。
     * 5. 若您暫無回調服務,也可以通過ListSnapshots介面主動查詢,該介面預設只返回最新一次的截圖結果。詳情請參見ListSnapshots介面文檔。
     */
    public class SubmitSnapshotJob {
    
        // 阿里雲帳號AccessKey擁有所有API的存取權限,建議您使用RAM使用者進行API訪問或日常營運。
        // 強烈建議不要把AccessKey ID和AccessKey Secret儲存到工程代碼裡,否則可能導致AccessKey泄露,威脅您帳號下所有資源的安全。
        // 本樣本通過從環境變數中讀取AccessKey,來實現API訪問的身分識別驗證。運行程式碼範例前,請配置環境變數ALIBABA_CLOUD_ACCESS_KEY_ID和ALIBABA_CLOUD_ACCESS_KEY_SECRET。
        public static String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
        public static String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
    
        public static void main(String[] args) {
    
            try{
                DefaultAcsClient vodClient = initVodClient(accessKeyId, accessKeySecret);
                SubmitSnapshotJobResponse response = submitSnapshotJob(vodClient);
                System.out.println("RequestId is:" + response.getRequestId());
                System.out.println("JobId is:" + response.getSnapshotJob().getJobId());
            }catch (Exception e){
    
            }
        }
    
        public static SubmitSnapshotJobResponse submitSnapshotJob(DefaultAcsClient vodClient) throws ClientException {
            SubmitSnapshotJobRequest request = new SubmitSnapshotJobRequest();
            request.setVideoId("a42b**********633b79f0102");
            request.setSnapshotTemplateId("1f27a7**********eba2756");
            //自訂透傳參數,回調時可用,非必須,用於區分封面首幀截圖
            request.setUserData("{\"Extend\":{\"SnapshotType\":\"FirstFrame\",\"VideoId\":\"a42bf540********33b79f0102\"}}");
            return vodClient.getAcsResponse(request);
        }
    
        public static DefaultAcsClient initVodClient(String accessKeyId, String accessKeySecret) throws ClientException {
            // 點播服務接入地區
            String regionId = "cn-shanghai";  
            DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
            DefaultAcsClient client = new DefaultAcsClient(profile);
    
            return client;
        }
    
        //ListSnapshots 查詢截圖
        public static ListSnapshotsResponse listSnapshots(DefaultAcsClient vodClient) throws ClientException {
            ListSnapshotsRequest request = new ListSnapshotsRequest();
            request.setVideoId("a42bf540b1b371ed804a6633b79****");
            request.setSnapshotType("NormalSnapshot");
    
            ListSnapshotsResponse response = vodClient.getAcsResponse(request);
            System.out.println("RequestId is:" + response.getRequestId());
            System.out.println("SnapshotUrl is:" + response.getMediaSnapshot().getSnapshots().get(0).getUrl());
            return vodClient.getAcsResponse(request);
        }
    
    }
    
  3. 修改視頻封面為視頻首幀截圖。

    此處以視頻上傳完成後,修改單個視頻封面的情境為例進行說明,其他情境的實現,請參見上傳視頻時設定封面視頻上傳後更新封面

    通過調用UpdateVideoInfo - 修改單個音視頻資訊介面,傳入CoverURL參數指定視頻封面。調用樣本如下:

    package com.alibaba.bltest.transcode;
    
    import com.aliyuncs.DefaultAcsClient;
    import com.aliyuncs.exceptions.ClientException;
    import com.aliyuncs.profile.DefaultProfile;
    import com.aliyuncs.vod.model.v20170321.UpdateVideoInfoRequest;
    import com.aliyuncs.vod.model.v20170321.UpdateVideoInfoResponse;
    
    /**
     * 說明:
     * 1. 本Demo為修改單個視頻封面,如需修改其他視頻參數,請參見UpdateVideoInfo的介面文檔。
     * 2. 對於修改封面的情境,請確保您使用的圖片地址是有效。
     */
    public class UpdateVideoInfo {
    
        // 阿里雲帳號AccessKey擁有所有API的存取權限,建議您使用RAM使用者進行API訪問或日常營運。
        // 強烈建議不要把AccessKey ID和AccessKey Secret儲存到工程代碼裡,否則可能導致AccessKey泄露,威脅您帳號下所有資源的安全。
        // 本樣本通過從環境變數中讀取AccessKey,來實現API訪問的身分識別驗證。運行程式碼範例前,請配置環境變數ALIBABA_CLOUD_ACCESS_KEY_ID和ALIBABA_CLOUD_ACCESS_KEY_SECRET。
        public static String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
        public static String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
    
        public static void main(String[] args) {
    
            try{
                DefaultAcsClient vodClient = initVodClient(accessKeyId, accessKeySecret);
                UpdateVideoInfoResponse response = updateVideoInfo(vodClient);
                System.out.println("RequestId is:" + response.getRequestId());
            }catch (Exception e){
    
            }
        }
    
        public static UpdateVideoInfoResponse updateVideoInfo(DefaultAcsClient vodClient) throws ClientException {
            UpdateVideoInfoRequest request = new UpdateVideoInfoRequest();
            request.setVideoId("a42b***********33b79f0102");
            //設定首幀封面時,CoverURL為首幀截圖任務成功後輸出的圖片地址
            request.setCoverURL("http://demo.aliyuncdn.com/a42bf5******40b1b37/snapshots/normal/41B7AF54-18672BB301D-1748-0984-309-112420****.jpg");
    
            return vodClient.getAcsResponse(request);
        }
    
        public static DefaultAcsClient initVodClient(String accessKeyId, String accessKeySecret) throws ClientException {
            // 點播服務接入地區
            String regionId = "cn-shanghai";  
            DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
            DefaultAcsClient client = new DefaultAcsClient(profile);
            return client;
        }
    }
    

完整執行個體

package com.alibaba.bltest.transcode;


import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.vod.model.v20170321.*;
import org.apache.commons.lang3.StringUtils;

/**
 * 說明:
 * 1. 本Demo為完整截圖+修改封面邏輯設計,部分代碼需要根據自己商務邏輯自行修改。
 * 2. 本Demo非直接可用,部分邏輯需要自行補充。
 * 3. 本Demo僅供實現參考,不代表唯一實現方式。
 */
public class SnapshotAndUpdateCover {

    // 阿里雲帳號AccessKey擁有所有API的存取權限,建議您使用RAM使用者進行API訪問或日常營運。
    // 強烈建議不要把AccessKey ID和AccessKey Secret儲存到工程代碼裡,否則可能導致AccessKey泄露,威脅您帳號下所有資源的安全。
    // 本樣本通過從環境變數中讀取AccessKey,來實現API訪問的身分識別驗證。運行程式碼範例前,請配置環境變數ALIBABA_CLOUD_ACCESS_KEY_ID和ALIBABA_CLOUD_ACCESS_KEY_SECRET。
    public static String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
    public static String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");

    public static void main(String[] args) {


        try{
            DefaultAcsClient vodClient = initVodClient(accessKeyId, accessKeySecret);
            //視頻ID
            String videoId = "a42bf540b1b37*******b79f0102";

            //情境一:有回調服務 或 MNS
            //若是為新上傳的視頻設定封面,則需要先擷取到音視頻分析成功事件
            //若是為存量視頻設定封面,則可以直接從此步驟開始提交截圖任務
            submitSnapshotJob(vodClient,videoId);

            //擷取到視頻截圖成功事件,判斷截圖類型,取得需要的圖片URL
            JSONObject callBackMessage = new JSONObject();  //此處替換為回調服務收到的message
            String snapshotType = callBackMessage.getJSONObject("UserData").getJSONObject("Extend").getString("SnapshotType");
            if("FirstFrame".equals(snapshotType)){

                //這裡的截圖路徑邏輯需要根據您自行定義的截圖路徑邏輯來替換
                String coverUrl = callBackMessage.getJSONArray("SnapshotInfos").getJSONObject(0).getString("SnapshotRegular").replace("{SnapshotCount}","00001");
                //修改視頻封面
                updateVideoInfo(vodClient,videoId,coverUrl);
            }

            //情境二:無回調服務 或 MNS
            //若是為新上傳的視頻設定封面,則視頻上傳後,輪詢視頻狀態
            String videoStatus = "";
            while(!"Normal".equals(videoStatus)){
                videoStatus = getVideoInfo(vodClient,videoId);
                Thread.sleep(1000);
            }

            //若是為存量視頻設定封面,則可以直接從此步驟開始提交截圖任務
            submitSnapshotJob(vodClient,videoId);

            //輪詢截圖結果
            String coverUrl = "";
            while(StringUtils.isBlank(coverUrl)){
                coverUrl = listSnapshots(vodClient,videoId);
                Thread.sleep(1000);
            }

            //修改視頻封面
            updateVideoInfo(vodClient,videoId,coverUrl);
        }catch (Exception e){

        }
    }

    /**
     * 提交截圖任務
     */
    public static SubmitSnapshotJobResponse submitSnapshotJob(DefaultAcsClient vodClient, String vid) throws ClientException {
        SubmitSnapshotJobRequest request = new SubmitSnapshotJobRequest();
        request.setVideoId(vid);
        request.setSnapshotTemplateId("1f27a7f*********70eba2756");
        //自訂透傳參數,回調時可用,非必須,用於區分封面首幀截圖
        request.setUserData("{\"Extend\":{\"SnapshotType\":\"FirstFrame\",\"VideoId\":\"a42bf540********33b79f0102\"}}");

        return vodClient.getAcsResponse(request);
    }

    /**
     * 修改視頻封面
     */
    public static UpdateVideoInfoResponse updateVideoInfo(DefaultAcsClient vodClient, String vid, String coverUrl) throws ClientException {
        UpdateVideoInfoRequest request = new UpdateVideoInfoRequest();
        request.setVideoId(vid);
        //設定首幀封面時,CoverURL為首幀截圖任務成功後輸出的圖片地址
        request.setCoverURL(coverUrl);

        return vodClient.getAcsResponse(request);
    }

    /**
     * 初始化sdk執行個體
     */
    public static DefaultAcsClient initVodClient(String accessKeyId, String accessKeySecret) throws ClientException {
        // 點播服務接入地區
        String regionId = "cn-shanghai";  
        DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
        DefaultAcsClient client = new DefaultAcsClient(profile);

        return client;
    }

    /**
     * 查詢截圖
     */
    public static String listSnapshots(DefaultAcsClient vodClient, String vid) throws ClientException {
        ListSnapshotsRequest request = new ListSnapshotsRequest();
        request.setVideoId(vid);
        request.setSnapshotType("NormalSnapshot");

        ListSnapshotsResponse response = vodClient.getAcsResponse(request);
        String coverUrl = "";
        System.out.println("RequestId is:" + response.getRequestId());
        try{
            coverUrl = response.getMediaSnapshot().getSnapshots().get(0).getUrl();
            System.out.println("SnapshotUrl is:" + response.getMediaSnapshot().getSnapshots().get(0).getUrl());
        }catch (NullPointerException e){

        }
        return coverUrl;
    }

    /**
     * 查詢單個視頻
     */
    public static String getVideoInfo(DefaultAcsClient vodClient, String vid) throws ClientException {
        GetVideoInfoRequest request = new GetVideoInfoRequest();
        request.setVideoId(vid);

        GetVideoInfoResponse response = vodClient.getAcsResponse(request);
        System.out.println("RequestId is:" + response.getRequestId());
        String videoStatus = "";
        try{
            videoStatus = response.getVideo().getStatus();
            System.out.println("Video Status is:" + response.getVideo().getStatus());
        }catch (NullPointerException e){

        }

        return videoStatus;
    }
}

步驟三:(可選)預熱視頻資源

通過ApsaraVideo for VOD的預熱功能,將視頻資源提前緩衝到CDN節點上,使用者請求播放視頻時,可以直接從CDN節點擷取到最新的資源,無需再回來源站點擷取,從而提升使用者請求播放的響應速度,有利於播放器預先載入的實現。

說明

由於重新整理預熱有一定的回源流量成本,可根據視頻熱度進行預熱,將視頻主動預熱在阿里雲各個節點上。

控制台方式配置

  1. 登入ApsaraVideo for VOD控制台

  2. 在左側導覽列選擇組態管理 > 分發加速配置 > 重新整理預熱,進入到重新整理預熱頁面。

  3. 重新整理緩衝頁簽,配置預熱資訊。

    • 操作類型:選擇預熱

    • 重新整理類型:固定為URL

    • URL:輸入待預熱的視頻資源的URL。輸入的URL必須帶有http://https://。同一個帳號每天最多預熱500個URL,每次最多隻能提交100條。

  4. 單擊提交,完成預熱配置。

OpenAPI方式配置

  1. 調用PreloadVodObjectCaches - 預熱緩衝介面實現預熱視頻資源。

步驟四:使用阿里雲播放器播放視頻

使用阿里雲播放器通過UrlSource方式播放視頻。