Java 阿里云视频直播开发流程

首先来看一下直播效果 推流工具有很多种(例如OBS、阿里云直播Demo推流、等等,我用的是芯象导播)阿里播放器地址

一、直播基础服务概述 官方文档说明


二、直播域名配置需要两个域名(推流域名、播流域名) 官方文档说明


四、开发流程

1、Java SDK安装 我用的是Apache Maven安装方式 官方安装说明文档

2、Java代码生成推流地址和播放地址 官方案例

java 复制代码
package com.zaiyun.zhibo.utils;

import com.zaiyun.common.core.domain.model.User;
import com.zaiyun.common.utils.DateUtils;
import com.zaiyun.common.utils.SecurityUtils;
import com.zaiyun.zhibo.domain.LiveRooms;
import org.springframework.stereotype.Component;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.HashMap;

/**
 * 阿里视频直播工具类
 */
@Component
public class LiveUtils {
    /**
     * 生成推流地址
     *
     * @param appName    推流AppName
     * @param streamName 推流StreamName
     */
    public static String buildPushUrl(String appName, String streamName) {
        String pushDomain = "zyt.*****.com"; //推流域名
        String pushKey = "2T39rSP2dVro";//推流域名配置的鉴权Key
        String pushUrl = "";
        //推流域名未开启鉴权功能的情况下
        if (pushKey == "") {
            pushUrl = "rtmp://" + pushDomain + "/" + appName + "/" + streamName;
        } else {
            Long timeStamp = System.currentTimeMillis() / 1000L + 3601L;
            String stringToMd5 = "/" + appName + "/" + streamName + "-" + Long.toString(timeStamp) + "-0-0-" + pushKey;
            String authKey = md5(stringToMd5);
            pushUrl = "rtmp://" + pushDomain + "/" + appName + "/" + streamName + "?auth_key=" + Long.toString(timeStamp) + "-0-0-" + authKey;
        }
        return pushUrl;
    }

    /**
     * 生成播放地址
     *
     * @param appName    播放appName(同推流appName)
     * @param streamName 播放streamName,播放源流时,streamName 同推流streamName;播放转码流时,streamName 为推流streamName_{转码模板ID}
     */
    public static HashMap<String, String> buildPullUrl(String appName, String streamName) {
        String pullDomain = "zyb.*****.com"; //播放域名
        String pullKey = "92KiuYjNYr5H"; //播放鉴权Key
        String rtmpUrl = ""; //rtmp的拉流地址
        String hlsUrl = ""; //m3u8的拉流地址
        String flvUrl = ""; //flv的拉流地址
        String rtsUrl = ""; //rts的拉流地址
        //播放域名未配置鉴权Key的情况下
        if (pullKey == "") {
            rtmpUrl = "rtmp://" + pullDomain + "/" + appName + "/" + streamName;
            rtsUrl = "artc://" + pullDomain + "/" + appName + "/" + streamName;
            hlsUrl = "http://" + pullDomain + "/" + appName + "/" + streamName + ".m3u8";
            flvUrl = "http://" + pullDomain + "/" + appName + "/" + streamName + ".flv";
        } else {
            Long timeStamp = System.currentTimeMillis() / 1000L + 3600L;
            String rtmpToMd5 = "/" + appName + "/" + streamName + "-" + Long.toString(timeStamp) + "-0-0-" + pullKey;
            String rtmpAuthKey = md5(rtmpToMd5);
            rtmpUrl = "rtmp://" + pullDomain + "/" + appName + "/" + streamName + "?auth_key=" + Long.toString(timeStamp) + "-0-0-" + rtmpAuthKey;

            String hlsToMd5 = "/" + appName + "/" + streamName + ".m3u8-" + Long.toString(timeStamp) + "-0-0-" + pullKey;
            String hlsAuthKey = md5(hlsToMd5);
            hlsUrl = "http://" + pullDomain + "/" + appName + "/" + streamName + ".m3u8" + "?auth_key=" + Long.toString(timeStamp) + "-0-0-" + hlsAuthKey;

            String flvToMd5 = "/" + appName + "/" + streamName + ".flv-" + Long.toString(timeStamp) + "-0-0-" + pullKey;
            String flvAuthKey = md5(flvToMd5);
            flvUrl = "http://" + pullDomain + "/" + appName + "/" + streamName + ".flv" + "?auth_key=" + Long.toString(timeStamp) + "-0-0-" + flvAuthKey;

            String rtsToMd5 = "/" + appName + "/" + streamName + "-" + Long.toString(timeStamp) + "-0-0-" + pullKey;
            String rtsAuthKey = md5(rtsToMd5);
            rtsUrl = "artc://" + pullDomain + "/" + appName + "/" + streamName + "?auth_key=" + Long.toString(timeStamp) + "-0-0-" + rtsAuthKey;
        }
        HashMap<String, String> url = new HashMap<>();
        url.put("rtmpUrl", rtmpUrl);
        url.put("hlsUrl", hlsUrl);
        url.put("flvUrl", flvUrl);
        url.put("rtsUrl", rtsUrl);

        return url;
    }

