Java集成腾讯云音视频录制功能

Java集成腾讯云音视频录制功能Java 集成腾讯云音视频录制功能 为什么要实现音视频录制功能 因为我们做的是一个医院的项目 医生和患者可能进行视频通话和语音通话 为了保证通话的质量以及后续的问题 我们就需要进行音视频录制 以便后续的问题解决 为什么选择使用腾讯云实现音视频录制功能 因为我们做的是微信小程序

大家好,我是讯享网,很高兴认识大家。

Java集成腾讯云音视频录制功能

为什么要实现音视频录制功能

因为我们做的是一个医院的项目,医生和患者可能进行视频通话和语音通话,为了保证通话的质量以及后续的问题,

我们就需要进行音视频录制,以便后续的问题解决

为什么选择使用腾讯云实现音视频录制功能

因为我们做的是微信小程序

  1. 腾讯云是基于腾讯的技术支撑,大厂技术比较稳定;
  2. 微信和腾讯云都是腾讯的产品,两者兼容性更好;
  3. 腾讯云提供的有uni-app的例子,参考资料更充分,可以基于demo和现有系统集成。

注意:userId需要保持在整个房间是唯一的,不管是录制还是音视频通话,进入房间的userId必须唯一,不然就会造成录制不了的情况

1.导入依赖

因为我们是Gradle项目,与我们之前Maven项目导入依赖的方式不一样,Gradle项目导入依赖的方式如下所示

implementation 'com.tencentcloudapi:tencentcloud-sdk-java-common:3.1.691' implementation 'com.tencentcloudapi:tencentcloud-sdk-java-trtc:3.1.691' implementation 'com.tencentcloudapi:tencentcloud-sdk-java-vod:3.1.704' 

讯享网

2.实现云端录制

流程图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YaUQaOLH-1680487013379)(C:\Users\11\AppData\Roaming\Typora\typora-user-images\image-20230403092937476.png)]
讯享网

2.1 添加配置文件

访问秘钥和key
在这里插入图片描述

SDKAppID和SDKSecretKey

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W2EGXXrF-1680487013380)(C:\Users\11\AppData\Roaming\Typora\typora-user-images\image-20230401100744076.png)]

在application.properties添加一下配置

讯享网secretid=访问秘钥ID secretkey=访问秘钥Key expiretime=过期时间 sdkappid=SDKAppID key=SDKSecretKey 
2.2 回调地址设置

打开音视频控制台 --》应用管理 --》回调配置

跟着下面配置就可以了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VC5U95iR-1680487013381)(C:\Users\11\AppData\Roaming\Typora\typora-user-images\image-20230401121640938.png)]

2.3 签名 Sign
/ * @param key 回调秘钥 * @param body 入参 * @return 签名 Sign 计算公式中 key 为计算签名 Sign 用的加密密钥。 * @throws Exception */ private static String getResultSign(String key, String body) throws Exception { 
    Mac hmacSha256 = Mac.getInstance("HmacSHA256"); SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(), "HmacSHA256"); hmacSha256.init(secret_key); return Base64.getEncoder().encodeToString(hmacSha256.doFinal(body.getBytes())); } 
2.4 实现房间回调

房间回调API文档地址:https://cloud.tencent.com/document/product/647/51586

使用房间回调事件可以监听进入房间和退出房间时间,分别对应开始录制和退出录制(当我们进入房间开始录制,退出房间就退出录制)

入参是body加上请求头的方式,详细信息大家可以查阅文档,这里我就不一一赘述了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iCLNAmjP-1680487013381)(C:\Users\11\AppData\Roaming\Typora\typora-user-images\image-20230401095115187.png)]

代码实现

