腾讯云的云直播和即时通讯IM开发(全网最详细之一)

如果你也在面临做直播的 业务的时候迷茫的时候,来看看吧。

腾讯云–云直播

最近这几个项目也是在做直播相关的App开发,之前刚做的时候,自己也经历很多坑。
慢慢的爬过这些坑,做了几款直播软件以后,也算有了心得。更加熟练的调用。
分享自己的做直播的流程,以及配合腾讯云的直播官方文档的调用。

我做的这几个直播的项目是基于腾讯云的云直播服务进行开发的

  1. 腾讯云的账户分:个人账户和企业认证账户。
  2. 只有认证方式是不同的,其他的操作已经步骤以及思路都是一样的。
  3. 首先: 先去认证账户信息,进行实名认证的流程后,就可以使用腾讯云的服务了。
  4. 新的用户首次认证的时候,都可以免费体验腾讯云的云直播和即时通讯IM的服务(免费试用期一个月)
  5. 下面直接进入开发吧,不多啰嗦。

登录腾讯云的管理后台

在这里插入图片描述

  1. 点击云直播。(如果你是第一次使用腾讯云的云直播的话,你是需要去开通云直播服务后,才能可以进行使用)

在这里插入图片描述

-----现在看到的就是云直播的后台
1:首先,你要理解,直播是怎么回事?-----回答:直播利用的就是腾讯提供的云直播的服务,推流,拉流,客户端(主播)发起推流,创建直播房间成功后,创建IM群组成功后,客户端(用户)发起拉流。用户进入直播间可以看到主播的直播画面,这就是拉流成功。主播进行开播,开播后,主播可以看到自己的画面,能持续直播并且有画面,说明此时的推流地址是没问题的,可以进行直播。
2:其次就是怎么配置腾讯云的云直播后台的配置 ----回答:核心的配置,就是配置两条已经备案过的域名(一条域名用来做推流域名,另一条域名用来做拉流域名)
3:腾讯云的直播如何集成到自己的代码开发中去 —回答:集成自己的代码开发,这块我会在后面进行详细的讲解,以及代码的示范提供。

参考腾讯云的官方文档配置推拉流域名
在这里插入图片描述
新手指南

建议新手区参考新手指南,
先去看看,把直播的这两条推拉流域名配置好。
一条推流域名,一条拉流域名(都是需要去备案的)

在这里插入图片描述

其次就是要开通新手免费使用的流量包,没有流量包是不能进行直播的。

在这里插入图片描述

接下来需要了解,如何生成推流拉流地址。
先看腾讯云给出的生成规则。
只要你满足生成规则,你生成的流地址是正常的,就可以用来进行推拉流,进行正常的直播。

在这里插入图片描述
先看官网的地址生成器:

1:看看需要哪些参数
2:看看地址解析说明的配置
3:推拉流地址是要经过我们后台去代码生成的,然后返回给前端,安卓或者IOS,拿着地址去调用腾讯云的直播SDK,进行推流,拉流,完成APP端的主播,开播,用户进入直播间去观看,等功能。

在这里插入图片描述
具体看看,怎么生成推拉流的地址的

在这里插入图片描述
在这里插入图片描述

在这里,有官网提供的推拉流地址的生成代码


