一、生成推流地址
package com.fitness.club.common.utils.tecentCloud;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.live.v20180801.LiveClient;
import com.tencentcloudapi.live.v20180801.models.*;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Date;
/**
* 推拉流生成工具
*/
public class AutoAddressUtils {
private static final char[] DIGITS_LOWER =
{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
// 用于 生成推流防盗链的key 域名管理中点击推流域名-->推流配置-->鉴权配置-->主KEY
// private static final String PUSH_KEY = "";
// // API密钥id
// private static final String SECRET_ID = "";
// // API密钥key
// private static final String SECRET_KEY = "";
// // 推流域名
// public static final String PUSH_DOMAIN = "";
// // 拉流域名
// public static final String PULL_DOMAIN = "";
// //云直播回调密钥
// public static final String CALL_BACK_KEY = "";
//app名称
public static final String APP_NAME = "live";
/**
* 获取推流地址
*
* @param streamName
* @param txTime
* @return
*/
public static String getPushRTMPUrl(String streamName, long txTime) {
String safeUrl = getSafeUrl(PUSH_KEY, streamName, txTime);
return "rtmp://" + PUSH_DOMAIN + "/" + APP_NAME + "/" + streamName + "?" + safeUrl;
}
/*
* KEY+ streamName + txTime
*/
private static String getSafeUrl(String key, String streamName, long txTime) {
String input = new StringBuilder().
append(key).
append(streamName).
append(Long.toHexString(txTime).toUpperCase()).toString();
String txSecret = null;
try {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
txSecret = byteArrayToHexString(
messageDigest.digest(input.getBytes("UTF-8")));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return txSecret == null ? "" :
new StringBuilder().
append("txSecret=").
append(txSecret).
append("&").
append("txTime=").
append(Long.toHexString(txTime).toUpperCase()).
toString();
}
private static String byteArrayToHexString(byte[] data) {
char[] out = new char[data.length << 1];
for (int i = 0, j = 0; i < data.length; i++) {
out[j++] = DIGITS_LOWER[(0xF0 & data[i]) >>> 4];
out[j++] = DIGITS_LOWER[0x0F & data[i]];
}
return new String(out);
}
}
二、腾讯云直播,回调时,如何获取参数
/**
* 推断流回调
* @param request
* @throws Exception
*/
@RequestMapping("/liveCallBack")
public void liveCallBack(HttpServletRequest request) throws Exception {
//HTTP POST 请求,包体内容为 JSON
ServletInputStream in = request.getInputStream();
//把流转化成字符串
String content = IOUtils.toString(in, "UTF-8");
//获取参数
LiveCallBackVo liveCallBackVo = JSON.parseObject(content, LiveCallBackVo.class);
//后台服务器在收到通知消息后可以根据同样的算法确认 sign 是否正确,进而确认消息是否确实来自腾讯云后台。
if (liveCallBackVo != null) {
//后台服务器在收到通知消息后可以根据同样的算法确认 sign 是否正确,进而确认消息是否确实来自腾讯云后台。
String md5 = MD5Util.getMD5(AutoAddressUtils.CALL_BACK_KEY + liveCallBackVo.getT(), false, 32);
if (!md5.equals(liveCallBackVo.getSign())) {
return;
}
//处理推断流业务
if (StringUtils.isNotBlank(liveCallBackVo.getChannel_id())) {
//查询该直播间是否存在
Live live = liveService.getLive(liveCallBackVo.getChannel_id());
if (live != null) {
if (StringUtils.isNotBlank(liveCallBackVo.getEvent_type())) {
if ("0".equals(liveCallBackVo.getEvent_type())) {
//如果是断流回调
liveService.liveEndBack(live);
System.out.println("进入断流--------------------------------------------");
} else if ("1".equals(liveCallBackVo.getEvent_type())) {
//如果是推流回调
if (1 != live.getLiveState()) {
liveService.liveStartBack(live);
System.out.println("进入推流--------------------------------------------");
}
}
}
}
}
}
}
三、回调参数Vo类
@Data
public class LiveCallBackVo {
//事件类型参数
/**
* 事件类型参数
* 直播推流 event_type = 1
* 直播断流 event_type = 0
*/
private String event_type;
//回调公共参数
/**
* 回调公共参数
* 过期时间,事件通知签名过期 UNIX 时间戳。
*/
private Integer t;
/**
* 回调公共参数
* 事件通知安全签名 sign = MD5(key + t)。
*/
private String sign;
//回调消息参数
/**
* 用户 APPID
*/
private Integer appid;
/**
* 推流域名
*/
private String app;
/**
* 推流路径
*/
private String appname;
/**
* 直播流名称
*/
private String stream_id;
/**
* 同直播流名称
*/
private String channel_id;
/**
* 事件消息产生的 UNIX 时间戳
*/
private String event_time;
/**
* 消息序列号,标识一次推流活动,一次推流活动会产生相同序列号的推流和断流消息
*/
private String sequence;
/**
* 直播接入点的 IP
*/
private String node;
/**
* 用户推流 IP
*/
private String user_ip;
/**
* 用户推流 URL 所带参数
*/
private String stream_param;
/**
* 断流事件通知推流时长,单位毫秒
*/
private String push_duration;
/**
* 推断流错误码
*/
private String errcode;
/**
* 推断流错误描述
* 1 recv rtmp deleteStream 主播端主动断流(删除流时)
* 2 recv rtmp closeStream 主播端主动断流(禁用流时)
* 3 recv() return 0 主播端主动断开 TCP 连接
* 4 recv() return error 主播端 TCP 连接异常
* 7 rtmp message large than 1M 收到流数据异常
* 其他 直播服务内部异常 如需处理请联系腾讯商务人员或者提交工单
*/
private String errmsg;
}
四、MD5
public static String getMD5(String pwd, boolean isUpper, Integer bit) {
String md5 = "";
try {
// 创建加密对象
MessageDigest md = MessageDigest.getInstance("md5");
if (bit == 64) {
BASE64Encoder bw = new BASE64Encoder();
md5 = bw.encode(md.digest(pwd.getBytes(StandardCharsets.UTF_8)));
} else {
// 计算MD5函数
md.update(pwd.getBytes());
byte[] b = md.digest();
int i;
StringBuilder sb = new StringBuilder();
for (byte value : b) {
i = value;
if (i < 0) {
i += 256;
}
if (i < 16) {
sb.append("0");
}
sb.append(Integer.toHexString(i));
}
md5 = sb.toString();
if (bit == 16) {
//截取32位md5为16位
md5 = md5.substring(8, 24);
if (isUpper) {
md5 = md5.toUpperCase();
}
return md5;
}
}
//转换成大写
if (isUpper) {
md5 = md5.toUpperCase();
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("md5加密抛出异常!");
}
return md5;
}
本文主要介绍了腾讯云直播中如何生成推流地址,并详细讲解了直播回调时参数的获取方法。同时,提到了回调参数Vo类的设计以及MD5在其中的应用。
5万+

被折叠的 条评论
为什么被折叠?



