全文目錄,一步到位
- 1.前言簡介
- 1.1 專欄傳送門
- 1.1.1 文檔傳送門
- 2. java基礎使用
- 2.1 準備工作
- 2.1.1 云控制臺獲取(密鑰和密鑰secret)
- 2.1.2 找到trtc控制臺
- 2.1.3 vod云點播控制臺
- 2.2 使用準備的數據進行操作
- 2.2.0 引入依賴
- 2.2.1 創建TrtcUtils工具類
- 2.2.2 TrtcReqDTO 錄制請求dto
- 2.2.3 TrtcCommonReqDto 請求dto
- 2.2.4 OrderTrtcVideo 數據庫存儲實體類
- 2.2.5 獲取用戶usersig(舊版)
- 2.3 業務使用方式
- 2.3.0 json傳遞數據
- 2.3.1 創建service方法
- 2.3.2 TrtcServiceImpl 實現類
- 2.3.4 上傳后視頻效果
- 3. 文章的總結與預告
- 3.1 本文總結
- 3.2 代碼指正
1.前言簡介
騰訊trtc
合流模式
使用 如果時單流 可在控制臺直接設置
1.1 專欄傳送門
1.1.1 文檔傳送門
===> 傳送門: api文檔-官網地址
2. java基礎使用
2.1 準備工作
2.1.1 云控制臺獲取(密鑰和密鑰secret)
===> 騰訊云控制臺登錄 傳送門<===
如圖所示
2.1.2 找到trtc控制臺
===> im控制臺 傳送門 <===
創建sdkAppId 開通需要的服務
2.1.3 vod云點播控制臺
===> vod云點播控制臺地址
- 創建視頻生成模板
- 創建任務流綁定視頻模板
--------> 如圖所示
2.2 使用準備的數據進行操作
2.2.0 引入依賴
trtc包和vod包
源碼位置: 源碼gitee地址
<!-- # 版本在maven生效需要時間,如獲取不到對應的版本,可以調低版本號--><dependency><groupId>com.tencentcloudapi</groupId><artifactId>tencentcloud-sdk-java-trtc</artifactId><version>3.1.1218</version></dependency><!-- # 版本在maven生效需要時間,如獲取不到對應的版本,可以調低版本號--><dependency><groupId>com.tencentcloudapi</groupId><artifactId>tencentcloud-sdk-java-vod</artifactId><version>3.1.1212</version></dependency>
2.2.1 創建TrtcUtils工具類
缺少的包可以忽略 刪除都可以
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import com.google.common.base.Objects;
import com.tencentcloudapi.common.AbstractModel;
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.trtc.v20190722.TrtcClient;
import com.tencentcloudapi.trtc.v20190722.models.*;
import com.tencentcloudapi.vod.v20180717.VodClient;
import com.tencentcloudapi.vod.v20180717.models.*;import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.util.CollectionUtils;import java.util.List;/*** trtc工具類* 這里的常量就不大寫了* @author pzy* @version 0.1.1*/
@Slf4j
public class TrtcUtils {/*** 密鑰key*/private static final String secretId = "";/*** 密鑰secret*/private static final String secretKey = "";/*** 請求節點*/private static final String trtcEndPoint = "trtc.tencentcloudapi.com";/*** sdk 的 appid*/public static final String SDKAppID = "";//vod-------------------------------------------------------->private static final String vodEndPoint = "vod.tencentcloudapi.com";/*** vod任務模板名稱*/public static final String vodTaskTemplateName = "";/*** vod的subAppId*/public static final Long vodSubAppId = ;/*** 0. 獲取trtc客戶端對象(不對外)*/private static TrtcClient getTrtcClient() {// 實例化一個client選項,可選的,沒有特殊需求可以跳過ClientProfile clientProfile = new ClientProfile();// 實例化一個http選項,可選的,沒有特殊需求可以跳過HttpProfile httpProfile = new HttpProfile();httpProfile.setEndpoint(trtcEndPoint);clientProfile.setHttpProfile(httpProfile);// 實例化一個認證對象,入參需要傳入騰訊云賬戶 SecretId 和 SecretKey,此處還需注意密鑰對的保密// 代碼泄露可能會導致 SecretId 和 SecretKey 泄露,并威脅賬號下所有資源的安全性。以下代碼示例僅供參考,建議采用更安全的方式來使用密鑰,請參見:https://cloud.tencent.com/document/product/1278/85305// 密鑰可前往官網控制臺 https://console.cloud.tencent.com/cam/capi 進行獲取Credential cred = new Credential(secretId, secretKey);return new TrtcClient(cred, "ap-beijing", clientProfile);}/*** 1. 開啟TRTC云錄制功能*/@SneakyThrowspublic static CreateCloudRecordingResponse sendTrtcRecord(CreateCloudRecordingRequest req) {//獲取trtc客戶端對象TrtcClient trtcClient = getTrtcClient();// 返回的resp是一個CreateCloudRecordingResponse的實例,與請求對象對應CreateCloudRecordingResponse resp = trtcClient.CreateCloudRecording(req);// 輸出json格式的字符串回包log.info("===> 開啟TRTC云錄制功能-響應信息: {}" + AbstractModel.toJsonString(resp));return resp;}/*** 2. 停止TRTC云端錄制任務*/@SneakyThrowspublic static Object functionCloudRecording(TrtcCommonReqDto trtcCommonReqDto) {String taskId = trtcCommonReqDto.getTaskId();Assert.notNull(taskId, () -> new ServiceException("請傳遞任務id后重試~"));// 實例化要請求產品的client對象,clientProfile是可選的TrtcClient client = getTrtcClient();/* 功能類型 1 停止錄制(默認) 2查詢錄制狀態 */Long sdkAppId = Long.valueOf(SDKAppID);if (Objects.equal(trtcCommonReqDto.getFunctionType(), "1")) {DeleteCloudRecordingRequest req = new DeleteCloudRecordingRequest();req.setSdkAppId(sdkAppId);req.setTaskId(taskId);// 返回的resp是一個DeleteCloudRecordingResponse的實例,與請求對象對應DeleteCloudRecordingResponse resp = client.DeleteCloudRecording(req);// 輸出json格式的字符串回包log.info("===> 停止TRTC云端錄制任務-響應信息: {}" , AbstractModel.toJsonString(resp));return resp;}/* 功能類型 1 停止錄制(默認) 2查詢錄制狀態 */if (Objects.equal(trtcCommonReqDto.getFunctionType(), "2")) {// 實例化一個請求對象,每個接口都會對應一個request對象DescribeCloudRecordingRequest req = new DescribeCloudRecordingRequest();req.setSdkAppId(sdkAppId);req.setTaskId(taskId);// 返回的resp是一個DescribeCloudRecordingResponse的實例,與請求對象對應DescribeCloudRecordingResponse resp = client.DescribeCloudRecording(req);log.info("===> 查詢TRTC云端錄制任務狀態-響應信息: {}" + AbstractModel.toJsonString(resp));return resp;}throw new ServiceException("抱歉,類型不存在,請重試呦~");}/*** 3. vod云點播地址獲取 通過roomId(暫不優化)*/@SneakyThrowspublic static SearchMediaResponse getVodAddressUrl(TrtcCommonReqDto trtcCommonReqDto) {Credential cred = new Credential(secretId, secretKey);// 實例化一個http選項,可選的,沒有特殊需求可以跳過HttpProfile httpProfile = new HttpProfile();httpProfile.setEndpoint(vodEndPoint);// 實例化一個client選項,可選的,沒有特殊需求可以跳過ClientProfile clientProfile = new ClientProfile();clientProfile.setHttpProfile(httpProfile);// 實例化要請求產品的client對象,clientProfile是可選的VodClient client = new VodClient(cred, "ap-guangzhou", clientProfile);// 實例化一個請求對象,每個接口都會對應一個request對象SearchMediaRequest req = new SearchMediaRequest();req.setSubAppId(vodSubAppId);List<String> roomIds = trtcCommonReqDto.getRoomIds();if (CollectionUtils.isEmpty(roomIds)) {return new SearchMediaResponse();}String[] trtcRoomIds1 = roomIds.toArray(new String[0]);req.setTrtcRoomIds(trtcRoomIds1);// 返回的resp是一個SearchMediaResponse的實例,與請求對象對應SearchMediaResponse resp = client.SearchMedia(req);// 輸出json格式的字符串回包log.info("===> 查詢Vod云端視頻信息: {}", AbstractModel.toJsonString(resp));return resp;}/*** 查詢vod云點播地址并封裝對象 (根據訂單和房間號存入)* <p>* ps: 失敗也存,最好異步或者延時調用, 不是立即生成的* -> 優化: 增加重試機制,現在默認好用*/public static List<OrderTrtcVideo> getVodUrlByRoomInOrder(TrtcCommonReqDto trtcCommonReqDto) {String orderRegisterId = trtcCommonReqDto.getOrderRegisterId();SearchMediaResponse searchMediaResponse = TrtcUtils.getVodAddressUrl(trtcCommonReqDto);//處理數據List<OrderTrtcVideo> orderTrtcVideoList = Lists.newArrayList();/*校驗: totalCounts是0 則查詢失敗*/MediaInfo[] mediaInfoSet = searchMediaResponse.getMediaInfoSet();if (Objects.equal(searchMediaResponse.getTotalCount(), 0L) || mediaInfoSet.length <= 0) {log.error("===> 云點播數據查詢失敗,獲取失敗~~~");//失敗了也存記錄trtcCommonReqDto.getRoomIds().forEach(roomId ->orderTrtcVideoList.add(new OrderTrtcVideo(orderRegisterId, roomId, trtcCommonReqDto.getTaskId(), null, "0")));} else {log.error("===> 云點播數據查詢成功,獲取成功~~~");for (MediaInfo mediaInfo : mediaInfoSet) {MediaBasicInfo basicInfo = mediaInfo.getBasicInfo();String mediaUrl = basicInfo.getMediaUrl();MediaSourceData sourceInfo = basicInfo.getSourceInfo();TrtcRecordInfo trtcRecordInfo = sourceInfo.getTrtcRecordInfo();orderTrtcVideoList.add(new OrderTrtcVideo(orderRegisterId,trtcRecordInfo.getRoomId(), trtcRecordInfo.getTaskId(), mediaUrl));}}return orderTrtcVideoList;}public static void main(String[] args) {List<String> list = Lists.newArrayList();list.add("2807212226");getVodAddressUrl(new TrtcCommonReqDto().setRoomIds(list));}
}
2.2.2 TrtcReqDTO 錄制請求dto
官方提供了請求對象 但是部分方法沒有set方法, 調整如此
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import com.tencentcloudapi.trtc.v20190722.models.MixLayoutParams;
import com.tencentcloudapi.trtc.v20190722.models.MixTranscodeParams;
import com.tencentcloudapi.trtc.v20190722.models.RecordParams;
import com.tencentcloudapi.trtc.v20190722.models.StorageParams;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;/*** trtc請求dto* @author pzy*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class TrtcReqDTO {/*** TRTC的[SdkAppId](https://cloud.tencent.com/document/product/647/46351#sdkappid),和錄制的房間所對應的SdkAppId相同。*/private Long SdkAppId;/*** TRTC的[RoomId](https://cloud.tencent.com/document/product/647/46351#roomid),錄制的TRTC房間所對應的RoomId。注:房間號類型默認為整型,若房間號類型為字符串,請通過RoomIdType指定。*/private String RoomId;/*** 錄制機器人的UserId,用于進房發起錄制任務。【*注意】這個UserId不能與當前房間內的主播觀眾[UserId](https://cloud.tencent.com/document/product/647/46351#userid)重復。如果一個房間發起多個錄制任務時,機器人的userid也不能相互重復,否則會中斷前一個錄制任務。建議可以把房間ID作為UserId的標識的一部分,即錄制機器人UserId在房間內唯一。*/private String UserId;/*** 錄制機器人UserId對應的校驗簽名,即UserId和UserSig相當于錄制機器人進房的登錄密碼,具體計算方法請參考TRTC計算[UserSig](https://cloud.tencent.com/document/product/647/45910#UserSig)的方案。*/private String UserSig;/*** 云端錄制控制參數。*/private RecordParams RecordParams;/*** 云端錄制文件上傳到云存儲的參數(不支持同時設置云點播VOD和對象存儲COS)*/private StorageParams StorageParams;/*** TRTC房間號的類型。【*注意】必須和錄制的房間所對應的RoomId類型相同:0: 字符串類型的RoomId1: 32位整型的RoomId(默認)*/private Long RoomIdType;/*** 合流的轉碼參數,錄制模式為合流的時候可以設置。*/private MixTranscodeParams MixTranscodeParams;/*** 合流的布局參數,錄制模式為合流的時候可以設置。*/private MixLayoutParams MixLayoutParams;/*** 接口可以調用的時效性,從成功開啟錄制并獲得任務ID后開始計算,超時后無法調用查詢、更新和停止等接口,但是錄制任務不會停止。 參數的單位是小時,默認72小時(3天),最大可設置720小時(30天),最小設置6小時。舉例說明:如果不設置該參數,那么開始錄制成功后,查詢、更新和停止錄制的調用時效為72個小時。*/private Long ResourceExpiredHour;/*** TRTC房間權限加密串,只有在TRTC控制臺啟用了高級權限控制的時候需要攜帶,在TRTC控制臺如果開啟高級權限控制后,TRTC 的后臺服務系統會校驗一個叫做 [PrivateMapKey] 的“權限票據”,權限票據中包含了一個加密后的 RoomId 和一個加密后的“權限位列表”。由于 PrivateMapKey 中包含 RoomId,所以只提供了 UserSig 沒有提供 PrivateMapKey 時,并不能進入指定的房間。*/private String PrivateMapKey;}
2.2.3 TrtcCommonReqDto 請求dto
import com.google.common.collect.Lists;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;import java.util.List;/*** trtc停止請求dto* @author pzy* @version 0.1.1*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class TrtcCommonReqDto {/*** 錄制任務的唯一Id,在啟動錄制成功后會返回。*/private String TaskId;/*** 功能類型 1 停止錄制(默認) 2查詢錄制狀態*/private String functionType = "1";/*** roomIds房間號*/private List<String> roomIds = Lists.newLinkedList();/** 掛號訂單id */private String orderRegisterId;}
2.2.4 OrderTrtcVideo 數據庫存儲實體類
視頻對應
訂單號
對應房間號
對應taskId
進行存儲
如果失敗可以重試(也存數據庫)
import com.baomidou.mybatisplus.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;/*** 訂單trtc視頻對象 order_trtc_video** @author pzy*/
@Data
@NoArgsConstructor
@AllArgsConstructor
//@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@TableName("order_trtc_video")
@Schema(title = "訂單trtc視頻對象 order_trtc_video")
public class OrderTrtcVideo {private static final long serialVersionUID=1L;@Schema(description = "主鍵id")@TableId(value = "id")private Long id;@Schema(description = "訂單id")private String orderRegisterId;@Schema(description = "房間id")private String roomId;@Schema(description = "任務id")private String taskId;@Schema(description = "云點播視頻url")private String vodVideoUrl;@Schema(description = "云點播狀態(0失敗 1成功)")private String vodStatus;public OrderTrtcVideo(String orderRegisterId, String roomId, String taskId, String vodVideoUrl) {this.orderRegisterId = orderRegisterId;this.roomId = roomId;this.taskId = taskId;this.vodVideoUrl = vodVideoUrl;}public OrderTrtcVideo(String orderRegisterId, String roomId, String taskId, String vodVideoUrl, String vodStatus) {this.orderRegisterId = orderRegisterId;this.roomId = roomId;this.taskId = taskId;this.vodVideoUrl = vodVideoUrl;this.vodStatus = vodStatus;}
}
2.2.5 獲取用戶usersig(舊版)
:> 依賴如下
<dependency><groupId>com.github.tencentyun</groupId><artifactId>tls-sig-api-v2</artifactId><version>1.1</version></dependency>
import com.tencentyun.TLSSigAPIv2;
public static String getUserSig(Long userId){
TLSSigAPIv2 api = new TLSSigAPIv2(sdkAppId, secretKey);return api.genSig(userId, expire);
}
2.3 業務使用方式
2.3.0 json傳遞數據
{"userId": "123456","userSig": "eJwtzF0LgjAYhuH-stNC5tpHCh0tsKgOIiM9nGzFS8xNE*mD-ntLPXyuG54PyvenqDctShGJMJoPG7SpO7jCwDFZUMan8tB35T1olMYcYyzIkvOxmKeH1gRnjJGQRu3A-k1QQgRNsJhe4BaOE36*OCurfrdWjUxw5qQtsk3JlXaMinxW*uL9OjT1cbtC3x*78zBl","roomId": "123","mixLayoutParams": {"backGroundColor": "#FF0000","backgroundImageRenderMode": 1,"maxResolutionUserId": "user_1","mediaId": 0,"mixLayoutList": [{"alpha": 100,"height": 100,"imageLayer": 2,"left": 100,"mediaId": 1,"renderMode": 1,"top": 100,"userId": "user_1","width": 100}],"mixLayoutMode": 3,"renderMode": 1},"recordParams": {"maxIdleTime": 60,"maxMediaFileDuration": 1440,"recordMode": 2,"streamType": 0},"storageParams": {"cloudVod": {"tencentVod": {"classId": 0,"mediaType": 0,"sessionContext": "任務流上下文,任務完成回調時透傳","sourceContext": "上傳上下文,上傳完成回調時透傳"}}}
}
2.3.1 創建service方法
R是
統一返回值
可根據自己業務自行修改
/*** trtc** @author pzy* @version 0.1.1*/
public interface TrtcService {R createCloudRecording(TrtcReqDTO trtcReqDTO);R functionCloudRecording(TrtcCommonReqDto trtcCommonReqDto);R getVodAddressUrl(TrtcCommonReqDto trtcCommonReqDto);
}
2.3.2 TrtcServiceImpl 實現類
依賴包沒用特殊的 本地環境沒有百度搜就行
import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.base.Objects;
import com.google.common.collect.Lists;
import com.tencentcloudapi.trtc.v20190722.models.*;
import com.tencentcloudapi.vod.v20180717.models.*;import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;import java.util.List;@Slf4j
@Service
@RequiredArgsConstructor
public class TrtcServiceImpl implements TrtcService {@DubboReferenceprivate final A a;/*** 創建TRTC云錄制功能(數據處理)*/@Overridepublic R createCloudRecording(TrtcReqDTO trtcReqDTO) {log.info("TRTC 前端入參請求數據===> {}", JSON.toJSONString(trtcReqDTO));//不得使用其他數據業務trtcReqDTO.setSdkAppId(Long.valueOf(TrtcUtils.SDKAppID));trtcReqDTO.setResourceExpiredHour(72L);/*如果是空 默認合流模式 使用默認數據*/RecordParams recordParams = trtcReqDTO.getRecordParams() != null ? trtcReqDTO.getRecordParams() : new RecordParams();recordParams.setRecordMode(2L);recordParams.setMaxIdleTime(30L);recordParams.setStreamType(0L);recordParams.setMaxMediaFileDuration(1440L);trtcReqDTO.setRecordParams(recordParams);//云點播 自動上傳模板默認值-------------------->StorageParams storageParams = trtcReqDTO.getStorageParams() != null ? trtcReqDTO.getStorageParams() : new StorageParams();CloudVod cloudVod = storageParams.getCloudVod() != null ? storageParams.getCloudVod() : new CloudVod();TencentVod tencentVod = cloudVod.getTencentVod() != null ? cloudVod.getTencentVod() : new TencentVod();tencentVod.setSubAppId(TrtcUtils.vodSubAppId);tencentVod.setProcedure(TrtcUtils.vodTaskTemplateName);tencentVod.setExpireTime(0L);tencentVod.setClassId(0L);tencentVod.setMediaType(0L);cloudVod.setTencentVod(tencentVod);storageParams.setCloudVod(cloudVod);trtcReqDTO.setStorageParams(storageParams);//--------------------------------------------->log.info("TRTC 后端固定參數覆蓋后請求入參數據===> {}", JSON.toJSONString(trtcReqDTO));//數據賦值CreateCloudRecordingRequest req = new CreateCloudRecordingRequest();BeanUtil.copyProperties(trtcReqDTO, req);log.info("TRTC 標準參數<官方要求>請求格式===> {}", JSON.toJSONString(req));return R.ok(TrtcUtils.sendTrtcRecord(req));}@Overridepublic R functionCloudRecording(TrtcCommonReqDto trtcCommonReqDto) {Object resp = TrtcUtils.functionCloudRecording(trtcCommonReqDto);// /*校驗: 如果是停止調用*/if (Objects.equal(trtcCommonReqDto.getFunctionType(), "1")) {// 添加trtc云點播視頻urladdOrderTrtcVodUrl(trtcCommonReqDto);}return R.ok(resp);}/*** 添加trtc云點播視頻url*/@SneakyThrows@Asyncprotected void addOrderTrtcVodUrl(TrtcCommonReqDto trtcCommonReqDto) {Thread.sleep(15000);//模擬延時隊列List<OrderTrtcVideo> orderTrtcVideoList = TrtcUtils.getVodUrlByRoomInOrder(trtcCommonReqDto);//添加Trtc視頻log.info("===> 批量添加trtc視頻記錄中 =====> ");//TODO}@Overridepublic R getVodAddressUrl(TrtcCommonReqDto trtcCommonReqDto) {SearchMediaResponse resp = TrtcUtils.getVodAddressUrl(trtcCommonReqDto);return R.ok(resp);}
}
2.3.4 上傳后視頻效果
3. 文章的總結與預告
3.1 本文總結
trtc錄制并上傳到vod , 錄制結束時根據房間號進行查詢 存入數據庫 設置重試機制
3.2 代碼指正
如有遺漏, 代碼錯誤,流程錯誤,更優方案等 歡迎評論區指正 謝謝
@author: pingzhuyan
@description: ok
@year: 2024