讯享网//# 功能:第三方回调sign校验 //# 参数: //# key:控制台配置的密钥key //# body:腾讯云回调返回的body体 //# sign:腾讯云回调返回的签名值sign //# 返回值: //# Status:OK 表示校验通过,FAIL 表示校验失败,具体原因参考Info //# Info:成功/失败信息 @ApiOperation(value = "音视频房间回调接口") @PostMapping("/roomCallback") public void roomCallback(@RequestBody String body, HttpServletRequest request) throws Exception { 
    String key = "key"; String sdkAppId = request.getHeader("SdkAppId"); String sign = request.getHeader("Sign"); String resultSign = getResultSign(key,body); ValueOperations ops = redisTemplate.opsForValue(); if (resultSign.equals(sign)) { 
    JSONObject jsonObject = (JSONObject) JSON.parse(body); Integer eventType = jsonObject.getInteger("EventType"); // 事件类型 String eventInfo = jsonObject.getString("EventInfo"); // 事件信息 JSONObject jsonObject1 = (JSONObject) JSON.parse(eventInfo); String roomId = jsonObject1.getString("RoomId"); // 房间号 String userId = jsonObject1.getString("UserId"); // 用户ID if (!StringUtils.isEmpty(userId)) { 
    // 执行业务逻辑,判断是医生端还是患者端进入房间,查询出相关的问诊订单 } // 创建房间事件(创建房间事件只会进入一次房间回调接口,可以防止重复两次调用录制接口) if (eventType == 101) { 
    logger.debug("{'Status': 'OK', 'Info': '校验通过'}"); String openCloudRecording = openCloudRecording(userId, roomId); // 开启录制 JSONObject jsonObject2 = (JSONObject) JSON.parse(openCloudRecording); String taskId = jsonObject2.getString("taskId"); // 任务ID if (!StringUtils.isEmpty(taskId)) { 
    // 执行相关业务 } } else if (eventType == 104) { 
    // 104 退出房间事件 logger.debug("{'Status': 'FAIL', 'Info': '退出房间'}"); closeDeleteCloudRecording("录制任务ID"); // 退出录制 } } else { 
    logger.debug("{'Status': 'FAIL', 'Info': '校验失败'}"); } logger.debug("腾讯云测试成功"); } 
2.5 开启音视频录制

开启云端录制API文档地址:https://cloud.tencent.com/document/api/647/73786

当房间回调事件监听到进入房间事件我们就开启语音(视频)通话了,就会调用开启音视频录制接口

输入参数我就不做赘述了(输出参数开启云端录制和关闭云端录制都是一致的),详细信息请看API文档

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0SIXel2V-1680487013381)(C:\Users\11\AppData\Roaming\Typora\typora-user-images\image-20230401103201717.png)]

代码实现

/ * 开启腾讯云录制 * @param userId * @param roomId * @return * @throws Exception */ private String openCloudRecording(String userId, String roomId) throws Exception { 
    try { 
    //创建文件对象 Properties properties = new Properties(); //加载文件获取数据 文件带后缀 properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream ("application.properties")); //根据key来获取value String secretId = properties.getProperty("secretid"); String secretKey = properties.getProperty("secretkey"); String ExpireTime = properties.getProperty("expiretime"); String sdkAppId = properties.getProperty("sdkappid"); String key = properties.getProperty("key"); Credential cred = new Credential(secretId, secretKey); // 实例化一个http选项,可选的,没有特殊需求可以跳过 HttpProfile httpProfile = new HttpProfile(); httpProfile.setEndpoint("trtc.tencentcloudapi.com"); // 实例化一个client选项,可选的,没有特殊需求可以跳过 ClientProfile clientProfile = new ClientProfile(); clientProfile.setHttpProfile(httpProfile); // 实例化要请求产品的client对象,clientProfile是可选的 TrtcClient client = new TrtcClient(cred, "ap-beijing", clientProfile); // 实例化一个请求对象,每个接口都会对应一个request对象 CreateCloudRecordingRequest req = new CreateCloudRecordingRequest(); // 实例化一个请求对象,每个接口都会对应一个request对象 CreateCloudRecordingRequest req = new CreateCloudRecordingRequest(); req.setSdkAppId(Long.valueOf(sdkAppId)); // SdkAppId – TRTC的[SdkAppId](https://cloud.tencent.com/document/product/647/46351#sdkappid),和录制的房间所对应的SdkAppId相同 req.setRoomId(roomId); // RoomId – TRTC的[RoomId](https://cloud.tencent.com/document/product/647/46351#roomid),录制的TRTC房间所对应的RoomId req.setRoomIdType(1L); / * 录制机器人用于进入TRTC房间拉流的[UserId](https://cloud.tencent.com/document/product/647/46351#userid), * 注意这个UserId不能与其他TRTC房间内的主播或者其他录制任务等已经使用的UserId重复,建议可以把房间ID作为userId的标识的一部分, * 即录制机器人进入房间的userid应保证独立且唯一 */ req.setUserId(userId); TLSSigAPIv2 api = new TLSSigAPIv2(Long.valueOf(sdkAppId), key); String userSign = api.genUserSig(userId, Long.valueOf(ExpireTime)); req.setUserSig(userSign); // 录制机器人用于进入TRTC房间拉流的用户签名,当前 UserId 对应的验证签名,相当于登录密码 RecordParams recordParams = new RecordParams(); // 单流录制 recordParams.setMaxIdleTime(30L); // 30 秒内房间里面没有主播,自动停止录制 recordParams.setStreamType(0L); // 0:录制音频+视频流(默认); 1:仅录制音频流; 2:仅录制视频流 recordParams.setRecordMode(1L); // 1:单流录制,分别录制房间的订阅UserId的音频和视频,将录制文件上传至云存储; 2:混流录制,将房间内订阅UserId的音视频混录成一个音视频文件,将录制文件上传至云存储; recordParams.setOutputFormat(0L); // 0:(默认)输出文件为hls格式。1:输出文件格式为hls+mp4。2:输出文件格式为hls+aac StorageParams storageParams1 = new StorageParams(); CloudVod cloudVod1 = new CloudVod(); TencentVod tencentVod1 = new TencentVod(); cloudVod1.setTencentVod(tencentVod1); // 腾讯云点播相关参数。 storageParams1.setCloudVod(cloudVod1); // 必填】腾讯云云点播的账号信息,目前仅支持存储至腾讯云点播VOD。 req.setRecordParams(recordParams); // 云端录制控制参数 req.setStorageParams(storageParams1); // 云端录制文件上传到云存储的参数(目前只支持使用腾讯云点播作为存储) // 返回的resp是一个CreateCloudRecordingResponse的实例,与请求对象对应 CreateCloudRecordingResponse resp = client.CreateCloudRecording(req); // 输出json格式的字符串回包 String s = JSON.toJSONString(resp); return s; } catch (TencentCloudSDKException | IOException e) { 
    return e.toString(); } catch (Exception e) { 
    return e.toString(); } } 