    /**
     * 计算md5
     */
    public static String md5(String param) {
        if (param == null || param.length() == 0) {
            return null;
        }
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            md5.update(param.getBytes());
            byte[] byteArray = md5.digest();

            BigInteger bigInt = new BigInteger(1, byteArray);
            // 参数16表示16进制
            String result = bigInt.toString(16);
            // 不足32位高位补零
            while (result.length() < 32) {
                result = "0" + result;
            }
            return result;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 登录需的要鉴权信息
     */
    public static HashMap<String, Object> appAuth(LiveRooms room) {
        String role = "";
        User user = SecurityUtils.getLoginUser().getUser();
        String userId = user.getUserId().toString();
        String appId = room.getAppId();
        String appKey = room.getAppKey();
        String appSign = room.getAppSign();

        String nonce = java.util.UUID.randomUUID().toString();
        Long timestamp = DateUtils.addHours(new Date(), 1).getTime() / 1000;

        String signContent = String.format("%s%s%s%s%s%s", appId, appKey, userId, nonce, timestamp, role);
        String appToken = org.apache.commons.codec.digest.DigestUtils.sha256Hex(signContent);

        HashMap<String, Object> result = new HashMap<>();
        result.put("appId", appId);
        result.put("appSign", appSign);
        result.put("appToken", appToken);
        result.put("role", role);
        result.put("nonce", nonce);
        result.put("userId", userId);
        result.put("timestamp", timestamp);
        result.put("userName", user.getUserName());

        return result;
    }
}

3、直播间互动功能(消息组)

java 复制代码
package com.zaiyun.zhibo.controller;

import com.zaiyun.common.annotation.Anonymous;
import com.zaiyun.common.core.controller.BaseController;
import com.zaiyun.common.core.domain.AjaxResult;
import com.zaiyun.zhibo.domain.LiveRooms;
import com.zaiyun.zhibo.mapper.LiveRoomsMapper;
import com.zaiyun.zhibo.utils.LiveAppUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.HashMap;

/**
 * 最新版本的消息组
 */
@Anonymous
@RestController
@RequestMapping("/live/app")
public class LiveAppController extends BaseController {
    @Resource
    LiveAppUtils liveAppUtils;
    @Resource
    LiveRoomsMapper liveRoomsMapper;

    /**
     * 创建互动消息应用
     */
    @PostMapping("/create")
    public AjaxResult createMessageApp() {
        try {
            String appName = "myApp";
            return success(liveAppUtils.createMessageApp(appName));
        } catch (Exception e) {
            return AjaxResult.error(201, e.getMessage());
        }
    }

    /**
     * 获取互动消息应用
     */
    @PostMapping("/list")
    public AjaxResult getMessageAppList() {
        try {
            return success(liveAppUtils.getMessageAppList());
        } catch (Exception e) {
            return AjaxResult.error(201, e.getMessage());
        }
    }

    /**
     * 获取互动消息应用详情
     */
    @PostMapping("/info")
    public AjaxResult getMessageAppInfo() {
        try {
            String appId = "abc13a82b773";
            return success(liveAppUtils.getMessageAppInfo(appId));
        } catch (Exception e) {
            return AjaxResult.error(201, e.getMessage());
        }
    }

    /**
     * 创建消息组
     */
    @PostMapping("/group/create")
    public AjaxResult createMessageGroup() {
        try {
            String appId = "abc13a82b773";
            return success(liveAppUtils.createMessageGroup(appId));
        } catch (Exception e) {
            return AjaxResult.error(201, e.getMessage());
        }
    }

    /**
     * 查询指定用户下消息组列表
     */
    @PostMapping("/group/list")
    public AjaxResult listMessageGroup() {
        try {
            String appId = "abc13a82b773";
            return success(liveAppUtils.listMessageGroup(appId));
        } catch (Exception e) {
            return AjaxResult.error(201, e.getMessage());
        }
    }