package com.test;import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;public class Test {public static void main(String[] args) {System.out.println(getSafeUrl("txrtmp", "11212122", 1469762325L));}private static final char[] DIGITS_LOWER ={'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};/** 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);}
}

下面是我改进后的代码,大家可以作为参考:

package com.*.utils;import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.time.ZoneOffset;/*** 推拉流生成工具* @author * @date 2020-10-16 12:11:58*/
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'};private static final String pushKey = "f58*********d4f5d"; //域名管理中点击推流域名-->推流配置-->鉴权配置-->主KEYprivate static final String pushDomain = "*********"; //云直播控制台配置的推流域名private static final String pullDomain = "*********";//云直播控制台配置的拉流域名private static final String AppName = "live"; //直播SDK-->应用管理-->自己创建应用中的应用名称public static void main(String[] args) {long LiveRecordId = Long.parseLong(GenerateIdUtil.generateIdUtilId());System.out.println(LiveRecordId);LocalDateTime localDateTime =  LocalDateTime.now();long nowTime = localDateTime.toEpochSecond(ZoneOffset.of("+8"));long endTime = nowTime + 60*60*12;     // 默认12小时LiveAddress addressUrl = AutoAddressUtils.getAddressUrl(GenerateIdUtil.generateIdUtilId(), endTime);System.out.println(addressUrl.getPushRTMP());System.out.println(addressUrl.getPullUDP());System.out.println(addressUrl.getPullRTMP());System.out.println(addressUrl.getPullM3U8());System.out.println(addressUrl.getPullFLV());}public static LiveAddress getAddressUrl(String streamName, long txTime) {String safeUrl = getSafeUrl(pushKey, streamName, txTime);LiveAddress liveAddress = new LiveAddress();liveAddress.setPushRTMP("rtmp://"+pushDomain+"/"+AppName+"/"+streamName+"?"+safeUrl);liveAddress.setPullRTMP("rtmp://"+pullDomain+"/"+AppName+"/"+streamName+"?"+safeUrl);liveAddress.setPullFLV("http://"+pullDomain+"/"+AppName+"/"+streamName+".flv?"+safeUrl);liveAddress.setPullM3U8("http://"+pullDomain+"/"+AppName+"/"+streamName+".m3u8?"+safeUrl);liveAddress.setPullUDP("webrtc://"+pullDomain+"/"+AppName+"/"+streamName+"?"+safeUrl);return liveAddress;}/** 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);}
}

1:生成推拉流的地址,前端调用云直播的SDK,拿到推拉流地址,就可以进行直播了。
2:因为我们是要集成代码去进行开发的,现在设计业务表。
3:创建一个直播场次表(live_record),既是每一次开播都是一个新的直播场次。