2.6 关闭音视频录制

关闭云端录制API文档地址:https://cloud.tencent.com/document/api/647/73785

当房间回调事件监听到退出房间事件我们就退出语音(视频)通话了,就会调用关闭音视频录制接口

输入参数我就不做赘述了(输出参数开启云端录制和关闭云端录制都是一致的),详细信息请看API文档

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KxY5ogdD-1680487013381)(C:\Users\11\AppData\Roaming\Typora\typora-user-images\image-20230401103201717.png)]

代码实现

讯享网/ * 关闭腾讯云录制 * @param taskId 任务ID * @return */ public String closeDeleteCloudRecording(String taskId){ 
    try { 
    if (taskId != null) { 
    taskId = taskId.replaceAll(" ", "+"); } // 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密 // 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305 // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取 //创建文件对象 Properties properties = new Properties(); //加载文件获取数据 文件带后缀 properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream ("application.properties")); //根据key来获取value String SecretId = properties.getProperty("secretid"); String SecretKey = properties.getProperty("secretkey"); String sdkAppId = properties.getProperty("sdkappid"); Credential cred = new Credential(SecretId, SecretKey); // 实例化一个http选项,可选的,没有特殊需求可以跳过 HttpProfile httpProfile = new HttpProfile(); httpProfile.setEndpoint("trtc.tencentcloudapi.com"); // 实例化一个client选项,可选的,没有特殊需求可以跳过 ClientProfile clientProfile = new ClientProfile(); clientProfile.setHttpProfile(httpProfile); // 实例化要请求产品的client对象,clientProfile是可选的 TrtcClient client = new TrtcClient(cred, "ap-beijing", clientProfile); // 实例化一个请求对象,每个接口都会对应一个request对象 DeleteCloudRecordingRequest req = new DeleteCloudRecordingRequest(); req.setSdkAppId(Long.valueOf(sdkAppId)); // SdkAppId – TRTC的SDKAppId,和录制的房间所对应的SDKAppId相同 req.setTaskId(taskId); // TaskId – 录制任务的唯一Id,在启动录制成功后会返回 // 返回的resp是一个DeleteCloudRecordingResponse的实例,与请求对象对应 DeleteCloudRecordingResponse resp = client.DeleteCloudRecording(req); // 输出json格式的字符串回包 String s = JSON.toJSONString(resp); return s; } catch (TencentCloudSDKException | IOException e) { 
    return e.toString(); } } 
2.7 云端录制回调

云端录制回调API文档地址:https://cloud.tencent.com/document/product/647/81113

当云端录制回调监听到录制上传成功事件,就会调用下载音视频接口,我们根据我们给我们数据库存储地址的表中标记,

未下载的进行下载。

