功能需求:
傳入一個videoFile也就是視頻字節流,返回騰訊云點播的視頻保存url
需要在騰訊云中尋找的配置信息:
導入的依賴:
<!--騰訊云點播--><dependency><groupId>com.tencentcloudapi</groupId><artifactId>tencentcloud-sdk-java</artifactId><version>4.0.11</version></dependency><!--騰訊云cos--><dependency><groupId>com.qcloud</groupId><artifactId>cos_api</artifactId><version>5.6.54</version></dependency>
大體分為兩步:
1.將視頻上傳到騰訊云
我們借助騰訊云依賴提供的cos客戶端,將騰訊云的id,秘鑰等配置信息傳入,再將文件信息配置到cos客戶端,發送請求,生成這個視頻的訪問路徑
2.騰訊云點播保存騰訊云中我們剛剛上傳的視頻并返回一個播放改視頻的url
同理,借助VOD客戶端上傳對應視頻
全部源代碼
package net.mingsoft.cms.biz.impl;import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.region.Region;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.vod.v20180717.VodClient;
import com.tencentcloudapi.vod.v20180717.models.*;
import net.mingsoft.base.biz.impl.BaseBizImpl;
import net.mingsoft.base.dao.IBaseDao;
import net.mingsoft.cms.biz.IVideoBiz;
import net.mingsoft.cms.dao.IVideoDao;
import net.mingsoft.cms.entity.VideoEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;/*** 視頻管理服務實現類(集成COS上傳與云點播同步)* 提供視頻上傳到騰訊云COS并同步到云點播服務功能*/
@Service("cmsVideoBizImpl")
public class VideoBizImpl extends BaseBizImpl<IVideoDao, VideoEntity> implements IVideoBiz {private static final Logger log = LoggerFactory.getLogger(VideoBizImpl.class);// 騰訊云配置信息 - 需要從配置文件或環境變量中獲取private static final String SECRET_ID = "YOUR_TENCENT_CLOUD_SECRET_ID";private static final String SECRET_KEY = "YOUR_TENCENT_CLOUD_SECRET_KEY";private static final String BUCKET_NAME = "your-bucket-name";private static final String BUCKET_REGION = "ap-region-1";private static final String COS_DOMAIN = "your-bucket.cos.ap-region-1.myqcloud.com";// 云點播配置private static final String VOD_REGION = "ap-region-1";private static final Long VOD_SUB_APP_ID = 1000000L;/*** 上傳視頻文件到騰訊云并同步到云點播* @param videoFile 視頻文件* @return 云點播播放URL* @throws IOException 文件讀取異常*/@Overridepublic String uploadVideo(MultipartFile videoFile) throws IOException {// 1. 初始化COS客戶端COSCredentials cosCred = new BasicCOSCredentials(SECRET_ID, SECRET_KEY);ClientConfig clientConfig = new ClientConfig(new Region(BUCKET_REGION));clientConfig.setHttpProtocol(HttpProtocol.https);try (COSClient cosClient = new COSClient(cosCred, clientConfig)) {// 2. 處理文件信息String originalFilename = videoFile.getOriginalFilename();String fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));// 添加目錄前綴便于管理String newFileName = "videos/" + UUID.randomUUID() + fileExtension;// 3. 上傳文件到COStry (InputStream inputStream = videoFile.getInputStream()) {ObjectMetadata metadata = new ObjectMetadata();metadata.setContentLength(videoFile.getSize());metadata.setContentType(videoFile.getContentType());PutObjectRequest putObjectRequest = new PutObjectRequest(BUCKET_NAME,newFileName,inputStream,metadata);cosClient.putObject(putObjectRequest);}log.info("視頻已成功上傳到COS,路徑:{}", newFileName);// 4. 生成COS訪問URLString cosUrl = "https://" + COS_DOMAIN + "/" + newFileName;// 5. 同步到云點播并獲取播放鏈接String playUrl = syncToVod(cosUrl, originalFilename);log.info("視頻已成功同步到云點播,播放URL: {}", playUrl);return playUrl;} catch (TencentCloudSDKException e) {log.error("云點播API調用失敗", e);throw new RuntimeException("視頻處理失敗:" + e.getMessage());}}/*** 將COS視頻同步到云點播并獲取播放鏈接* @param cosUrl COS視頻URL* @param originalFilename 原始文件名* @return 云點播播放URL*/private String syncToVod(String cosUrl, String originalFilename) throws TencentCloudSDKException {// 1. 初始化VOD客戶端Credential cred = new Credential(SECRET_ID, SECRET_KEY);HttpProfile httpProfile = new HttpProfile();httpProfile.setEndpoint("vod.tencentcloudapi.com");ClientProfile clientProfile = new ClientProfile();clientProfile.setHttpProfile(httpProfile);try (VodClient vodClient = new VodClient(cred, VOD_REGION, clientProfile)) {// 2. 拉取上傳到云點播PullUploadRequest pullRequest = new PullUploadRequest();pullRequest.setMediaUrl(cosUrl);pullRequest.setMediaName(originalFilename);pullRequest.setSubAppId(VOD_SUB_APP_ID);log.info("開始拉取上傳視頻到云點播,COS URL: {}", cosUrl);// 3. 執行拉取上傳PullUploadResponse pullResponse = vodClient.PullUpload(pullRequest);String taskId = pullResponse.getTaskId();log.info("云點播拉取上傳任務已創建,任務ID: {}", taskId);// 4. 等待任務完成并獲取文件IDString fileId = waitForTaskCompletion(vodClient, taskId);if (fileId == null) {throw new RuntimeException("云點播任務處理超時或失敗");}log.info("視頻已成功同步到云點播,文件ID: {}", fileId);// 5. 獲取播放URLreturn getPlayUrl(vodClient, fileId);}}/*** 等待云點播任務完成*/private String waitForTaskCompletion(VodClient vodClient, String taskId) throws TencentCloudSDKException {int maxRetries = 30; // 最大重試次數int retryInterval = 2000; // 重試間隔2秒for (int i = 0; i < maxRetries; i++) {try {Thread.sleep(retryInterval);DescribeTaskDetailRequest taskRequest = new DescribeTaskDetailRequest();taskRequest.setTaskId(taskId);taskRequest.setSubAppId(VOD_SUB_APP_ID);DescribeTaskDetailResponse taskResponse = vodClient.DescribeTaskDetail(taskRequest);String status = taskResponse.getStatus();if ("FINISH".equals(status)) {PullUploadTask pullUploadTask = taskResponse.getPullUploadTask();if (pullUploadTask != null) {return pullUploadTask.getFileId();} else {throw new RuntimeException("無法獲取PullUploadTask信息");}} else if ("FAIL".equals(status)) {throw new RuntimeException("云點播任務處理失敗");}} catch (InterruptedException e) {Thread.currentThread().interrupt();throw new RuntimeException("任務等待被中斷", e);}}throw new RuntimeException("云點播任務處理超時");}/*** 獲取視頻播放URL*/private String getPlayUrl(VodClient vodClient, String fileId) throws TencentCloudSDKException {DescribeMediaInfosRequest mediaRequest = new DescribeMediaInfosRequest();mediaRequest.setFileIds(new String[]{fileId});mediaRequest.setSubAppId(VOD_SUB_APP_ID);DescribeMediaInfosResponse mediaResponse = vodClient.DescribeMediaInfos(mediaRequest);if (mediaResponse.getMediaInfoSet() == null || mediaResponse.getMediaInfoSet().length == 0) {throw new RuntimeException("未找到視頻信息,文件ID: " + fileId);}MediaInfo mediaInfo = mediaResponse.getMediaInfoSet()[0];return mediaInfo.getBasicInfo().getMediaUrl();}/*** 獲取轉碼后的播放URL(可選)*/private String getTranscodePlayUrl(VodClient vodClient, String fileId) throws TencentCloudSDKException {DescribeMediaInfosRequest mediaRequest = new DescribeMediaInfosRequest();mediaRequest.setFileIds(new String[]{fileId});mediaRequest.setSubAppId(VOD_SUB_APP_ID);DescribeMediaInfosResponse mediaResponse = vodClient.DescribeMediaInfos(mediaRequest);return mediaResponse.getMediaInfoSet()[0].getBasicInfo().getMediaUrl();}@Overrideprotected IBaseDao<VideoEntity> getDao() {return null;}
}