Selaa lähdekoodia

直播间创建直播连接,直播间进行数据连接,目前支持RTMP服务器和FLV格式播放

yuhongqi 3 päivää sitten
vanhempi
commit
d7db37186e

+ 14 - 1
fs-company/src/main/java/com/fs/company/controller/live/LiveController.java

@@ -3,6 +3,7 @@ package com.fs.company.controller.live;
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.R;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.poi.ExcelUtil;
@@ -19,7 +20,7 @@ import java.util.Map;
 
 /**
  * 直播Controller
- * 
+ *
  * @author fs
  * @date 2025-01-17
  */
@@ -88,6 +89,8 @@ public class LiveController extends BaseController
         return AjaxResult.success(liveService.selectLiveByLiveIdAndCompanyIdAndCompanyUserId(liveId, user.getCompanyId(), user.getUserId()));
     }
 
+
+
     /**
      * 新增直播
      */
@@ -123,6 +126,16 @@ public class LiveController extends BaseController
         return toAjax(liveService.deleteLiveByLiveIds(liveIds));
     }
 
+    @GetMapping("/living/{liveId}")
+    public R getRoom(@PathVariable String liveId) {
+        Map<String, Object> resultMap = liveService.getLiveRoom(liveId);
+        if ("200".equals(resultMap.get("code"))) {
+            return R.ok().put("livingUrl", resultMap.get("livingUrl"));
+        } else {
+            return R.error((String) resultMap.get("msg"));
+        }
+    }
+
     /**
      * 设置企业ID和企业用户ID
      * @param live 直播间

+ 26 - 3
fs-live-app/src/main/java/com/fs/app/controller/LiveController.java

@@ -17,9 +17,7 @@ import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiResponse;
 import lombok.AllArgsConstructor;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
@@ -27,6 +25,7 @@ import java.time.LocalDateTime;
 import java.time.temporal.ChronoUnit;
 import java.util.Comparator;
 import java.util.List;
+import java.util.Map;
 
 
 @Api("直播信息接口")
@@ -93,4 +92,28 @@ public class LiveController extends AppBaseController {
 		return R.ok().put("data", list);
 	}
 
+	@PostMapping("/create")
+	public R createRoom(@RequestBody Map<String, Object> payload) {
+		if (!payload.containsKey("liveId")) {
+			return R.error("直播间id缺失");
+		}
+		Long liveId = Long.valueOf(payload.get("liveId").toString());
+		Map<String, Object> resultMap = liveService.createLiveRoom(liveId);
+		if ("200".equals(resultMap.get("code"))) {
+			return R.ok();
+		} else {
+			return R.error(resultMap.get("msg").toString());
+		}
+	}
+
+	@GetMapping("/{liveId}")
+	public R getRoom(@PathVariable String liveId) {
+		Map<String, Object> resultMap = liveService.getLiveRoom(liveId);
+		if ("200".equals(resultMap.get("code"))) {
+			return R.ok(resultMap);
+		} else {
+			return R.error((String) resultMap.get("msg"));
+		}
+	}
+
 }

+ 2 - 1
fs-service/src/main/java/com/fs/live/domain/Live.java

@@ -97,6 +97,7 @@ public class Live extends BaseEntity {
     /** 直播地址 */
     @Excel(name = "直播地址")
     private String rtmpUrl;
+    private String flvHlsUrl;
 
     @TableField(exist = false)
     private String videoUrl;
@@ -107,5 +108,5 @@ public class Live extends BaseEntity {
     private String configJson;
 
     /** 直播审核状态,销售端修改后需要总后台审核 0未审核 1已审核*/
-    private String is_audit;
+    private Integer isAudit;
 }

+ 5 - 0
fs-service/src/main/java/com/fs/live/service/ILiveService.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import com.fs.live.domain.Live;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * 直播Service接口
@@ -83,4 +84,8 @@ public interface ILiveService extends IService<Live>
      * @return
      */
     List<Live> liveList();
+
+    Map<String, Object> createLiveRoom(Long liveId);
+
+    Map<String, Object> getLiveRoom(String streamKey);
 }

+ 69 - 0
fs-service/src/main/java/com/fs/live/service/impl/LiveServiceImpl.java

@@ -1,6 +1,8 @@
 package com.fs.live.service.impl;
 
+import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.core.domain.R;
 import com.fs.common.exception.base.BaseException;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.StringUtils;
@@ -11,11 +13,17 @@ import com.fs.live.mapper.LiveMapper;
 import com.fs.live.service.ILiveDataService;
 import com.fs.live.service.ILiveService;
 import com.fs.live.service.ILiveVideoService;
+import com.fs.system.domain.SysConfig;
+import com.fs.system.service.ISysConfigService;
+import com.qcloud.cos.utils.Md5Utils;
 import lombok.AllArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * 直播Service业务层处理
@@ -31,6 +39,9 @@ public class LiveServiceImpl extends ServiceImpl<LiveMapper, Live> implements IL
     private final ILiveVideoService liveVideoService;
     private final ILiveDataService liveDataService;
 
