Sfoglia il codice sorgente

视频录制,停止录制

18792927508 2 anni fa
parent
commit
eb09ba6ae9

+ 36
- 1
ruoyi-admin/src/main/java/com/ruoyi/web/controller/wisdomarbitrate/VideoController.java Vedi File

1
 package com.ruoyi.web.controller.wisdomarbitrate;
1
 package com.ruoyi.web.controller.wisdomarbitrate;
2
 
2
 
3
 import cn.hutool.core.util.StrUtil;
3
 import cn.hutool.core.util.StrUtil;
4
+import com.alibaba.fastjson.JSON;
4
 import com.ruoyi.common.annotation.Anonymous;
5
 import com.ruoyi.common.annotation.Anonymous;
5
 import com.ruoyi.common.core.controller.BaseController;
6
 import com.ruoyi.common.core.controller.BaseController;
6
 import com.ruoyi.common.core.domain.AjaxResult;
7
 import com.ruoyi.common.core.domain.AjaxResult;
7
 import com.ruoyi.wisdomarbitrate.domain.IdentityAuthentication;
8
 import com.ruoyi.wisdomarbitrate.domain.IdentityAuthentication;
9
+import com.ruoyi.wisdomarbitrate.domain.vo.ReservedConferenceVO;
8
 import com.ruoyi.wisdomarbitrate.domain.vo.SendRoomNoMessageVO;
10
 import com.ruoyi.wisdomarbitrate.domain.vo.SendRoomNoMessageVO;
9
 import com.ruoyi.wisdomarbitrate.domain.vo.WeChatUserVO;
11
 import com.ruoyi.wisdomarbitrate.domain.vo.WeChatUserVO;
10
 import com.ruoyi.wisdomarbitrate.service.VideoService;
12
 import com.ruoyi.wisdomarbitrate.service.VideoService;
11
 import com.ruoyi.wisdomarbitrate.service.WeChatUserService;
13
 import com.ruoyi.wisdomarbitrate.service.WeChatUserService;
14
+import com.tencentcloudapi.common.Credential;
15
+import com.tencentcloudapi.common.exception.TencentCloudSDKException;
16
+import com.tencentcloudapi.common.profile.ClientProfile;
17
+import com.tencentcloudapi.common.profile.HttpProfile;
18
+import com.tencentcloudapi.trtc.v20190722.TrtcClient;
19
+import com.tencentcloudapi.trtc.v20190722.models.*;
20
+import com.tencentyun.TLSSigAPIv2;
12
 import org.springframework.beans.factory.annotation.Autowired;
21
 import org.springframework.beans.factory.annotation.Autowired;
13
 import org.springframework.web.bind.annotation.*;
22
 import org.springframework.web.bind.annotation.*;
14
 import org.springframework.web.multipart.MultipartFile;
23
 import org.springframework.web.multipart.MultipartFile;
15
 
24
 
16
 import javax.servlet.http.HttpServletRequest;
25
 import javax.servlet.http.HttpServletRequest;
17
 import javax.validation.Valid;
26
 import javax.validation.Valid;
27
+import java.io.IOException;
18
 
28
 
19
 /**
29
 /**
20
  * @author wangqiong
30
  * @author wangqiong
21
- * @description 视频录制
31
+ * @description trtc实时音视频
22
  * @date 2023-10-26 11:25
32
  * @date 2023-10-26 11:25
23
  */
33
  */
24
 @RestController
34
 @RestController
59
 
69
 
60
         return videoService.videoList(caseId);
70
         return videoService.videoList(caseId);
61
     }
71
     }
72
+    /**
73
+     * 开启腾讯云录制
74
+     * @param vo
75
+     * @return
76
+     * @throws Exception
77
+     */
78
+    @Anonymous
79
+    @PostMapping("/openCloudRecording")
80
+    private AjaxResult openCloudRecording( @RequestBody ReservedConferenceVO vo)  {
81
+        if(vo.getCaseId()==null || StrUtil.isEmpty(vo.getRoomId())){
82
+            return AjaxResult.error("参数错误");
83
+        }
84
+        return videoService.openCloudRecording(vo.getCaseId(),vo.getRoomId());
85
+    }
86
+    /**
87
+     * 关闭腾讯云录制
88
+     * @param taskId 任务ID
89
+     * @return
90
+     */
91
+    @Anonymous
92
+    @PostMapping("/closeDeleteCloudRecording")
93
+    public AjaxResult closeDeleteCloudRecording(@RequestParam("taskId") String taskId){
94
+        return videoService.closeDeleteCloudRecording(taskId);
95
+    }
96
+
62
 }