    /**
     * 消息组详情
     */
    @PostMapping("/group/describe")
    public AjaxResult groupDescribe() {
        try {
            HashMap<String, String> parameter = new HashMap<>();
            parameter.put("appId", "abc13a82b773");
            parameter.put("groupId", "211a39c8-2ebd-4d4b-978e-dfa31836220f");

            return success(liveAppUtils.groupDescribe(parameter));
        } catch (Exception e) {
            return AjaxResult.error(201, e.getMessage());
        }
    }

    /**
     * 发送消息到群组
     */
    @PostMapping("/send/group")
    public AjaxResult sendMessageGroup(@RequestBody HashMap<String, String> data) {
        try {
            String roomId = data.get("roomId");
            String msgType = data.get("msgType");
            String body = data.get("body");
            if (roomId == null || msgType == null || body == null) {
                return AjaxResult.error(201, "参数错误 roomId 或 msgType 或 body");
            }
            LiveRooms liveRooms = new LiveRooms();
            liveRooms.setId(Integer.parseInt(roomId));
            LiveRooms room = liveRoomsMapper.findRoomByWhere(liveRooms);
            HashMap<String, String> parameter = new HashMap<>();
            parameter.put("appId", room.getAppId());
            parameter.put("groupId", room.getGroupId());
            parameter.put("senderId", "admin" + getUserId());//发送者
            parameter.put("msgType", msgType);//消息类型
            parameter.put("body", body);//消息内容

            return success(liveAppUtils.sendMessageGroup(parameter));
        } catch (Exception e) {
            return AjaxResult.error(201, e.getMessage());
        }
    }

    /**
     * 发送消息到用户
     */
    @PostMapping("/send/user")
    public AjaxResult sendMessageUser() {
        try {
            HashMap<String, String> parameter = new HashMap<>();
            parameter.put("appId", "abc13a82b773");
            parameter.put("senderId", "uid10");//发送者
            parameter.put("receiverId", "100");//接收者
            parameter.put("body", "{\"content\":\"这里是发送的消息内容!\"}");//消息内容

            return success(liveAppUtils.sendMessageUser(parameter));
        } catch (Exception e) {
            return AjaxResult.error(201, e.getMessage());
        }
    }

    /**
     * 查询群组消息列表
     */
    @PostMapping("/group/messages")
    public AjaxResult getGroupMessages() {
        try {
            HashMap<String, String> parameter = new HashMap<>();
            parameter.put("appId", "abc13a82b773");
            parameter.put("groupId", "211a39c8-2ebd-4d4b-978e-dfa31836220f");

            return success(liveAppUtils.getGroupMessages(parameter));
        } catch (Exception e) {
            return AjaxResult.error(201, e.getMessage());
        }
    }

    /**
     * 查询群组用户列表
     */
    @PostMapping("/group/users")
    public AjaxResult getGroupUsers() {
        try {
            HashMap<String, String> parameter = new HashMap<>();
            parameter.put("appId", "abc13a82b773");
            parameter.put("groupId", "211a39c8-2ebd-4d4b-978e-dfa31836220f");

            return success(liveAppUtils.getGroupUsers(parameter));
        } catch (Exception e) {
            return AjaxResult.error(201, e.getMessage());
        }
    }
}
java 复制代码
package com.zaiyun.zhibo.utils;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.live.model.v20161101.*;
import com.aliyuncs.profile.DefaultProfile;
import com.zaiyun.common.config.AlibabaConfig;
import com.zaiyun.common.utils.uuid.UUID;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;

/**
 * 阿里视频直播工具类
 */
@Component
public class LiveAppUtils {
    /**
     * 初始化配置
     */
    public static IAcsClient createClient() throws Exception {
        DefaultProfile profile = DefaultProfile.getProfile("cn-shanghai", AlibabaConfig.getAccessKeyId(), AlibabaConfig.getAccessKeySecret());
        return new DefaultAcsClient(profile);
    }

    /**
     * 创建互动消息应用
     *
     * @param appName 互动消息应用名称,长度 2~16 个字符
     */
    public static CreateLiveMessageAppResponse createMessageApp(String appName) throws Exception {
        IAcsClient client = createClient();
        CreateLiveMessageAppRequest request = new CreateLiveMessageAppRequest();
        request.setAppName(appName);
        request.setAuditType(1);//内置安全审核
        try {
            return client.getAcsResponse(request);
        } catch (ClientException error) {
            throw new RuntimeException("创建互动消息应用异常!" + error);
        }
    }