+    @Autowired
+    private ISysConfigService sysConfigService;
+
     /**
      * 查询直播
      *
@@ -166,4 +177,62 @@ public class LiveServiceImpl extends ServiceImpl<LiveMapper, Live> implements IL
     public List<Live> liveList() {
         return liveMapper.liveList();
     }
+
+    @Override
+    public Map<String, Object> createLiveRoom(Long liveId) {
+        Map<String, Object> resultMap = new HashMap<>();
+        Live live = this.selectLiveByLiveId(liveId);
+        if (live == null || live.getStatus() != 1 || live.getIsShow() != 1 || live.getIsAudit() != 1) {
+            resultMap.put("code", "500");
+            resultMap.put("msg", "您未拥有直播权限");
+            return resultMap;
+        }
+        SysConfig sysConfig = sysConfigService.selectConfigByConfigKey("living.config");
+        Map<String, String> livingConfigMap = JSON.parseObject(sysConfig.getConfigValue(), Map.class);
+        if (livingConfigMap == null || livingConfigMap.isEmpty()) {
+            resultMap.put("code", "500");
+            resultMap.put("msg", "缺失直播配置");
+            return Collections.emptyMap();
+        }
+        String rtmpPushUrl = generateRtmpPushUrl(livingConfigMap.get("domain"), livingConfigMap.get("app"), liveId.toString());
+        String flvPlayUrl = generateFlvPlayUrl(livingConfigMap.get("http"), livingConfigMap.get("app"), liveId.toString());
+        live.setRtmpUrl(rtmpPushUrl);
+        live.setFlvHlsUrl(flvPlayUrl);
+        this.updateLive(live);
+        resultMap.put("code", "200");
+        return resultMap;
+    }
+
+    @Override
+    public Map<String, Object> getLiveRoom(String liveId) {
+        Map<String, Object> resultMap = new HashMap<>();
+        Live live = this.selectLiveByLiveId(Long.valueOf(liveId));
+        if (live == null) {
+            resultMap.put("code", "500");
+            resultMap.put("msg", "未查询到直播间");
+            return resultMap;
+        }
+        resultMap.put("code", "200");
+        resultMap.put("livingUrl", live.getFlvHlsUrl());
+        return resultMap;
+    }
+
+
+
+    public static String generateRtmpPushUrl(String domain, String app, String liveId) {
+        long timestamp = System.currentTimeMillis() / 1000; // 秒级时间戳
+        String SECRET_KEY = liveId + timestamp;
+        String sign = Md5Utils.md5Hex(liveId + SECRET_KEY + timestamp);
+        return String.format("rtmp://%s/%s/%s?timestamp=%d&sign=%s", domain, app, liveId,timestamp,sign);
+    }
+
+    /**
+     * 生成 FLV 播放地址(用于前端播放)
+     */
+    public static String generateFlvPlayUrl(String domain, String app, String liveId) {
+        long timestamp = System.currentTimeMillis() / 1000;
+        String SECRET_KEY = liveId + timestamp;
+        String sign = Md5Utils.md5Hex(liveId + SECRET_KEY + timestamp);
+        return String.format("http://%s/%s/%s.flv?timestamp=%d&sign=%s", domain, app, liveId, timestamp, sign);
+    }
 }

+ 10 - 1
fs-service/src/main/resources/mapper/live/LiveMapper.xml

@@ -29,10 +29,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="updateTime"    column="update_time"    />
         <result property="remark"    column="remark"    />
         <result property="configJson"    column="config_json"    />
+        <result property="isAudit"    column="is_audit"    />
     </resultMap>
 
     <sql id="selectLiveVo">
-        select live_id, company_id, company_user_id,talent_id, live_name, live_desc, show_type, status, anchor_id, live_type, start_time, finish_time, live_img_url, live_config, is_show, is_del, qw_qr_code, rtmp_url, create_time, create_by, update_by, update_time, remark,config_json from live
+        select live_id, company_id, company_user_id,talent_id, live_name, is_audit, live_desc, show_type, status, anchor_id, live_type, start_time, finish_time, live_img_url, live_config, is_show, is_del, qw_qr_code, rtmp_url, flv_hls_url, create_time, create_by, update_by, update_time, remark,config_json from live
     </sql>
 
     <select id="selectLiveList" parameterType="Live" resultMap="LiveResult">
@@ -55,6 +56,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="isDel != null "> and is_del = #{isDel}</if>
             <if test="qwQrCode != null  and qwQrCode != ''"> and qw_qr_code = #{qwQrCode}</if>
             <if test="rtmpUrl != null  and rtmpUrl != ''"> and rtmp_url = #{rtmpUrl}</if>
+            <if test="flvHlsUrl != null  and flvHlsUrl != ''"> and flv_hls_url = #{flvHlsUrl}</if>
+            <if test="isAudit != null  and isAudit != ''"> and is_audit = #{isAudit}</if>
         </where>
     </select>
 
@@ -107,6 +110,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="updateTime != null">update_time,</if>
             <if test="remark != null">remark,</if>
             <if test="configJson != null">config_json,</if>
+            <if test="flvHlsUrl != null">flv_hls_url,</if>
+            <if test="isAudit != null">is_audit,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="companyId != null">#{companyId},</if>
@@ -132,6 +137,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="updateTime != null">#{updateTime},</if>
             <if test="remark != null">#{remark},</if>
             <if test="configJson != null">#{configJson},</if>
+            <if test="flvHlsUrl != null">#{flvHlsUrl},</if>
+            <if test="isAudit != null">#{isAudit},</if>
          </trim>
     </insert>
 
@@ -159,6 +166,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="updateTime != null">update_time = #{updateTime},</if>
             <if test="remark != null">remark = #{remark},</if>
             <if test="configJson != null">config_json = #{configJson},</if>
+            <if test="flvHlsUrl != null">flv_hls_url = #{flvHlsUrl},</if>
+            <if test="isAudit != null">is_audit = #{isAudit},</if>
         </trim>
         where live_id = #{liveId}
     </update>