97
 }

+ 5
- 1
ruoyi-admin/src/main/resources/application.yml Vedi File

178
   # sdkAppId
178
   # sdkAppId
179
   sdkAppId: 1600011167
179
   sdkAppId: 1600011167
180
   # 密钥
180
   # 密钥
181
-  secretKey: 17d136d9327576a247f991bdfed3a6d14cebc7d540a52245086829c3a1421a86
181
+  sdkSecretKey: 17d136d9327576a247f991bdfed3a6d14cebc7d540a52245086829c3a1421a86
182
+  # 腾讯云账户 SecretId
183
+  secretId: AKID3xfHgroY4MQHvLXUXMwIQL1UjmbBX1Tv
184
+  # 腾讯云密钥
185
+  secretKey: INDrIXcT8YmomZBcsy0oNirnU0LTN4X7

+ 9
- 0
ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/VideoService.java Vedi File

17
     AjaxResult bindCaseId(Long caseId, String roomId);
17
     AjaxResult bindCaseId(Long caseId, String roomId);
18
 
18
 
19
     AjaxResult videoList(Long caseId);
19
     AjaxResult videoList(Long caseId);
20
+
21
+    /**
22
+     * 开启腾讯云录制
23
+     * @param roomId
24
+     * @return
25
+     */
26
+    AjaxResult openCloudRecording(long caseId,String roomId);
27
+
28
+    AjaxResult closeDeleteCloudRecording(String taskId);
20
 }
29
 }

+ 5
- 5
ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/CaseApplicationServiceImpl.java Vedi File

79
     @Value("${imConfig.sdkAppId}")
79
     @Value("${imConfig.sdkAppId}")
80
     private long sdkAppId;
80
     private long sdkAppId;
81
     // 腾讯云即时通信密钥
81
     // 腾讯云即时通信密钥
82
-    @Value("${imConfig.secretKey}")
83
-    private String secretKey;
82
+    @Value("${imConfig.sdkSecretKey}")
83
+    private String sdkSecretKey;
84
     @Autowired
84
     @Autowired
85
     private CaseApplicationMapper caseApplicationMapper;
85
     private CaseApplicationMapper caseApplicationMapper;
86
 
86
 
113
     private DeptIdentifyMapper deptIdentifyMapper;
113
     private DeptIdentifyMapper deptIdentifyMapper;
114
     @Autowired
114
     @Autowired
115
     private ReservedConferenceMapper reservedConferenceMapper;
115
     private ReservedConferenceMapper reservedConferenceMapper;
116
-    @Autowired
117
-    private SysDeptMapper deptMapper;
116
+
118
     // 手机号正则
117
     // 手机号正则
119
     private static final Pattern TELEPHONE_REGX = Pattern.compile("^1(3\\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\\d|9[0-35-9])\\d{8}$");
118
     private static final Pattern TELEPHONE_REGX = Pattern.compile("^1(3\\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\\d|9[0-35-9])\\d{8}$");
120
 
119
 
2520
      * @return
2519
      * @return
2521
      */
2520
      */
2522
     public String generateUserSign(String userId) {
2521
     public String generateUserSign(String userId) {
2523
-        TLSSigAPIv2 tlsSigAPIv2 = new TLSSigAPIv2(sdkAppId, secretKey);
2522
+        TLSSigAPIv2 tlsSigAPIv2 = new TLSSigAPIv2(sdkAppId, sdkSecretKey);
2524
         return tlsSigAPIv2.genUserSig(userId, 60 * 60 * 10);
2523
         return tlsSigAPIv2.genUserSig(userId, 60 * 60 * 10);
2525
     }
2524
     }
2526
 
2525
 
2543
         }
2542
         }
2544
         // 生成房间号id
2543
         // 生成房间号id
2545
         String roomId = generateRoomId();
2544
         String roomId = generateRoomId();
2545
+//        String roomId = reservedConferenceVO.getRoomId();
2546
         Date startTime = reservedConferenceVO.getScheduleStartTime();
2546
         Date startTime = reservedConferenceVO.getScheduleStartTime();
2547
         Date endTime = reservedConferenceVO.getScheduleEndTime();