/*Navicat MySQL Data TransferSource Server         : 192.168.1.105Source Server Type    : MySQLSource Server Version : 50730Source Host           : 111.6.79.10:3317Source Schema         : liveTarget Server Type    : MySQLTarget Server Version : 50730File Encoding         : 65001Date: 16/10/2020 17:41:45
*/SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for live_record
-- ----------------------------
DROP TABLE IF EXISTS `live_record`;
CREATE TABLE `live_record`  (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键的ID\r\n',`live_record_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '直播的场次ID',`anchor_code` bigint(20) NULL DEFAULT NULL COMMENT '主播code',`title` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '直播标题',`label` int(11) NULL DEFAULT NULL COMMENT '直播标签 分类',`live_cover` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '直播封面',`stream_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '流名称',`push_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '推流地址',`start_time` datetime(0) NULL DEFAULT NULL COMMENT '开播时间',`end_time` datetime(0) NULL DEFAULT NULL COMMENT '关播时间',`stream_end_time` datetime(0) NULL DEFAULT NULL COMMENT '流结束时间(流存活时间)',`showing` int(1) NULL DEFAULT 1 COMMENT '是否正在直播  1正在直播  0 已经直播',`recommend` int(1) NULL DEFAULT 1 COMMENT '是否推荐  0不推荐  1推荐',`watch_num` int(1) NULL DEFAULT 0 COMMENT '观看人数',`like_num` int(1) NULL DEFAULT 0 COMMENT '点赞人数',`location_longitude` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '定位经度',`location_latitude` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '定位纬度',`location_province` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '定位省份',`location_city` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '定位城市',`status` int(11) NULL DEFAULT 1 COMMENT '1正常  预留',`pull_rtmp_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '拉流地址',`pull_flv_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '拉流地址',`pull_m3u8_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '拉流地址',`pull_udp_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '拉流地址',`live_module` int(11) NULL DEFAULT NULL COMMENT '0城市1医疗2旅游',`room_number` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '直播的场次ID  和live_record_id值一样',`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 105 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '直播场次表' ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;

1:设计完直播场次表(live_record)
2:开播接口---->开播的原理:APP端向java后台发送开播请求,主要是后台代码生成一条开播记录,以及对应的推流拉流地址。App拿到请求回来的(合法的推拉流)推拉流地址,然后调用腾讯云的SDK进行推流,如果调用SDK成功,且推流地址正确,则直播就能被创建成功。拉流也是一样的。调用腾讯云的SDK进行拉流,如果调用SDK成功,且拉流地址正确。直播就能被用户访问且观看。
3:关播接口 ---->关播的原理:APP端(即是安卓,IOS)调用腾讯云的关播断流的SDK,调用成功以后,且调用成功后,再回调java后台,修改后台自己设计的live_record 表的状态值(0:不显示 1:显示)。修改的是我们后台自己的表设计的状态值。
4:送佛送到西,写一套完整的直播的开播流程代码。

直播场次实体

/*** 直播场次表-->根据live_record表进行生成的* @author * @date 2020-10-16 12:11:58*/
@Data
@TableName("live_record")
public class LiveRecord implements Serializable {private static final long serialVersionUID = 1L;/*** 表的主键ID*/@TableId(type = IdType.AUTO)@NotNull(message = "表的主键ID"+"不能为空",groups = UpdateGroup.class)@ApiModelProperty(name = "id",value = "表的主键ID")private Long id;/*** 流名称*/@ApiModelProperty(name = "streamName",value = "流名称")private String streamName;/*** 直播的场次ID*/@ApiModelProperty(name = "liveRecordId",value = "直播的场次ID")private String liveRecordId;/*** 主播code*/@ApiModelProperty(name = "anchorCode",value = "主播code")private Long anchorCode;/*** 直播标题*/@ApiModelProperty(name = "title",value = "直播标题")private String title;/*** 直播标签 分类*/@ApiModelProperty(name = "label",value = "直播标签 分类")private Integer label;/*** 直播封面*/@ApiModelProperty(name = "liveCover",value = "直播封面")private String liveCover;/*** 推流地址*/@ApiModelProperty(name = "pushUrl",value = "推流地址")private String pushUrl;/*** 开播时间*/@ApiModelProperty(name = "startTime",value = "开播时间")private LocalDateTime startTime;/*** 关播时间*/@ApiModelProperty(name = "endTime",value = "关播时间")private LocalDateTime endTime;/*** 流结束时间*/@ApiModelProperty(name = "streamEndTime",value = "流结束时间")private LocalDateTime streamEndTime;/*** 是否正在直播  1正在直播  0 历史直播*/@ApiModelProperty(name = "showing",value = "是否正在直播  1正在直播  0 历史直播")private Integer showing;/*** 是否推荐  0不推荐  1推荐*/@ApiModelProperty(name = "isRecommend",value = "是否推荐  0不推荐  1推荐")private Integer recommend;/*** 观看人数*/@ApiModelProperty(name = "watchNum",value = "观看人数")private Integer watchNum;/*** 点赞人数*/@ApiModelProperty(name = "likeNum",value = "点赞人数")private Integer likeNum;/*** 定位经度*/@ApiModelProperty(name = "locationLongitude",value = "定位经度")private String locationLongitude;/*** 定位纬度*/@ApiModelProperty(name = "locationLatitude",value = "定位纬度")private String locationLatitude;/*** 定位省份*/@ApiModelProperty(name = "locationProvince",value = "定位省份")private String locationProvince;/*** 定位城市*/@ApiModelProperty(name = "locationCity",value = "定位城市")private String locationCity;/*** 1正常  预留*/@ApiModelProperty(name = "status",value = "1正常  预留")private Integer status;/*** 拉流地址*/@ApiModelProperty(name = "pullRtmpUrl",value = "拉流地址")private String pullRtmpUrl;/*** 拉流地址*/@ApiModelProperty(name = "pullFlvUrl",value = "拉流地址")private String pullFlvUrl;/*** 拉流地址*/@ApiModelProperty(name = "pullM3u8Url",value = "拉流地址")private String pullM3u8Url;/*** 拉流地址*/@ApiModelProperty(name = "pullUdpUrl",value = "拉流地址")private String pullUdpUrl;/*** 创建时间*/@ApiModelProperty(name = "createTime",value = "创建时间")private LocalDateTime createTime;/*** 更新时间*/@ApiModelProperty(name = "updateTime",value = "更新时间")private LocalDateTime updateTime;/*** 房间号*/@ApiModelProperty(name = "roomNumber",value = "房间号")private String roomNumber;
}

封装一个推拉流地址实体

package com.*.utils;/*** 推拉流地址*/
public class LiveAddress {private String pushRTMP;private String pullRTMP;private String pullFLV;private String pullM3U8;private String pullUDP;public String getPushRTMP() {return pushRTMP;}public void setPushRTMP(String pushRTMP) {this.pushRTMP = pushRTMP;}public String getPullRTMP() {return pullRTMP;}public void setPullRTMP(String pullRTMP) {this.pullRTMP = pullRTMP;}public String getPullFLV() {return pullFLV;}public void setPullFLV(String pullFLV) {this.pullFLV = pullFLV;}public String getPullM3U8() {return pullM3U8;}public void setPullM3U8(String pullM3U8) {this.pullM3U8 = pullM3U8;}public String getPullUDP() {return pullUDP;}public void setPullUDP(String pullUDP) {this.pullUDP = pullUDP;}}

直播场次生成工具

package com.*.utils;import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.locks.ReentrantLock;public class GenerateIdUtil {// 使用单例模式,不允许直接创建实例private GenerateIdUtil() {}// 创建一个空实例对象,类需要用的时候才赋值private static GenerateIdUtil instance = null;// 单例模式--懒汉模式public static synchronized GenerateIdUtil getInstance() {if (instance == null) {instance = new GenerateIdUtil();}return instance;}// 全局自增数private static int count = 1;// 格式化的时间字符串private static final SimpleDateFormat sdf = new SimpleDateFormat("ddHHmmss");// 获取当前时间年月日时分秒毫秒字符串private static String getNowDateStr() {return sdf.format(new Date());}// 记录上一次的时间,用来判断是否需要递增全局数private static String now = null;//定义锁对象private final static ReentrantLock lock=new ReentrantLock();/*** 随机生成11位数字的随机数* @return*/public static String generateIdUtilId(){String Newnumber=null;String dateStr=getNowDateStr();lock.lock();//加锁//判断是时间是否相同if (dateStr.equals(now)) {try {if (count >= 10000){count = 1;}if (count<10) {Newnumber =  getNowDateStr()+"00"+count;}else if (count<100) {Newnumber =   getNowDateStr()+"0"+count;} else {Newnumber =  getNowDateStr()+count;}count++;} catch (Exception e) {}finally{lock.unlock();}}else{count=1;now =getNowDateStr();try {if (count >= 10000){count = 1;}if (count<10) {Newnumber =  getNowDateStr()+"00"+count;}else if (count<100) {Newnumber =  getNowDateStr()+"0"+count;}else  {Newnumber = getNowDateStr()+count;}count++;} catch (Exception e) {}finally{lock.unlock();}}return Newnumber;//返回的值}/*** 生成32位的随机的数字* @return*/public static String generateRandomTO32(int num) {String chars = "0123456789";char[] rands = new char[num];for (int i = 0; i < num; i++) {int rand = (int) (Math.random() * 10);rands[i] = chars.charAt(rand);}return String.valueOf(rands);}
}

直播的开播与关播

Controller层

package com.*.controller;import com.*.entity.LiveRecord;
import com.*.result.ResultObject;
import com.*.service.LiveBroadcastService;
import com.*.vo.LiveBroadCastVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;/*** 开播的模块* @author * @date 2020-10-16 12:11:58*/
@RequestMapping("/liveBroadCast")
public class LiveBroadCastController {@Autowiredprivate LiveBroadcastService liveBroadcastService;@ApiOperation("开播")@PostMapping("/open")public ResultObject open(@RequestBody LiveRecord liveRecord) {ResultObject resultObject = liveBroadcastService.open(liveRecord);return resultObject;}@ApiOperation("关播")@PostMapping("/close")public ResultObject close(@RequestBody LiveBroadCastVO liveBroadCastVO) {ResultObject resultObject = liveBroadcastService.close(liveBroadCastVO);return resultObject;}
}

service层

package com.*.service;
import com.*.entity.LiveRecord;
import com.*.result.ResultObject;
import com.*.vo.LiveBroadCastVO;/*** APP端开播模块* @author * @date 2020-10-16 12:11:58*/
public interface LiveBroadcastService {/*** 开播* @param liveRecord* @return*/ResultObject open(LiveRecord liveRecord);/*** 关播* @param liveBroadCastVO* @return*/ResultObject close(LiveBroadCastVO liveBroadCastVO);}

impl


/*** APP端开播模块* @author * @date 2020-10-16 12:11:58*/
@Service("LiveBroadcastService")
public class LiveBroadcastServiceImpl implements LiveBroadcastService {@Resourceprivate LiveRecordMapper liveRecordMapper;  //这个接口自己去实现@Transactional@Overridepublic ResultObject open(LiveRecord liveRecord) {if (liveRecord.getTitle() == null) {return ResultObject.error("直播标题不能为空");}if (liveRecord.getLocationLatitude() == null || liveRecord.getLocationLongitude() == null) {return ResultObject.error("直播定位没有开启");}if (liveRecord.getLiveCover() == null) {return ResultObject.error("直播的封面未上传");}//开播LocalDateTime localDateTime =  LocalDateTime.now();long nowTime = localDateTime.toEpochSecond(ZoneOffset.of("+8"));
//        long endTime = nowTime + 60*60*2;long endTime = nowTime + 60*3;LiveRecord liveRecord1 = new LiveRecord();String liveRecordId = GenerateIdUtil.generateIdUtilId();liveRecord1.setLiveRecordId(liveRecordId);liveRecord1.setTitle(liveRecord.getTitle());liveRecord1.setLiveCover(liveRecord.getLiveCover());liveRecord1.setAnchorCode(liveRecord.getAnchorCode());
/*        String toString = liveRecord.getAnchorCode().toString();String substring = toString.substring(toString.length()-6, toString.length());*/
//        liveRecord1.setRoomNumber(Integer.parseInt(substring));liveRecord1.setRoomNumber(liveRecordId);liveRecord1.setLocationProvince(liveRecord.getLocationProvince());liveRecord1.setLocationCity(liveRecord.getLocationCity());liveRecord1.setLabel(liveRecord.getLabel());liveRecord1.setLiveModule(liveRecord.getLiveModule());liveRecord1.setStartTime(localDateTime);liveRecord1.setCreateTime(localDateTime);liveRecord1.setShowing(0);  // 默认生成的直播不显示liveRecord1.setStreamEndTime(Instant.ofEpochSecond(endTime).atOffset(ZoneOffset.of("+08:00")).toLocalDateTime());liveRecord1.setLocationLatitude(liveRecord.getLocationLatitude());liveRecord1.setLocationLongitude(liveRecord.getLocationLongitude());LiveAddress addressUrl =AutoAddressUtils.getAddressUrl(liveRecordId, endTime);liveRecord1.setStreamName(liveRecordId);liveRecord1.setPushUrl(addressUrl.getPushRTMP());liveRecord1.setPullFlvUrl(addressUrl.getPullFLV());liveRecord1.setPullM3u8Url(addressUrl.getPullM3U8());liveRecord1.setPullRtmpUrl(addressUrl.getPullRTMP());liveRecord1.setPullUdpUrl(addressUrl.getPullUDP());try {liveRecordMapper.insert(liveRecord1); //自己写一个直播场次数据插入的接口} catch (Exception e) {e.printStackTrace();}return ResultObject.ok(liveRecord1);}@Transactional@Overridepublic ResultObject close(LiveBroadCastVO liveBroadCastVO) {// 修改直播场次的状态if (liveBroadCastVO.getLiveRecordId() == null) {return ResultObject.error("参数异常");}//修改状态值为0liveRecordMapper.updateShowing(liveBroadCastVO); //自己写一个修改直播的状态值的接口return ResultObject.ok("关播成功", null);}
}

如果不考虑直播的其他的一些异常的情况的话,简单的额直播的开播,关播,已经做好了。
把写好的开播,关播接口,提供给APP就行。
如果需要额外帮助:WX:380666989

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/47787.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入理解SeaTunnel:易用、高性能、支持实时流式和离线批处理的海量数据集成平台

深入理解SeaTunnel&#xff1a;易用、高性能、支持实时流式和离线批处理的海量数据集成平台 一、认识SeaTunnel二、SeaTunnel 系统架构、工作流程与特性三、SeaTunnel工作架构四、部署SeaTunnel1.安装Java2.下载SeaTunnel3.安装连接器 五、快速启动作业1.添加作业配置文件以定义…

Tapdata Cloud 场景通关系列:将数据导入阿里云 Tablestore,获得毫秒级在线查询和检索能力

【前言】作为中国的 “Fivetran/Airbyte”, Tapdata Cloud 自去年发布云版公测以来&#xff0c;吸引了近万名用户的注册使用。应社区用户上生产系统的要求&#xff0c;Tapdata Cloud 3.0 将正式推出商业版服务&#xff0c;提供对生产系统的 SLA 支撑。Tapdata 目前专注在实时数…

JAVA集成腾讯云即时通讯IM服务端

一. 腾讯IM快速入门 1. 注册腾讯云账号&#xff0c;找到即时通信IM控制台 腾讯IM控制台&#xff1a;登录 - 腾讯云 2. 创建即时通信应用 3. 进到应用里面可以看到这个应用的SDKAppID和key(密钥) 4. 可以参考官方提供的“服务端API接口文档”和“接口调试工具” API接口文档&am…

100套基于Java开发的毕业设计项目,完成项目源码可共分为五季,每季大约20套项目,希望大家多多支持持续关注哦!

很多大三大四的学生&#xff0c;苦于没有参考的毕设资料&#xff0c;或者下载的资料零零散散、代码有问题、数据有问题等等&#xff0c;造成毕设出现问题影响大学毕业。 现在&#xff0c;我们提供了经过审核的100个项目源码和对应的辅导视频&#xff0c;让大家在短时间内可以完…

chatgpt赋能python:Python选择器的SEO优化

Python选择器的SEO优化 作为一名有10年Python编程经验的工程师&#xff0c;我深知Python在Web开发和SEO优化方面的重要性。在这篇文章中&#xff0c;我将会介绍Python选择器的SEO优化并阐述如何使用它。 什么是Python选择器&#xff1f; Python选择器是一种解析HTML、CSS、X…

当我们聊飞书时,我们应该聊什么?

飞书&#xff0c;2020年的明星产品。沉寂了许久的产品界&#xff0c;终于迎来了话题明星。 我们已经聊腻了抖音快手短视频&#xff0c;看烦了直播电商小商店。现在我们终于转移了视线&#xff0c;转移到了飞书身上。没错&#xff0c;这次还是字节跳动。 那么&#xff0c;当我们…

吴恩达ChatGPT《LangChain Chat with Your Data》笔记

文章目录 1. Introduction2. Document Loading2.1 Retrieval Augmented Generation&#xff08;RAG&#xff09;2.2 Load PDFs2.3 Load YouTube2.4 Load URLs2.5 Load Notion 3. Document Splitting3.1 Splitter Flow3.2 Character Splitter3.3 Token Splitter3.4 Markdown Spl…

协同办公笔记软件综合评测:飞书、语雀、Notion、FlowUs、Wolai

飞书文档 介绍 飞书文档汇集了文档、表格、思维笔记等在线创作工具&#xff0c;同时为文件提供安全、强大的云端存储和内容管理能力&#xff0c;文档所有者可以根据需要灵活设置浏览、编辑、评论、分享等权限&#xff0c;让协作有序又高效。 核心特色 文稿类型&#xff1a;包括…

差评近一半,用 Python 分析胡歌的《猎场》到底值不值得看?

作者 | 布道 11 月 6 日&#xff0c;湖南卫视已经开播被称作年度压轴的大戏“猎场”&#xff0c;迅速占领各大榜单&#xff0c;成为一部高热度的电视剧。但是在豆瓣上却形成了两极分化。截止 11 月 8 日&#xff0c;该剧在豆瓣上的评分为 5.7 分。相比较胡歌之前《琅琊榜》的 9…

你评论,我赠书~【哈士奇赠书 - 13期】-〖Python程序设计-编程基础、Web开发及数据分析〗参与评论,即可有机获得

大家好&#xff0c;我是 哈士奇 &#xff0c;一位工作了十年的"技术混子"&#xff0c; 致力于为开发者赋能的UP主, 目前正在运营着 TFS_CLUB社区。 &#x1f4ac; 人生格言&#xff1a;优于别人,并不高贵,真正的高贵应该是优于过去的自己。&#x1f4ac; &#x1f4…

【Thunder送书 | 第三期 】「Python系列丛书」

文章目录 前言《Python高效编程——基于Rust语言》《Python从入门到精通》《Python Web深度学习》《Python分布式机器学习》文末福利 | 赠书活动 前言 Thunder送书第三期开始啦&#xff01;前面两期都是以【文末送书】的形式开展&#xff0c;本期将赠送Python系列丛书&#xff…

chatgpt赋能python:Python怎么隐藏密码:常用的方法和技巧

Python怎么隐藏密码&#xff1a;常用的方法和技巧 互联网时代&#xff0c;用户需要经常输入账号密码来进行在线交互。但是&#xff0c;账户密码的安全性问题也随之而来。为了防止私人信息被泄露&#xff0c;很多应用程序都需要对用户密码进行加密和隐藏。本文将介绍Python中常…

chatgpt赋能python:Python安装和打开教程

Python安装和打开教程 Python作为一种高效、灵活、易学易用的编程语言&#xff0c;越来越受到广大程序员的青睐&#xff0c;越来越多的人想要学习Python。在学习Python之前&#xff0c;首先要进行Python的安装和打开。那么&#xff0c;本篇文章将为您介绍如何安装和打开Python…

10分钟建立一个自媒体秘书——国产企业级大模型文心千帆初体验

目录 一、文心千帆简介二、模型搭建与调优2.1、数据准备——为秘书准备资料2.2、模型调优——为秘书安排培训课2.3、模型发布——让秘书开始上班 三、大模型助力产业智能化变革3.1、AI航海的启航引擎——大模型3.2、文心千帆体验心得 当一个轻轻松松的甩手掌柜&#xff0c;让AI…

微信登录的接口

目录 第一步&#xff1a;生成微信扫描二维码(网页内嵌的二维码)接口第二步&#xff1a;处理微信回调 &#xff0c;获取扫描人信息 微信开放平台&#xff1a; https://developers.weixin.qq.com/doc/oplatform/Mobile_App/WeChat_Login/Development_Guide.html 第一步&#xf…

IBOX NFT 数字藏品价格 监控 工具 科技

IBOX NFT 数字藏品价格监控工具 科技 -7月25号 由于原来的pc版本的科技使用的web端口&#xff0c;迫于ibox关闭的web端下单接口 所有不得已又开发了一个android的科技自用 锁单、监控、公告自动锁单、抢购、查询仓库交易信息 ibox 数字藏品最近比较火&#xff0c;所以开发…

通达信插件获取并存储通达信商品指数的实时数据

一、引子 通达信商品指数一共有23个&#xff0c;如下图所示&#xff1a; 如果想获取历史数据&#xff0c;只需要通过通达信的数据下载和导出功能即可&#xff0c;现在我们需要获取这23个指数的实时数据&#xff0c;通过导出功能就没有办法了。 在最初的阶段&#xff0c;考虑的…

免费获得筹码分布接口交易数据,Tushare的使用方法

在做量化交易时需要活动历史数据&#xff0c;Tushare是一个免费提供各类金融数据 , 助力智能投资与创新型投资的平台。在这个平台上可以免费获得股票、期货和外汇的各种数据。下面就给大家介绍一下Tushare的注册和使用方法。 使用流程是&#xff1a;1、用户注册 - 2、用户使用…

哪个软件能实盘测试策略,Quicklib提供期货CTA策略实盘模拟监控的好工具(原创)...

大家都知道开发期货程序化交易&#xff0c;是一个非常繁杂的工作&#xff0c;并且在策略实盘运行过程中&#xff0c;很难提供一个资金曲线进行查看&#xff0c;我开发了一款资金曲线分时图工具&#xff0c;可以将期货CTP账户的资金曲线绘制出来&#xff0c;方便检查实盘策略中的…

HCIA第二天笔记

思维导图 HCIA第二天笔记 IP报文头部 图 第二行分别是&#xff1a;标识字段&#xff0c;标志位和片偏移字段 标识字段&#xff1a;相当于序列号&#xff0c;假设给第一个分片的报文序号随即为x则后续的每个报文1 标志位&#xff1…