    /**
     * 查询互动消息应用列表
     */
    public static Object getMessageAppList() throws Exception {
        IAcsClient client = createClient();
        ListLiveMessageAppsRequest request = new ListLiveMessageAppsRequest();
        request.setSortType(1);
        try {
            return client.getAcsResponse(request);
        } catch (ClientException error) {
            throw new RuntimeException("查询互动消息应用列表异常!" + error);
        }
    }

    /**
     * 查询互动消息应用详情
     */
    public static Object getMessageAppInfo(String appId) throws Exception {
        IAcsClient client = createClient();
        DescribeLiveMessageAppRequest request = new DescribeLiveMessageAppRequest();
        request.setAppId(appId);
        try {
            return client.getAcsResponse(request);
        } catch (ClientException error) {
            throw new RuntimeException("查询互动消息应用详情异常!" + error);
        }
    }

    /**
     * 创建消息组
     *
     * @param appId 互动消息应用ID
     */
    public static String createMessageGroup(String appId) throws Exception {
        IAcsClient client = createClient();
        CreateLiveMessageGroupRequest request = new CreateLiveMessageGroupRequest();
        request.setAppId(appId);
        request.setCreatorId("admin1");//群组创建者ID。
        request.setDataCenter("cn-shanghai");//数据中心
        request.setGroupInfo("testgroupinfo");//群组扩展信息,最大512字符。
        request.setGroupId(UUID.fastUUID().toString());//要创建的群组ID,由大小写字母、数字组成,最大64字符。
        request.setGroupName(RandomStringUtils.randomAlphanumeric(10));//群组名,最大64字符。

        ArrayList<String> administrators = new ArrayList<>();
        administrators.add("aaaaa");
        administrators.add("bbbbb");
        administrators.add("ccccc");
        request.setAdministrators(administrators);//管理员用户ID数组

        try {
            CreateLiveMessageGroupResponse response = client.getAcsResponse(request);
            return response.getGroupId();
        } catch (ClientException error) {
            throw new RuntimeException("创建消息组异常!" + error);
        }
    }

    /**
     * 查询指定用户下消息组列表
     *
     * @param appId 互动消息应用ID
     */
    public static Object listMessageGroup(String appId) throws Exception {
        IAcsClient client = createClient();
        ListLiveMessageGroupsRequest request = new ListLiveMessageGroupsRequest();
        request.setAppId(appId);
        request.setSortType(2);
        try {
            return client.getAcsResponse(request);
        } catch (ClientException error) {
            throw new RuntimeException("查询指定用户下消息组列表异常!" + error);
        }
    }

    /**
     * 消息组详情
     *
     * @param parameter 请求参数
     */
    public static Object groupDescribe(HashMap<String, String> parameter) throws Exception {
        IAcsClient client = createClient();
        DescribeLiveMessageGroupRequest request = new DescribeLiveMessageGroupRequest();
        request.setAppId(parameter.get("appId"));
        request.setGroupId(parameter.get("groupId"));
        try {
            return client.getAcsResponse(request);
        } catch (ClientException error) {
            throw new RuntimeException("查询指定用户下消息组列表异常!" + error);
        }
    }

    /**
     * 发送消息到群组
     *
     * @param parameter 请求参数
     */
    public static Object sendMessageGroup(HashMap<String, String> parameter) throws Exception {
        IAcsClient client = createClient();
        SendLiveMessageGroupRequest request = new SendLiveMessageGroupRequest();
        request.setAppId(parameter.get("appId"));
        request.setGroupId(parameter.get("groupId"));
        request.setSenderId(parameter.get("senderId"));//发送者
        request.setBody(parameter.get("body"));//消息内容
        request.setMsgType(Long.parseLong(parameter.get("msgType")));//消息类型
        try {
            return client.getAcsResponse(request);
        } catch (ClientException error) {
            throw new RuntimeException("发送消息到群组异常!" + error);
        }
    }

    /**
     * 发送消息到用户
     *
     * @param parameter 请求参数
     */
    public static Object sendMessageUser(HashMap<String, String> parameter) throws Exception {
        IAcsClient client = createClient();
        SendLiveMessageUserRequest request = new SendLiveMessageUserRequest();
        request.setAppId(parameter.get("appId"));
        request.setSenderId(parameter.get("senderId"));//发送者
        request.setReceiverId(parameter.get("receiverId"));//接收者
        request.setBody(parameter.get("body"));//消息内容
        try {
            return client.getAcsResponse(request);
        } catch (ClientException error) {
            throw new RuntimeException("发送消息到用户异常!" + error);
        }
    }