输入(出)参数我就不做赘述了详细信息请看API文档

 //# 功能:第三方回调sign校验 //# 参数: //# key:控制台配置的密钥key //# body:腾讯云回调返回的body体 //# sign:腾讯云回调返回的签名值sign //# 返回值: //# Status:OK 表示校验通过,FAIL 表示校验失败,具体原因参考Info //# Info:成功/失败信息  @ApiOperation(value = "音视频录制回调接口") @PostMapping("/recordingCallback") public void recordingCallback(@RequestBody String body, HttpServletRequest request) throws Exception { 
    String key = "key"; String sdkAppId = request.getHeader("SdkAppId"); String sign = request.getHeader("Sign"); logger.info("body:"+body); logger.info("sdkAppId:"+sdkAppId); logger.info("sign:"+sign); String resultSign = getResultSign(key,body); logger.info("resultSign:"+resultSign); if (resultSign.equals(sign)) { 
    JSONObject jsonObject = (JSONObject) JSON.parse(body); Integer eventType = jsonObject.getInteger("EventType"); // 事件类型 String eventInfo = jsonObject.getString("EventInfo"); // 事件信息 JSONObject jsonObject1 = (JSONObject) JSON.parse(eventInfo); String taskId = jsonObject1.getString("TaskId"); // 任务ID String payload = jsonObject1.getString("Payload"); // 根据不同事件类型定义不同 JSONObject jsonObject2 = (JSONObject) JSON.parse(payload); String tencentVod = jsonObject2.getString("TencentVod"); // 点播平台信息 JSONObject jsonObject3 = (JSONObject) JSON.parse(tencentVod); if (eventType == 311) { 
    // 录制视频上传成功 String fileId = jsonObject3.getString("FileId"); // 点播平台的唯一 ID String videoUrl = jsonObject3.getString("VideoUrl"); // 点播平台的播放地址 // 进行相关业务逻辑处理 // 311事件证明视频已成功上传到云点播, // 建立相关的数据库用来存储音视频录制地址并和相关的业务ID绑定,用于后续下载 / * 使用线程池进行音视频下载,控制最大并发数,防止资源抢占导致服务崩溃 */ ExecutorService executorService = Executors.newCachedThreadPool(); executorService.submit(() -> { 
    try { 
    downloadVideo(fileIds); TimeUnit.SECONDS.sleep(1000 * 60 * 30); // 等待30分钟 } catch (Exception e) { 
    e.printStackTrace(); } }); } } else { 
    logger.debug("{'Status': 'FAIL', 'Info': '校验失败'}"); } logger.debug("腾讯云测试成功"); } 
2.8 音视频下载
2.8.1 音视频列表查询接口

为了保证数据的安全性,我们需要把云点播的音视频存储到医院的服务器上面,然后将云点播上面的音视频删除掉,然后将存储地址表中的视频路径改成服务器的路径。

音视频下载API文档地址:https://cloud.tencent.com/document/product/266/84093

https://cloud.tencent.com/document/product/266/31763

通过fileIds查询出在云点播上面存储的音视频列表,然后下载,再删除

输入(出)参数我就不做赘述了详细信息请看API文档

讯享网 / * 查询出音视频集合,并下载,在将云点播上面的音视频删除 * @param fileIds 点播平台唯一ID集合 * @throws Exception */ private void downloadVideo(String [] fileIds) throws Exception { 
    try{ 
    //创建文件对象 Properties properties = new Properties(); //加载文件获取数据 文件带后缀 properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream ("application.properties")); //根据key来获取value String secretId = properties.getProperty("secretid"); String secretKey = properties.getProperty("secretkey"); // 实例化一个认证对象,入参需要传入腾讯云账户 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); // 实例化一个http选项,可选的,没有特殊需求可以跳过 HttpProfile httpProfile = new HttpProfile(); httpProfile.setEndpoint("vod.tencentcloudapi.com"); // 实例化一个client选项,可选的,没有特殊需求可以跳过 ClientProfile clientProfile = new ClientProfile(); clientProfile.setHttpProfile(httpProfile); // 实例化要请求产品的client对象,clientProfile是可选的 VodClient client = new VodClient(cred, "ap-beijing", clientProfile); // 实例化一个请求对象,每个接口都会对应一个request对象 DescribeMediaInfosRequest req = new DescribeMediaInfosRequest(); req.setFileIds(fileIds); String[] basicInfos = { 
   "basicInfo"}; req.setFilters(basicInfos); // 返回的resp是一个DescribeMediaInfosResponse的实例,与请求对象对应 DescribeMediaInfosResponse resp = client.DescribeMediaInfos(req); // 输出json格式的字符串回包 logger.info(DescribeMediaInfosResponse.toJsonString(resp)); String json = DescribeMediaInfosResponse.toJsonString(resp); JSONObject jsonObject = (JSONObject) JSON.parse(json); JSONArray jsonArray = jsonObject.getJSONArray("MediaInfoSet"); // 媒体文件信息列表。 for (int i = 0; i < jsonArray.size(); i++) { 
    JSONObject jsonObject1 = jsonArray.getJSONObject(i); String fileId = jsonObject1.getString("FileId"); // 点播平台的唯一 ID String basicInfo = jsonObject1.getString("BasicInfo"); // 基础信息 JSONObject jsonObject2 = (JSONObject) JSON.parse(basicInfo); String mediaUrl = jsonObject2.getString("MediaUrl"); // 文件地址 String downPath = downloadImage(mediaUrl); // 下载音视频(返回本地下载地址) // 将未下载的音视频列表查询出来,进行下载到服务器上面,并更新数据库数据 // 业务逻辑处理 delVideo(fileId); // 删除音视频 logger.info(downPath); // 本地地址 } logger.info("下载音视频成功"); } catch (TencentCloudSDKException e) { 
    logger.debug(e.toString()); } catch (IOException e) { 
    e.printStackTrace(); } logger.debug("腾讯云测试成功"); } 