2547
         Date endTime = reservedConferenceVO.getScheduleEndTime();
2548
         Random rand = new Random();
2548
         Random rand = new Random();

+ 108
- 0
ruoyi-system/src/main/java/com/ruoyi/wisdomarbitrate/service/impl/VideoServiceImpl.java Vedi File

31
 import com.tencentcloudapi.common.exception.TencentCloudSDKException;
31
 import com.tencentcloudapi.common.exception.TencentCloudSDKException;
32
 import com.tencentcloudapi.common.profile.ClientProfile;
32
 import com.tencentcloudapi.common.profile.ClientProfile;
33
 import com.tencentcloudapi.common.profile.HttpProfile;
33
 import com.tencentcloudapi.common.profile.HttpProfile;
34
+import com.tencentcloudapi.trtc.v20190722.TrtcClient;
35
+import com.tencentcloudapi.trtc.v20190722.models.*;
34
 import com.tencentcloudapi.vod.v20180717.VodClient;
36
 import com.tencentcloudapi.vod.v20180717.VodClient;
35
 import com.tencentcloudapi.vod.v20180717.models.DescribeMediaInfosRequest;
37
 import com.tencentcloudapi.vod.v20180717.models.DescribeMediaInfosRequest;
36
 import com.tencentcloudapi.vod.v20180717.models.DescribeMediaInfosResponse;
38
 import com.tencentcloudapi.vod.v20180717.models.DescribeMediaInfosResponse;
39
+import com.tencentyun.TLSSigAPIv2;
37
 import lombok.extern.slf4j.Slf4j;
40
 import lombok.extern.slf4j.Slf4j;
38
 import org.springframework.beans.factory.annotation.Autowired;
41
 import org.springframework.beans.factory.annotation.Autowired;
42
+import org.springframework.beans.factory.annotation.Value;
39
 import org.springframework.stereotype.Service;
43
 import org.springframework.stereotype.Service;
40
 import org.springframework.transaction.annotation.Transactional;
44
 import org.springframework.transaction.annotation.Transactional;
41
 import org.springframework.util.ResourceUtils;
45
 import org.springframework.util.ResourceUtils;
63
 @Service
67
 @Service
64
 @Slf4j
68
 @Slf4j
65
 public class VideoServiceImpl implements VideoService {
69
 public class VideoServiceImpl implements VideoService {
70
+    // 腾讯云即时通信sdkAppId
71
+    @Value("${imConfig.sdkAppId}")
72
+    private long sdkAppId;
73
+    // 腾讯云即时通信密钥
74
+    @Value("${imConfig.sdkSecretKey}")
75
+    private String sdkSecretKey;
76
+    // 腾讯云个人账户secretId
77
+    @Value("${imConfig.secretId}")
78
+    private String secretId;
79
+    // 腾讯云个人账户密钥
80
+    @Value("${imConfig.secretKey}")
81
+    private String secretKey;
66
     @Autowired
82
     @Autowired
67
     private CaseApplicationMapper caseApplicationMapper;
83
     private CaseApplicationMapper caseApplicationMapper;
68
     @Autowired
84
     @Autowired
149
         return  AjaxResult.success(caseAttachList);
165
         return  AjaxResult.success(caseAttachList);
150
     }
166
     }
151
 
167
 