    /**
     * 查询群组消息列表
     *
     * @param parameter 请求参数
     */
    public static Object getGroupMessages(HashMap<String, String> parameter) throws Exception {
        IAcsClient client = createClient();
        ListLiveMessageGroupMessagesRequest request = new ListLiveMessageGroupMessagesRequest();
        request.setAppId(parameter.get("appId"));
        request.setGroupId(parameter.get("groupId"));
        request.setSortType(2);
        request.setPageSize(10);
        try {
            return client.getAcsResponse(request);
        } catch (ClientException error) {
            throw new RuntimeException("查询群组消息列表异常!" + error);
        }
    }

    /**
     * 查询群组用户列表
     *
     * @param parameter 必须参数
     */
    public static Object getGroupUsers(HashMap<String, String> parameter) throws Exception {
        IAcsClient client = createClient();
        ListLiveMessageGroupUsersRequest request = new ListLiveMessageGroupUsersRequest();
        request.setAppId(parameter.get("appId"));
        request.setGroupId(parameter.get("groupId"));
        request.setSortType(2);
        request.setPageSize(30);
        try {
            return client.getAcsResponse(request);
        } catch (ClientException error) {
            throw new RuntimeException("查询群组用户列表异常!" + error);
        }
    }
}

4、推流、断流回调

java 复制代码
	/**
     * 推流、断流回调地址
     */
    @GetMapping("/callback")
    public void callback(HttpServletRequest request) {
        try {
            //处理回调请求参数
            HashMap<String, Object> paramsMap = ConvertUtils.getRequestData(request);

           //开始推流
            if (paramsMap.get("action").equals("publish")) {
                tiktokLogger.info("开始推流:" + paramsMap);
                liveRoomsLogService.addRoomLog(paramsMap);
            }

            //推流中断
            if (paramsMap.get("action").equals("publish_done")) {
                tiktokLogger.info("推流中断:" + paramsMap);
                liveRoomsLogService.upRoomLog(paramsMap);
            }
        } catch (Exception e) {
            tiktokLogger.info("回调异常:" + e.getMessage());
        }
    }
    