2.8.2 音视频下载接口

通过fileIds查询出在云点播上面存储的音视频列表,然后下载,再删除

下载地址:https://blog.csdn.net/_/article/details/

代码

 / * 将视频下载到本地 * @param fileUrl 视频路径 * @return */ public String downloadImage(String fileUrl) { 
    long l = 0L; String path = null; String staticAndMksDir = null; if (fileUrl != null) { 
    //下载时文件名称 String fileName = fileUrl.substring(fileUrl.lastIndexOf(".")); try { 
    String dataStr = new SimpleDateFormat("yyyyMMdd").format(new Date()); String uuidName = UUID.randomUUID().toString(); path = "resources/images/"+dataStr+"/"+uuidName+fileName; staticAndMksDir = Paths.get(ResourceUtils.getURL("classpath:").getPath(),"resources", "images",dataStr).toFile().toString(); HttpUtil.downloadFile(fileUrl, staticAndMksDir + File.separator + uuidName + fileName); } catch (Exception e) { 
    e.printStackTrace(); } finally { 
    logger.debug("下载成功"); } } log.info(System.currentTimeMillis()-l); return path; } 
2.9 删除音视频

为了保证数据的安全性,我们需要把云点播的音视频存储到医院的服务器上面,然后将云点播上面的音视频删除掉,然后将存储地址表中的视频路径改成服务器的路径。

音视频删除API文档地址:https://cloud.tencent.com/document/product/266/31764

输入(出)参数我就不做赘述了详细信息请看API文档

讯享网 / * 删除音视频 * @param fileId 通过点播平台唯一ID删除掉音视频 * @throws Exception */ private void delVideo(String fileId) throws Exception { 
    try{ 
    //创建文件对象 Properties properties = new Properties(); //加载文件获取数据 文件带后缀 properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream ("application.properties")); //根据key来获取value String secretId = properties.getProperty("secretid"); String secretKey = properties.getProperty("secretkey"); // 实例化一个认证对象,入参需要传入腾讯云账户 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); // 实例化一个http选项,可选的,没有特殊需求可以跳过 HttpProfile httpProfile = new HttpProfile(); httpProfile.setEndpoint("vod.tencentcloudapi.com"); // 实例化一个client选项,可选的,没有特殊需求可以跳过 ClientProfile clientProfile = new ClientProfile(); clientProfile.setHttpProfile(httpProfile); // 实例化要请求产品的client对象,clientProfile是可选的 VodClient client = new VodClient(cred, "", clientProfile); // 实例化一个请求对象,每个接口都会对应一个request对象 DeleteMediaRequest req = new DeleteMediaRequest(); req.setFileId(fileId); // 返回的resp是一个DeleteMediaResponse的实例,与请求对象对应 DeleteMediaResponse resp = client.DeleteMedia(req); // 输出json格式的字符串回包 // 输出json格式的字符串回包 logger.info("删除音视频成功"); logger.info("删除音视频:", DeleteMediaResponse.toJsonString(resp)); } catch (TencentCloudSDKException e) { 
    logger.debug(e.toString()); } } 

至此我们集成腾讯音视频就结束了

小讯
上一篇 2025-03-26 12:16
下一篇 2025-03-25 12:56

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/27689.html