168
+    /**
169
+     * 开启腾讯云录制
170
+     * @param roomId
171
+     * @return
172
+     */
173
+    @Override
174
+    public AjaxResult openCloudRecording(long caseId,String roomId) {
175
+        try {
176
+            String userId="recorder_"+roomId;
177
+
178
+            Credential cred = new Credential(secretId, secretKey);
179
+
180
+            // 实例化一个http选项,可选的,没有特殊需求可以跳过
181
+            HttpProfile httpProfile = new HttpProfile();
182
+            httpProfile.setEndpoint("trtc.tencentcloudapi.com");
183
+            // 实例化一个client选项,可选的,没有特殊需求可以跳过
184
+            ClientProfile clientProfile = new ClientProfile();
185
+            clientProfile.setHttpProfile(httpProfile);
186
+            // 实例化要请求产品的client对象,clientProfile是可选的
187
+            TrtcClient client = new TrtcClient(cred, "ap-beijing", clientProfile);
188
+
189
+            // 实例化一个请求对象,每个接口都会对应一个request对象
190
+            CreateCloudRecordingRequest req = new CreateCloudRecordingRequest();
191
+            req.setSdkAppId(sdkAppId); // SdkAppId – TRTC的[SdkAppId](https://cloud.tencent.com/document/product/647/46351#sdkappid),和录制的房间所对应的SdkAppId相同
192
+            req.setRoomId(roomId); // RoomId – TRTC的[RoomId](https://cloud.tencent.com/document/product/647/46351#roomid),录制的TRTC房间所对应的RoomId
193
+            req.setRoomIdType(1L);
194
+            /**
195
+             *  录制机器人用于进入TRTC房间拉流的[UserId](https://cloud.tencent.com/document/product/647/46351#userid),
196
+             *  注意这个UserId不能与其他TRTC房间内的主播或者其他录制任务等已经使用的UserId重复,建议可以把房间ID作为userId的标识的一部分,
197
+             *  即录制机器人进入房间的userid应保证独立且唯一
198
+             */
199
+            req.setUserId(userId);
200
+
201
+            TLSSigAPIv2 api = new TLSSigAPIv2(Long.valueOf(sdkAppId), sdkSecretKey);
202
+            String userSign = api.genUserSig(userId, 60 * 60 * 10);
203
+            req.setUserSig(userSign); // 录制机器人用于进入TRTC房间拉流的用户签名,当前 UserId 对应的验证签名,相当于登录密码
204
+            RecordParams recordParams = new RecordParams();
205
+            // 混流录制
206
+            recordParams.setMaxIdleTime(60L*5); // 5分钟内房间里面没有主播,自动停止录制
207
+            recordParams.setStreamType(0L); // 0:录制音频+视频流(默认); 1:仅录制音频流; 2:仅录制视频流
208
+            recordParams.setRecordMode(2L); // 1:单流录制,分别录制房间的订阅UserId的音频和视频,将录制文件上传至云存储; 2:混流录制,将房间内订阅UserId的音视频混录成一个音视频文件,将录制文件上传至云存储;
209
+            recordParams.setOutputFormat(0L); // 0:(默认)输出文件为hls格式。1:输出文件格式为hls+mp4。2:输出文件格式为hls+aac
210
+
211
+            StorageParams storageParams1 = new StorageParams();
212
+            CloudVod cloudVod1 = new CloudVod();
213
+            TencentVod tencentVod1 = new TencentVod();
214
+            // 录制的文件永久保存
215
+            tencentVod1.setExpireTime(0L);
216
+            // 录制文件名拼接前缀
217
+            tencentVod1.setUserDefineRecordId(caseId+"@");
218
+            cloudVod1.setTencentVod(tencentVod1); // 腾讯云点播相关参数。
219
+            storageParams1.setCloudVod(cloudVod1); // 必填】腾讯云云点播的账号信息,目前仅支持存储至腾讯云点播VOD。
220
+            req.setRecordParams(recordParams); // 云端录制控制参数
221
+            req.setStorageParams(storageParams1); // 云端录制文件上传到云存储的参数(目前只支持使用腾讯云点播作为存储)
222
+            // 返回的resp是一个CreateCloudRecordingResponse的实例,与请求对象对应
223
+            CreateCloudRecordingResponse resp = client.CreateCloudRecording(req);
224
+            // 输出json格式的字符串回包
225
+            String s = JSON.toJSONString(resp);
226
+            return AjaxResult.success(s);
227
+        } catch (TencentCloudSDKException e) {
228
+            return AjaxResult.error(e.toString());
229
+        }
230
+    }
231
+
232
+    @Override
233
+    public AjaxResult closeDeleteCloudRecording(String taskId) {
234
+        // 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密
235
+        // 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305
236
+        // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
237
+        Credential cred = new Credential(secretId, secretKey);
238
+        // 实例化一个http选项,可选的,没有特殊需求可以跳过
239
+        HttpProfile httpProfile = new HttpProfile();
240
+        httpProfile.setEndpoint("trtc.tencentcloudapi.com");
241
+        // 实例化一个client选项,可选的,没有特殊需求可以跳过
242
+        ClientProfile clientProfile = new ClientProfile();
243
+        clientProfile.setHttpProfile(httpProfile);
244
+        // 实例化要请求产品的client对象,clientProfile是可选的
245
+        TrtcClient client = new TrtcClient(cred, "ap-beijing", clientProfile);
246
+        // 实例化一个请求对象,每个接口都会对应一个request对象
247
+        DeleteCloudRecordingRequest req = new DeleteCloudRecordingRequest();
248
+
249
+        // 返回的resp是一个DeleteCloudRecordingResponse的实例,与请求对象对应
250
+        DeleteCloudRecordingResponse resp = null;
251
+        try {
252
+            resp = client.DeleteCloudRecording(req);
253
+        } catch (TencentCloudSDKException e) {
254
+            return AjaxResult.error(e.toString());
255
+        }
256
+       return AjaxResult.success(DeleteCloudRecordingResponse.toJsonString(resp));
257
+    }
258
+
259
+
152
     /**
260
     /**
153
      *  查询出音视频集合,并下载,在将云点播上面的音视频删除
261
      *  查询出音视频集合,并下载,在将云点播上面的音视频删除
154
      * @param fileIds 点播平台唯一ID集合
262
      * @param fileIds 点播平台唯一ID集合

+ 4
- 4
ruoyi-system/src/main/resources/mapper/wisdomarbitrate/CaseApplicationMapper.xml Vedi File

68
         c.update_by ,c.update_time , c.arbitrator_name,ca.application_organ_id applicationOrganId ,ca.application_organ_name as applicantName,c.filearbitra_url
68
         c.update_by ,c.update_time , c.arbitrator_name,ca.application_organ_id applicationOrganId ,ca.application_organ_name as applicantName,c.filearbitra_url
69
         from case_log_record r
69
         from case_log_record r
70
         join case_application c on r.case_appli_id=c.id
70
         join case_application c on r.case_appli_id=c.id
71
-        LEFT JOIN case_affiliate ca ON ca.case_appli_id = c.id AND ca.identity_type=1
71
+         JOIN case_affiliate ca ON ca.case_appli_id = c.id AND ca.identity_type=1
72
         <where>
72
         <where>
73
             
73
             
74
             <if test="lockStatus != null">
74
             <if test="lockStatus != null">
125
         applicantName,
125
         applicantName,
126
         c.arbitrator_id,ca.identity_num , ca.identity_type,c.filearbitra_url,c.lock_status
126
         c.arbitrator_id,ca.identity_num , ca.identity_type,c.filearbitra_url,c.lock_status
127
         from case_application c
127
         from case_application c
128
-        LEFT JOIN case_affiliate ca ON ca.case_appli_id = c.id
128
+         JOIN case_affiliate ca ON ca.case_appli_id = c.id
129
         <where>
129
         <where>
130
             <if test="caseStatus != null">
130
             <if test="caseStatus != null">
131
                 AND c.case_status = #{caseStatus}
131
                 AND c.case_status = #{caseStatus}
219
         c.case_status,ca.application_organ_id,
219
         c.case_status,ca.application_organ_id,
220
         c.arbitrator_id,ca.identity_num , ca.identity_type
220
         c.arbitrator_id,ca.identity_num , ca.identity_type
221
         from case_application c
221
         from case_application c
222
-        LEFT JOIN case_affiliate ca ON ca.case_appli_id = c.id
222
+         JOIN case_affiliate ca ON ca.case_appli_id = c.id
223
         <where>
223
         <where>
224
             <if test="caseStatus != null">
224
             <if test="caseStatus != null">
225
                 AND c.case_status = #{caseStatus}
225
                 AND c.case_status = #{caseStatus}
298
         c.begin_video_date ,c.online_video_person ,c.contract_number ,c.create_by ,c.create_time ,c.lock_status,
298
         c.begin_video_date ,c.online_video_person ,c.contract_number ,c.create_by ,c.create_time ,c.lock_status,
299
         c.update_by ,c.update_time , c.arbitrator_name,ca.application_organ_id applicationOrganId ,ca.application_organ_name as applicantName,c.filearbitra_url
299
         c.update_by ,c.update_time , c.arbitrator_name,ca.application_organ_id applicationOrganId ,ca.application_organ_name as applicantName,c.filearbitra_url
300
         from case_application c
300
         from case_application c
301
-        LEFT JOIN case_affiliate ca ON ca.case_appli_id = c.id AND ca.identity_type=1
301
+         JOIN case_affiliate ca ON ca.case_appli_id = c.id AND ca.identity_type=1
302
         <where>
302
         <where>
303
             <if test="caseStatus != null">
303
             <if test="caseStatus != null">
304
                 AND c.case_status = #{caseStatus}
304
                 AND c.case_status = #{caseStatus}