    /**
     * 处理请求参数
     *
     * @param request 请求
     * @return 结果
     */
    public static HashMap<String, Object> getRequestData(HttpServletRequest request) {
        HashMap<String, Object> paramsMap = new HashMap<>(); //重新定义请求的参数
        Map<String, String[]> map = request.getParameterMap(); //请求中的map数组
        for (String key : map.keySet()) { //遍历数组
            String[] value = map.get(key);
            if (value.length == 1) {
                paramsMap.put(key, map.get(key)[0]);
            } else {
                paramsMap.put(key, value);
            }
        }
        return paramsMap;
    }

推流、断流日志

java 复制代码
09:44:32.770 [http-nio-8082-exec-13] INFO  extend-tiktok - [callback,44] - 开始推流:{app=zyt.***.com, node=117.49.93.167, appname=TtSCpj, width=1080, action=publish, id=D6v3Su5mMQ, time=1723599872, usrargs=vhost=zyb.***.com&auth_key=1723603295-0-0-487e7adb13e00bdda7e7c6cbd97f88f8&ali_publisher&ali_edge_node_ip=117.49.93.167&ali_node_via=live13.cn4435%2clive15.l2et135-3&ali_node_ip=10.120.24.162#26%2c118.178.204.227#6&alilive_streamidv2=live13.cn4435_2955_3699959155_1723599872186&alilive_clienthost=live15.l2et135-3&orig_tc_url=rtmp://zyt.***.com/TtSCpj, height=1920}
09:46:06.204 [http-nio-8082-exec-15] INFO  extend-tiktok - [callback,50] - 推流中断:{app=zyt.***.com, node=117.49.93.167, appname=TtSCpj, width=1080, action=publish_done, id=D6v3Su5mMQ, time=1723599966, usrargs=vhost=zyb.***.com&auth_key=1723603295-0-0-487e7adb13e00bdda7e7c6cbd97f88f8&ali_publisher_ip=&ali_edge_node_ip=117.49.93.167&ali_node_via=live13.cn4435%2clive15.l2et135-3&ali_node_ip=10.120.24.162#26%2c118.178.204.227#6&alilive_streamidv2=live13.cn4435_2955_3699959155_1723599872186&alilive_clienthost=live15.l2et135-3&orig_tc_url=rtmp://zyt.***.com/TtSCpj, height=1920}
09:46:25.407 [http-nio-8082-exec-64] INFO  extend-tiktok - [callback,44] - 开始推流:{app=zyt.***.com, node=117.49.93.167, appname=Srvv66, ip=, width=1080, action=publish, id=b974e1hqmy, time=1723599985, usrargs=vhost=zyb.***.com&auth_key=1723603558-0-0-c54c7bad6bde755300bac0efb5ae44b7&ali_publisher_ip=&ali_edge_node_ip=117.49.93.167&ali_node_via=live6.cn4435%2clive3.l2et135-3&ali_node_ip=10.120.24.217#26%2c118.178.204.215#6&alilive_streamidv2=live6.cn4435_3485_3698551537_1723599984805&alilive_clienthost=live3.l2et135-3&orig_tc_url=rtmp://zyt.***.com/Srvv66, height=1920}
09:53:58.001 [http-nio-8082-exec-53] INFO  extend-tiktok - [callback,50] - 推流中断:{app=zyt.***.com, node=117.49.93.167, appname=Srvv66, ip=, width=1080, action=publish_done, id=b974e1hqmy, time=1723600437, usrargs=vhost=zyb.***.com&auth_key=1723603558-0-0-c54c7bad6bde755300bac0efb5ae44b7&ali_publisher_ip=&ali_edge_node_ip=117.49.93.167&ali_node_via=live6.cn4435%2clive3.l2et135-3&ali_node_ip=10.120.24.217#26%2c118.178.204.215#6&alilive_streamidv2=live6.cn4435_3485_3698551537_1723599984805&alilive_clienthost=live3.l2et135-3&orig_tc_url=rtmp://zyt.***.com/Srvv66, height=1920}
11:01:52.914 [http-nio-8082-exec-18] INFO  extend-tiktok - [callback,44] - 开始推流:{app=zyt.***.com, node=58.222.29.233, appname=Srvv66, ip=, width=1080, action=publish, id=b974e1hqmy, time=1723604512, usrargs=vhost=zyb.***.com&auth_key=1723603558-0-0-c54c7bad6bde755300bac0efb5ae44b7&ali_publisher_ip=&ali_edge_node_ip=58.222.29.233&ali_node_via=live1.cn3421%2clive15.l2et135-3&ali_node_ip=10.120.25.6#26%2c118.178.204.227#6&alilive_streamidv2=live1.cn3421_76677_2481419939_1723604511502&alilive_clienthost=live15.l2et135-3&orig_tc_url=rtmp://zyt.***.com/Srvv66, height=1920}
11:14:48.320 [http-nio-8082-exec-65] INFO  extend-tiktok - [callback,50] - 推流中断:{app=zyt.***.com, node=58.222.29.233, appname=Srvv66, ip=, width=1080, action=publish_done, id=b974e1hqmy, time=1723605288, usrargs=vhost=zyb.***.com&auth_key=1723603558-0-0-c54c7bad6bde755300bac0efb5ae44b7&ali_publisher_ip=&ali_edge_node_ip=58.222.29.233&ali_node_via=live1.cn3421%2clive15.l2et135-3&ali_node_ip=10.120.25.6#26%2c118.178.204.227#6&alilive_streamidv2=live1.cn3421_76677_2481419939_1723604511502&alilive_clienthost=live15.l2et135-3&orig_tc_url=rtmp://zyt.***.com/Srvv66, height=1920}

直播记录

相关推荐
风_流沙2 分钟前
java 对ElasticSearch数据库操作封装工具类(对你是否适用嘞)
java·数据库·elasticsearch
ProtonBase31 分钟前
如何从 0 到 1 ,打造全新一代分布式数据架构
java·网络·数据库·数据仓库·分布式·云原生·架构
乐之者v37 分钟前
leetCode43.字符串相乘
java·数据结构·算法
suweijie7684 小时前
SpringCloudAlibaba | Sentinel从基础到进阶
java·大数据·sentinel
公贵买其鹿5 小时前
List深拷贝后,数据还是被串改
java
xlsw_8 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹9 小时前
基于java的改良版超级玛丽小游戏
java
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭9 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫9 小时前
泛型(2)
java
超爱吃士力架9 小时前
邀请逻辑
java·linux·后端