This commit is contained in:
zlzw 2024-11-01 18:21:57 +08:00
parent d7cf86507a
commit 579fd2eaf6
17 changed files with 650 additions and 500 deletions

View File

@ -1,65 +1,177 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="zh-CN"> <html lang="zh-CN">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <title>基础菜单 - Layui</title>
<title>用户中心</title> <meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/layui/css/layui.css"> <link rel="stylesheet" href="/layui/css/layui.css">
</head> </head>
<body> <body class="layui-bg-gray">
<div id="header"></div> <div id="header"></div>
<body> <div class="layui-panel" style="width: 260px; margin: 16px;">
<div id="view"></div> <ul class="layui-menu" id="demo-menu">
<li lay-options="{id: 100}">
<div class="layui-menu-body-title"><a href="javascript:;">menu item 1</a></div>
</li>
<li lay-options="{id: 101}">
<div class="layui-menu-body-title">
<a href="javascript:;">menu item 2 <span class="layui-badge-dot"></span></a>
</body> </div>
<script id="demo" type="text/html"> </li>
<h3>{{ d.title }}</h3> <li class="layui-menu-item-divider"></li>
<ul> <li class="layui-menu-item-group layui-menu-item-down" lay-options="{type: 'group'}">
{{# layui.each(d.list, function(index, item){ }} <div class="layui-menu-body-title">
<li> menu group <i class="layui-icon layui-icon-up"></i>
<span>{{ item.modname }}</span> </div>
<span>{{ item.alias }}</span> <ul>
<span>{{ item.site || '' }}</span> <li lay-options="{id: 103}">
<div class="layui-menu-body-title">menu item 3-1</div>
</li>
<li class="layui-menu-item-group" lay-options="{type: 'group', isAllowSpread: false}">
<div class="layui-menu-body-title">menu group 2</div>
<ul>
<li class="layui-menu-item-checked">
<div class="layui-menu-body-title">menu item 3-2-1</div>
</li>
<li>
<div class="layui-menu-body-title">menu item 3-2-2</div>
</li> </li>
{{# }); }}
{{# if(d.list.length === 0){ }}
无数据
{{# } }}
</ul> </ul>
</li>
<li>
<div class="layui-menu-body-title">menu item 3-3</div>
</li>
</ul>
</li>
<li class="layui-menu-item-divider"></li>
<li>
<div class="layui-menu-body-title">menu item 4 <span class="layui-badge">1</span></div>
</li>
<li>
<div class="layui-menu-body-title">menu item 5</div>
</li>
<li>
<div class="layui-menu-body-title">menu item 6</div>
</li>
<li class="layui-menu-item-parent" lay-options="{type: 'parent'}">
<div class="layui-menu-body-title">
menu item 7 Children
<i class="layui-icon layui-icon-right"></i>
</div>
<div class="layui-panel layui-menu-body-panel">
<ul>
<li class="layui-menu-item-parent" lay-options="{type: 'parent'}">
<div class="layui-menu-body-title">
menu item 7-1
<i class="layui-icon layui-icon-right"></i>
</div>
<div class="layui-panel layui-menu-body-panel">
<ul>
<li>
<div class="layui-menu-body-title">menu item 7-2-1</div>
</li>
<li>
<div class="layui-menu-body-title">menu item 7-2-2</div>
</li>
<li>
<div class="layui-menu-body-title">menu item 7-2-3</div>
</li>
<li>
<div class="layui-menu-body-title">menu item 7-2-4</div>
</li>
</ul>
</div>
</li>
<li>
<div class="layui-menu-body-title">menu item 7-2</div>
</li>
<li>
<div class="layui-menu-body-title">menu item 7-3</div>
</li>
</ul>
</div>
</li>
<li>menu item 8</li>
<li class="layui-menu-item-divider"></li>
<li class="layui-menu-item-group" lay-options="{type: 'group', isAllowSpread: false}">
<div class="layui-menu-body-title">menu group 9</div>
<ul>
<li>
<div class="layui-menu-body-title">menu item 9-1</div>
</li>
<li class="layui-menu-item-parent" lay-options="{type: 'parent'}">
<div class="layui-menu-body-title">
menu item 9-2
<i class="layui-icon layui-icon-right"></i>
</div>
<div class="layui-panel layui-menu-body-panel">
<ul>
<li>
<div class="layui-menu-body-title">menu item 9-2-1</div>
</li>
<li>
<div class="layui-menu-body-title">menu item 9-2-2</div>
</li>
<li>
<div class="layui-menu-body-title">menu item 9-2-3</div>
</li>
</ul>
</div>
</li>
<li>
<div class="layui-menu-body-title">menu item 9-31</div>
</li>
</ul>
</li>
<li class="layui-menu-item-divider"></li>
<li>
<div class="layui-menu-body-title">menu item 10</div>
</li>
</ul>
</div>
<script src="/js/jquery-3.2.1.js"></script>
<script src="/js/CommonConfig.js"></script>
<script>
headerModel = 4;
$('#header').load("/html/header.html");
</script>
<script src="/layui/layui.js"></script>
<script>
// loadHeader($('#header').get(0))
layui.use(function () {
var dropdown = layui.dropdown;
var layer = layui.layer;
var util = layui.util;
// 菜单点击事件
dropdown.on('click(demo-menu)', function (options) {
console.log(this, options);
// 显示 - 仅用于演示
layer.msg(util.escape(JSON.stringify(options)));
});
});
</script> </script>
<script src="/layui/layui.js"></script> <style>
<script src="/js/jquery-3.2.1.js"></script>
<script src="/js/CommonConfig.js"></script>
<script>
headerModel=4;
$('#header').load("/html/header.html");
layui.use(['form', 'laytpl'], function () { </style>
var form = layui.form;
var layer = layui.layer;
var laytpl = layui.laytpl
var data = { //数据
"title":"Layui常用模块"
,"list":[{"modname":"弹层","alias":"layer","site":"layer.layui99.com"},{"modname":"表单","alias":"form"}]
}
var getTpl = $("#demo").get(0).innerHTML
,view = document.getElementById('view');
laytpl(getTpl).render(data, function(html){
view.innerHTML = html;
console.log(html)
});
})
</script> </body>
<style>
</style>
</html> </html>

View File

@ -1,5 +1,6 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="zh-CN"> <html lang="zh-CN">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
@ -7,54 +8,84 @@
<link rel="stylesheet" href="/layui/css/layui.css"> <link rel="stylesheet" href="/layui/css/layui.css">
</head> </head>
<body> <body class="layui-bg-gray">
<div id="header"></div> <div id="header"></div>
<body> <div class="layui-panel" style="width: 260px; margin: 16px;">
<div id="view"></div> <ul class="layui-menu" id="menusss">
<!-- <div id="menuView"></div> -->
<li class="layui-menu-item-group layui-menu-item-down" lay-options="{type: 'group'}">
<div class="layui-menu-body-title">
menu group <i class="layui-icon layui-icon-up"></i>
</div>
<ul>
<li lay-options="{id: 103}">
<div class="layui-menu-body-title">menu item 3-1</div>
</li>
<li lay-options="{id: 102}">
<div class="layui-menu-body-title">menu item 3-2</div>
</li>
</ul>
</li>
</ul>
</div>
</body> </body>
<script id="demo" type="text/html"> <script id="menulist" type="text/html">
<h3>{{ d.title }}</h3> <ul class="layui-tab-title">
<ul> {{# layui.each(d.data, function(index, item){ }}
{{# layui.each(d.list, function(index, item){ }} <li lay-id="{{= item.live_room_id}}">{{= item.anchorName}}</li>
<li>
<span>{{ item.modname }}</span>
<span>{{ item.alias }}</span>
<span>{{ item.site || '' }}</span>
</li>
{{# }); }} {{# }); }}
{{# if(d.list.length === 0){ }} {{# if(d.data.length === 0){ }}
无数据 无数据
{{# } }} {{# } }}
</ul> </ul>
</script> </script>
<script src="/layui/layui.js"></script>
<script src="/js/jquery-3.2.1.js"></script> <script src="/js/jquery-3.2.1.js"></script>
<script src="/js/CommonConfig.js"></script> <script src="/js/CommonConfig.js"></script>
<script src="/js/httpUtils.js"></script>
<script src="/layui/layui.js"></script>
<script> <script>
headerModel=2; headerModel = 2;
$('#header').load("/html/header.html"); $('#header').load("/html/header.html");
</script>
layui.use(['form', 'laytpl'], function () {
var form = layui.form;
<script>
var roomId = '17961';
layui.use(['dropdown', 'laytpl'], function () {
var dropdown = layui.dropdown;
var layer = layui.layer; var layer = layui.layer;
var laytpl = layui.laytpl var laytpl = layui.laytpl;
var data = { //数据 function initTabs() {
"title":"Layui常用模块" getVideo(roomId, pageIndex, pageMax)
,"list":[{"modname":"弹层","alias":"layer","site":"layer.layui99.com"},{"modname":"表单","alias":"form"}] .then(data => {
initMenu(data)
})
} }
var getTpl = $("#demo").get(0).innerHTML dropdown.on('click(menusss)', function (options) {
,view = document.getElementById('view'); console.log(this, options);
laytpl(getTpl).render(data, function(html){
view.innerHTML = html;
console.log(html)
}); });
function initMenu(data) {
var view = $("#menuView").get(0);
laytpl($('#menulist').get(0).innerHTML).render(data, function (html) {
view.innerHTML = html;
layer.close(loadIndex)
});
}
function init() {
// initTabs()
}
init()
}) })
</script> </script>
@ -62,4 +93,5 @@
<style> <style>
</style> </style>
</html> </html>

View File

@ -7,7 +7,7 @@
<li class="layui-nav-item user"><a href="/html/body/user.html">用户中心</a></li> <li class="layui-nav-item user"><a href="/html/body/user.html">用户中心</a></li>
</ul> </ul>
</body> </body>
<script src="/layui/layui.js"></script> <!-- <script src="/layui/layui.js"></script> -->
<script> <script>
$(".index").removeClass("layui-this") $(".index").removeClass("layui-this")

View File

@ -47,7 +47,7 @@
<input type="text" name="recordDanmuDate" id="recordDanmuDate" value="00:00:00 - 23:59:59" <input type="text" name="recordDanmuDate" id="recordDanmuDate" value="00:00:00 - 23:59:59"
lay-verify="required" autocomplete="off" class="layui-input"> lay-verify="required" autocomplete="off" class="layui-input">
</div> </div>
<div class="layui-form-mid layui-text-em" onclick="timeTips(this)"><i <div class="layui-form-mid layui-text-em" onclick="timeTips(false,this)"><i
class="layui-icon layui-icon-help"></i> </div> class="layui-icon layui-icon-help"></i> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
@ -56,7 +56,7 @@
<input type="text" name="recordLiveDate" id="recordLiveDate" value="00:00:00 - 23:59:59" <input type="text" name="recordLiveDate" id="recordLiveDate" value="00:00:00 - 23:59:59"
lay-verify="required" autocomplete="off" class="layui-input"> lay-verify="required" autocomplete="off" class="layui-input">
</div> </div>
<div class="layui-form-mid layui-text-em" onclick="timeTips(this)"><i <div class="layui-form-mid layui-text-em" onclick="timeTips(true,this)"><i
class="layui-icon layui-icon-help"></i> </div> class="layui-icon layui-icon-help"></i> </div>
</div> </div>
<div class="layui-inline"> <div class="layui-inline">
@ -89,8 +89,13 @@
<script src="/js/httpUtils.js"></script> <script src="/js/httpUtils.js"></script>
<script src="/js/CommonConfig.js"></script> <script src="/js/CommonConfig.js"></script>
<script> <script>
function timeTips(that) { function timeTips(isLive,that) {
if(isLive){
layer.tips('是从开始到结束时间范围内,主播开播会启动录制,超过结束范围不会中断正在录制的任务', that); layer.tips('是从开始到结束时间范围内,主播开播会启动录制,超过结束范围不会中断正在录制的任务', that);
}else{
layer.tips('仅在当前时间范围内录制,如遇到正在直播,则延迟到下播时停止录制', that);
}
} }
var roomId = getParam("roomId"); var roomId = getParam("roomId");

View File

@ -21,7 +21,7 @@
{{# layui.each(d.data, function(index, item){ }} {{# layui.each(d.data, function(index, item){ }}
<div class="layui-col-xs3 layui-col-sm3 layui-col-md3"> <div class="layui-col-xs3 layui-col-sm3 layui-col-md3">
<div class="layui-bg-gray" style="padding: 16px;"> <div class="layui-bg-gray" style="padding: 16px;">
<div class="layui-row layui-col-space15"> <div class="layui-row layui-col-space16">
<div class="layui-card"> <div class="layui-card">
<div class="layui-card-header" ><img src="#" onerror="showImage('{{= item.anchorFace}}',this)" style="width: 40px; height: 40px;"/> {{= item.anchorName}} <div class="layui-card-header" ><img src="#" onerror="showImage('{{= item.anchorFace}}',this)" style="width: 40px; height: 40px;"/> {{= item.anchorName}}
<span style="float: right;">直播状态: <span style="float: right;">直播状态:

View File

@ -121,15 +121,21 @@ function deleteRoomConfig(roomId){
function getAllLive(page,limit){ function getAllLive(page,limit){
return get("/live/list?page="+page+"&limit="+limit) return get("/live/list?page="+page+"&limit="+limit)
} }
function getAllConfig(page,limit){
return get("/live/config/all?page="+page+"&limit="+limit)
}
//----------------首页相关接口end //----------------首页相关接口end
//----------------视频相关接口 //----------------直播视频相关接口
function startLiveVideo(roomId){ function startLiveVideo(roomId){
return get("/live/video/start?roomId="+roomId) return get("/live/video/start?roomId="+roomId)
} }
function stopLiveVideo(roomId){ function stopLiveVideo(roomId){
return get("/live/video/stop?roomId="+roomId) return get("/live/video/stop?roomId="+roomId)
} }
//----------------视频相关接口end function getVideo(roomId,page,limit){
return get("/file/list?roomId="+roomId+"&page="+page+"&limit="+limit)
}
//----------------直播视频相关接口end
//----------------弹幕相关接口 //----------------弹幕相关接口
function startLiveDanmu(roomId){ function startLiveDanmu(roomId){
return get("/live/danmu/start?roomId="+roomId) return get("/live/danmu/start?roomId="+roomId)

View File

@ -81,7 +81,12 @@ public class LiveConfigController {
@RequestMapping(value = "all", method = RequestMethod.GET) @RequestMapping(value = "all", method = RequestMethod.GET)
@ResponseBody @ResponseBody
public JSONObject getAllConfig(int page,int limit) { public JSONObject getAllConfig(int page,int limit) {
List<LiveConfigDatabaseBean> config = configService.getConfigs(page, limit); List<LiveConfigDatabaseBean> config ;
if(page==-1||limit==-1) {
config=configService.getAllConfig();
}else{
config=configService.getConfigs(page, limit);
}
if (config != null) { if (config != null) {
return ResultData.success(config,configService.getConfigCount()); return ResultData.success(config,configService.getConfigCount());
} }

View File

@ -2,22 +2,18 @@ package com.yutou.bilibili.Controllers;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.yutou.bilibili.datas.ResultData; import com.yutou.bilibili.datas.ResultData;
import com.yutou.bilibili.datas.VideoFilePath;
import com.yutou.bilibili.services.LiveDanmuService; import com.yutou.bilibili.services.LiveDanmuService;
import com.yutou.bilibili.services.LiveService; import com.yutou.bilibili.services.LiveService;
import com.yutou.bilibili.services.LiveVideoService; import com.yutou.bilibili.services.LiveVideoDownloadService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.val;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
@Controller @Controller
public class LiveController { public class LiveController {
@Resource @Resource
LiveVideoService videoService; LiveVideoDownloadService videoService;
@Resource @Resource
LiveDanmuService danmuService; LiveDanmuService danmuService;
@Resource @Resource

View File

@ -1,13 +1,11 @@
package com.yutou.bilibili.Controllers; package com.yutou.bilibili.Controllers;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.yutou.biliapi.bean.live.database.LiveConfigDatabaseBean; import com.yutou.biliapi.bean.live.database.LiveConfigDatabaseBean;
import com.yutou.biliapi.databases.BiliLiveConfigDatabase; import com.yutou.biliapi.databases.BiliLiveConfigDatabase;
import com.yutou.biliapi.net.WebSocketManager;
import com.yutou.bilibili.datas.ResultData; import com.yutou.bilibili.datas.ResultData;
import com.yutou.bilibili.datas.ReturnCode; import com.yutou.bilibili.datas.ReturnCode;
import com.yutou.bilibili.services.LiveVideoService; import com.yutou.bilibili.services.LiveVideoDownloadService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@ -18,7 +16,7 @@ import java.util.List;
@Controller @Controller
public class LiveVideoController { public class LiveVideoController {
@Resource @Resource
LiveVideoService videoService; LiveVideoDownloadService videoService;
@RequestMapping("/live/video/list") @RequestMapping("/live/video/list")
@ResponseBody @ResponseBody

View File

@ -5,17 +5,14 @@ import com.yutou.bilibili.Tools.FileServerUtils;
import com.yutou.bilibili.Tools.Tools; import com.yutou.bilibili.Tools.Tools;
import com.yutou.bilibili.datas.ResultData; import com.yutou.bilibili.datas.ResultData;
import com.yutou.bilibili.datas.VideoFilePath; import com.yutou.bilibili.datas.VideoFilePath;
import com.yutou.bilibili.services.LiveVideoService; import com.yutou.bilibili.services.LiveVideoDownloadService;
import com.yutou.common.okhttp.HttpDownloadUtils; import com.yutou.common.okhttp.HttpDownloadUtils;
import com.yutou.common.utils.AppTools; import com.yutou.common.utils.AppTools;
import com.yutou.common.utils.Base64Tools;
import com.yutou.common.utils.Log; import com.yutou.common.utils.Log;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.val;
import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.FileSystemResource;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@ -34,16 +31,16 @@ import java.util.List;
@Controller @Controller
public class VideoFileController { public class VideoFileController {
@Resource @Resource
LiveVideoService videoService; LiveVideoDownloadService videoService;
@ResponseBody @ResponseBody
@RequestMapping("/file/list") @RequestMapping("/file/list")
public JSONObject getFileList(String roomId) { public JSONObject getFileList(int page,int limit,String roomId) {
List<VideoFilePath> list; List<VideoFilePath> list;
if (StringUtils.hasText(roomId)) { if (StringUtils.hasText(roomId)) {
list = videoService.getVideoPath(roomId); list = videoService.getVideoPath(roomId);
} else { } else {
list = videoService.getAllVideoPath(); list = videoService.getAllVideoPath(page,limit);
} }
return ResultData.success(list); return ResultData.success(list);
} }

View File

@ -1,21 +1,19 @@
package com.yutou.bilibili.Tools; package com.yutou.bilibili.Tools;
import com.yutou.bilibili.services.LiveVideoService; import com.yutou.bilibili.services.LiveVideoDownloadService;
import com.yutou.bilibili.services.SystemService; import com.yutou.bilibili.services.SystemService;
import com.yutou.common.utils.FFmpegUtils;
import com.yutou.common.utils.Log; import com.yutou.common.utils.Log;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.context.ApplicationListener; import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent; import org.springframework.context.event.ContextClosedEvent;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@Component @Component
public class ApplicationClose implements ApplicationListener<ContextClosedEvent> { public class ApplicationClose implements ApplicationListener<ContextClosedEvent> {
@Resource @Resource
SystemService systemConfigService; SystemService systemConfigService;
@Resource @Resource
LiveVideoService videoService; LiveVideoDownloadService videoService;
@Override @Override
public void onApplicationEvent(ContextClosedEvent contextClosedEvent) { public void onApplicationEvent(ContextClosedEvent contextClosedEvent) {
Log.i("服务结束"); Log.i("服务结束");

View File

@ -8,6 +8,7 @@ import java.util.List;
public class VideoFilePath { public class VideoFilePath {
private String name; private String name;
private String roomId; private String roomId;
private String uid;
private String path; private String path;
private String cover; private String cover;
private boolean isParent; private boolean isParent;

View File

@ -27,7 +27,7 @@ public class LiveConfigService {
if (!StringUtils.hasText(roomId)) { if (!StringUtils.hasText(roomId)) {
return null; return null;
} }
bean.setRoomId(new String(roomId)); bean.setRoomId(roomId);
try { try {
LiveRoomInfo body = BiliLiveNetApiManager.getInstance().getApi(null).getRoomInfo(String.valueOf(bean.getRoomId())).execute().body().getData(); LiveRoomInfo body = BiliLiveNetApiManager.getInstance().getApi(null).getRoomInfo(String.valueOf(bean.getRoomId())).execute().body().getData();
MasterInfoBean infoBean = BiliLiveNetApiManager.getInstance().getApi(null).getMasterInfo(String.valueOf(body.getUid())).execute().body().getData(); MasterInfoBean infoBean = BiliLiveNetApiManager.getInstance().getApi(null).getMasterInfo(String.valueOf(body.getUid())).execute().body().getData();

View File

@ -6,11 +6,8 @@ import com.yutou.biliapi.bean.live.database.LiveConfigDatabaseBean;
import com.yutou.biliapi.databases.BiliLiveConfigDatabase; import com.yutou.biliapi.databases.BiliLiveConfigDatabase;
import com.yutou.biliapi.net.BiliLiveNetApiManager; import com.yutou.biliapi.net.BiliLiveNetApiManager;
import com.yutou.bilibili.datas.web.LiveData; import com.yutou.bilibili.datas.web.LiveData;
import com.yutou.common.okhttp.HttpBody;
import com.yutou.common.utils.AppTools;
import com.yutou.common.utils.Log; import com.yutou.common.utils.Log;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.val;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.io.IOException; import java.io.IOException;
@ -22,7 +19,7 @@ import java.util.List;
public class LiveService { public class LiveService {
BiliLiveConfigDatabase liveConfigDatabase; BiliLiveConfigDatabase liveConfigDatabase;
@Resource @Resource
LiveVideoService videoService; LiveVideoDownloadService videoDownloadService;
@Resource @Resource
LiveDanmuService danmuService; LiveDanmuService danmuService;
LiveApi api; LiveApi api;
@ -43,7 +40,7 @@ public class LiveService {
liveData.setAnchorUid(config.getAnchorUid()); liveData.setAnchorUid(config.getAnchorUid());
liveData.setAnchorName(config.getAnchorName()); liveData.setAnchorName(config.getAnchorName());
liveData.setAnchorFace(config.getAnchorFace()); liveData.setAnchorFace(config.getAnchorFace());
liveData.setDownloadVideo(videoService.checkDownload(config.getRoomId())); liveData.setDownloadVideo(videoDownloadService.checkDownload(config.getRoomId()));
liveData.setDanmu(danmuService.check(config.getRoomId())); liveData.setDanmu(danmuService.check(config.getRoomId()));
try { try {
LiveRoomInfo body = api.getRoomInfo(config.getRoomId()).execute().body().getData(); LiveRoomInfo body = api.getRoomInfo(config.getRoomId()).execute().body().getData();

View File

@ -0,0 +1,369 @@
package com.yutou.bilibili.services;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.util.DateUtils;
import com.yutou.biliapi.api.LiveApi;
import com.yutou.biliapi.bean.live.LiveRoomConfig;
import com.yutou.biliapi.bean.live.LiveRoomInfo;
import com.yutou.biliapi.bean.live.LiveRoomPlayInfo;
import com.yutou.biliapi.bean.live.database.LiveConfigDatabaseBean;
import com.yutou.biliapi.bean.live.database.LiveVideoDatabaseBean;
import com.yutou.biliapi.bean.login.LoginCookieDatabaseBean;
import com.yutou.biliapi.databases.BiliBiliLoginDatabase;
import com.yutou.biliapi.databases.BiliLiveConfigDatabase;
import com.yutou.biliapi.databases.BiliLiveDatabase;
import com.yutou.biliapi.enums.LiveProtocol;
import com.yutou.biliapi.enums.LiveVideoCodec;
import com.yutou.biliapi.enums.LiveVideoDefinition;
import com.yutou.biliapi.enums.LiveVideoFormat;
import com.yutou.biliapi.net.BiliLiveNetApiManager;
import com.yutou.bilibili.Tools.DateFormatUtils;
import com.yutou.bilibili.Tools.FileServerUtils;
import com.yutou.bilibili.Tools.LiveInfoNfoTools;
import com.yutou.bilibili.datas.VideoFilePath;
import com.yutou.bilibili.interfaces.DownloadInterface;
import com.yutou.common.okhttp.HttpCallback;
import com.yutou.common.okhttp.HttpDownloadUtils;
import com.yutou.common.record.AbsVideoRecord;
import com.yutou.common.utils.ConfigTools;
import com.yutou.common.utils.FFmpegUtils;
import com.yutou.common.utils.Log;
import okhttp3.Headers;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.io.File;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import static com.alibaba.fastjson2.util.DateUtils.DateTimeFormatPattern.DATE_FORMAT_10_DASH;
@Service
public class LiveVideoDownloadService {
private final ThreadPoolExecutor executor;
private final List<String> userStopList = new ArrayList<>();//手动停止列表
private final AbsVideoRecord videoRecord;
public LiveVideoDownloadService() {
Log.i("初始化下载服务");
videoRecord = new FFmpegUtils();
executor = new ThreadPoolExecutor(2, 4, Long.MAX_VALUE, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100));
}
public boolean checkDownload(String roomId) {
return videoRecord.check(roomId);
}
public void clearUserStopList() {
userStopList.clear();
}
public void start(LiveConfigDatabaseBean bean, boolean isUser) {
if (!isUser && userStopList.contains(bean.getRoomId().toString())) {
return;
}
if (isUser) {
userStopList.remove(bean.getRoomId().toString());
}
if (videoRecord.check(bean.getRoomId().toString())) {
return;
}
BiliLiveNetApiManager.getInstance().getApi(bean.getRecordUid()).getRoomInfo(bean.getRoomId().toString()).enqueue(new HttpCallback<LiveRoomInfo>() {
@Override
public void onResponse(Headers headers, int code, String status, LiveRoomInfo response, String rawResponse) {
if (response.getLiveStatus() == 1) {
VideoTask task = new VideoTask(bean, response);
executor.execute(task);
} else {
Log.i("移除下载");
}
}
@Override
public void onFailure(Throwable throwable) {
Log.i("移除下载");
}
});
}
public void stop(String roomId, boolean isUser) {
if (isUser) {
userStopList.add(roomId);
}
videoRecord.kill(roomId);
}
public JSONArray getDownloadTasks() {
JSONArray array = new JSONArray();
array.addAll(videoRecord.getRoomIds());
return array;
}
public void stopAll() {
videoRecord.killAll();
}
private class VideoTask implements Runnable {
LiveConfigDatabaseBean bean;
boolean isDownload = true;
LiveApi api;
String savePath;
File rootPath;
LiveConfigDatabaseBean config;
BiliLiveDatabase database;
LiveVideoDatabaseBean videoDatabaseBean;
LiveRoomInfo roomInfo;
public VideoTask(LiveConfigDatabaseBean bean, LiveRoomInfo roomInfo) {
this.bean = bean;
this.roomInfo = roomInfo;
api = BiliLiveNetApiManager.getInstance().getApi(bean.getRecordUid());
}
@Override
public void run() {
if (roomInfo.getLiveStatus() == 1) {
String time = DateUtils.format(new Date().getTime(), DATE_FORMAT_10_DASH);
rootPath = new File(bean.getRecordPath() + File.separator + bean.getAnchorName() + File.separator + time + File.separator + roomInfo.getTitle());
savePath = rootPath.getAbsolutePath() + File.separator + "[" +
DateUtils.format(new Date(),
"yyyy-MM-dd HH-mm-ss") + "]" + roomInfo.getTitle() + ".flv";
if (!rootPath.exists()) {
rootPath.mkdirs();
}
record(bean, roomInfo);
} else {
stop();
}
}
private void stop() {
videoRecord.kill(bean.getRoomId().toString());
api.getRoomInfo(config.getRoomId().toString()).enqueue(new HttpCallback<LiveRoomInfo>() {
@Override
public void onResponse(Headers headers, int code, String status, LiveRoomInfo response, String rawResponse) {
if (response.getLiveStatus() == 1) {
LiveVideoDownloadService.this.start(bean, false);
} else {
LiveVideoDownloadService.this.stop(bean.getRoomId().toString(), false);
}
}
@Override
public void onFailure(Throwable throwable) {
}
});
}
private void record(LiveConfigDatabaseBean bean, LiveRoomInfo roomInfo) {
this.config = bean;
isDownload = true;
LiveRoomConfig config = new LiveRoomConfig();
config.setLoginUid(bean.getRecordUid());
config.setRoomId(bean.getRoomId());
config.setAnchorName(bean.getAnchorName());
config.setLogin(StringUtils.hasText(bean.getRecordUid()));
config.setRoomInfo(roomInfo);
config.setRootPath(bean.getRecordPath());
database = new BiliLiveDatabase(config);
HttpDownloadUtils.download(new HttpDownloadUtils.Builder().setUrl(roomInfo.getKeyframe())
.setPath(rootPath.getAbsolutePath())
.setFileName("poster.jpg"));
LiveInfoNfoTools.saveLiveInfoNfo(roomInfo, rootPath.getAbsolutePath(), new File(savePath).getName().replace(".flv", ".nfo"));
saveLiveInfo(roomInfo);
api.getLiveRoomPlayInfo(
bean.getRoomId().toString(),
LiveProtocol.getAll(),
LiveVideoFormat.getAll(),
LiveVideoCodec.getAll(),
LiveVideoDefinition.ORIGINAL.getValue()).enqueue(new HttpCallback<LiveRoomPlayInfo>() {
@Override
public void onResponse(Headers headers, int code, String status, LiveRoomPlayInfo response, String rawResponse) {
LiveRoomPlayInfo.Codec codec = response.getPlayurlInfo().getPlayurl().getStream().get(0).getFormat().get(0).getCodec().get(0);
String url = codec.getUrlInfo().get(0).getHost() + codec.getBaseUrl() + codec.getUrlInfo().get(0).getExtra();
if (bean.getRecordLiveModel() == 1) {
javaRecord(url, response);
} else {
ffmpeg(url, response);
}
}
@Override
public void onFailure(Throwable throwable) {
Log.e(throwable);
}
});
}
private void javaRecord(String url, LiveRoomPlayInfo playInfo) {
HttpDownloadUtils.download(new HttpDownloadUtils.Builder()
.setUrl(url)
.setPath(savePath)
.setDownloadInterface(new DownloadInterface() {
@Override
public void onDownloadStart() {
super.onDownloadStart();
VideoTask.this.onStart();
}
@Override
public boolean onDownloading(double soFarBytes, double totalBytes) {
return isDownload;
}
@Override
public void onDownload(File file) {
super.onDownload(file);
stop();
}
@Override
public void onError(Exception e) {
super.onError(e);
stop();
}
}));
}
private void ffmpeg(String url, LiveRoomPlayInfo playInfo) {
String ffmpegPath = ConfigTools.load(ConfigTools.CONFIG, "ffmpeg", String.class);
String cookie = "";
LoginCookieDatabaseBean ck = BiliBiliLoginDatabase.getInstance().getCookie(config.getRecordUid());
if (ck != null) {
cookie = ck.toCookieString();
}
FFmpegUtils.Builder builder = new FFmpegUtils.Builder()
.withParam("-user_agent", ConfigTools.getUserAgent())
.withParam("-headers", "Referer: https://live.bilibili.com")
// .withNotSymbolParam("-progress", "-")
.withNotSymbolParam("-threads", "8")
.withNotSymbolParam("-c:v", "copy")
.withNotSymbolParam("-y", "");
if (ck != null) {
builder = builder.withParam("-cookies", cookie);
}
FFmpegUtils command = builder.build(config.getRoomId(), ffmpegPath, url, savePath);
Log.i(command.getCommand());
try {
command.start(new DownloadInterface() {
@Override
public void onDownloadStart() {
super.onDownloadStart();
VideoTask.this.onStart();
}
@Override
public boolean onDownloading(double soFarBytes, double totalBytes) {
if (!isDownload) {
command.stop();
}
return super.onDownloading(soFarBytes, totalBytes);
}
@Override
public void onDownload(File file) {
super.onDownload(file);
Log.e("下载完成 ");
stop();
}
});
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private void onStart() {
videoDatabaseBean = new LiveVideoDatabaseBean();
videoDatabaseBean.setPath(savePath);
videoDatabaseBean.setRoomInfoJson(JSONObject.toJSONString(roomInfo));
videoDatabaseBean.setStartTime(new Date());
database.addLiveInfo(videoDatabaseBean);
}
}
private void saveLiveInfo(LiveRoomInfo roomInfo) {
}
public List<VideoFilePath> getAllVideoPath(int page, int limit) {
BiliLiveConfigDatabase configDatabase = new BiliLiveConfigDatabase();
List<LiveConfigDatabaseBean> list = configDatabase.getConfigs(page, limit);
configDatabase.close();
List<VideoFilePath> filePathList = new ArrayList<>();
for (LiveConfigDatabaseBean bean : list) {
filePathList.addAll(getVideoFilePath(bean));
}
return filePathList;
}
public List<VideoFilePath> getVideoPath(String roomId) {
BiliLiveConfigDatabase configDatabase = new BiliLiveConfigDatabase();
LiveConfigDatabaseBean bean = configDatabase.getConfig(roomId);
configDatabase.close();
return new ArrayList<>(getVideoFilePath(bean));
}
private List<VideoFilePath> getVideoFilePath(LiveConfigDatabaseBean configBean) {
List<VideoFilePath> filePathList = new ArrayList<>();
String recordPath = configBean.getRecordPath() + File.separator + configBean.getAnchorName();
File recordDir = new File(recordPath);
BiliLiveDatabase database = new BiliLiveDatabase(LiveRoomConfig.buildConfig(configBean.getRoomId()), recordDir.getAbsolutePath());
VideoFilePath path = createVideoRootFilePath(configBean, recordDir);
if (recordDir.exists()) {
List<LiveVideoDatabaseBean> infos = database.getLiveInfos();
database.close();
path.setChildren(getVideoInfo(infos));
}
filePathList.add(path);
return filePathList;
}
private VideoFilePath createVideoRootFilePath(LiveConfigDatabaseBean config, File db) {
VideoFilePath path = new VideoFilePath();
path.setRoomId(config.getRoomId());
path.setCover(config.getAnchorFace());
path.setName(config.getAnchorName());
path.setUid(config.getAnchorUid());
path.setParent(true);
path.setPath(FileServerUtils.toUrl(db.getParent()));
return path;
}
private List<VideoFilePath> getVideoInfo(List<LiveVideoDatabaseBean> videoList) {
List<VideoFilePath> filePathList = new ArrayList<>();
for (LiveVideoDatabaseBean bean : videoList) {
VideoFilePath path = new VideoFilePath();
LiveRoomInfo roomInfo = JSONObject.parseObject(bean.getRoomInfoJson(), LiveRoomInfo.class);
path.setRoomId(roomInfo.getRoomId());
path.setName(roomInfo.getTitle());
path.setUid(roomInfo.getUid());
path.setPath(DateFormatUtils.format(bean.getSql_time()));
path.setCover(roomInfo.getKeyframe());
path.setParent(false);
path.setChildren(null);
filePathList.add(path);
}
return filePathList;
}
public static void main(String[] args) {
LiveVideoDownloadService service = new LiveVideoDownloadService();
List<VideoFilePath> path = service.getAllVideoPath(1, 8);
Log.i("path.size() = " + path.size());
Log.i(JSONArray.toJSONString(path));
}
}

View File

@ -1,371 +1,8 @@
package com.yutou.bilibili.services; package com.yutou.bilibili.services;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.util.DateUtils;
import com.yutou.biliapi.api.LiveApi;
import com.yutou.biliapi.bean.live.LiveRoomConfig;
import com.yutou.biliapi.bean.live.LiveRoomInfo;
import com.yutou.biliapi.bean.live.LiveRoomPlayInfo;
import com.yutou.biliapi.bean.live.database.LiveConfigDatabaseBean;
import com.yutou.biliapi.bean.live.database.LiveVideoDatabaseBean;
import com.yutou.biliapi.bean.login.LoginCookieDatabaseBean;
import com.yutou.biliapi.databases.BiliBiliLoginDatabase;
import com.yutou.biliapi.databases.BiliLiveConfigDatabase;
import com.yutou.biliapi.databases.BiliLiveDatabase;
import com.yutou.biliapi.enums.LiveProtocol;
import com.yutou.biliapi.enums.LiveVideoCodec;
import com.yutou.biliapi.enums.LiveVideoDefinition;
import com.yutou.biliapi.enums.LiveVideoFormat;
import com.yutou.biliapi.net.BiliLiveNetApiManager;
import com.yutou.biliapi.net.WebSocketManager;
import com.yutou.bilibili.Tools.DateFormatUtils;
import com.yutou.bilibili.Tools.FileServerUtils;
import com.yutou.bilibili.Tools.LiveInfoNfoTools;
import com.yutou.bilibili.Tools.Tools;
import com.yutou.bilibili.datas.VideoFilePath;
import com.yutou.bilibili.interfaces.DownloadInterface;
import com.yutou.common.okhttp.HttpCallback;
import com.yutou.common.okhttp.HttpDownloadUtils;
import com.yutou.common.record.AbsVideoRecord;
import com.yutou.common.utils.ConfigTools;
import com.yutou.common.utils.FFmpegUtils;
import com.yutou.common.utils.Log;
import okhttp3.Headers;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.io.File;
import java.io.FileFilter;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import static com.alibaba.fastjson2.util.DateUtils.DateTimeFormatPattern.DATE_FORMAT_10_DASH;
@Service @Service
public class LiveVideoService { public class LiveVideoService {
private final ThreadPoolExecutor executor;
private final List<String> userStopList = new ArrayList<>();//手动停止列表
private final AbsVideoRecord videoRecord;
public LiveVideoService() {
Log.i("初始化下载服务");
videoRecord = new FFmpegUtils();
executor = new ThreadPoolExecutor(2, 4, Long.MAX_VALUE, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100));
}
public boolean checkDownload(String roomId) {
return videoRecord.check(roomId);
}
public void clearUserStopList() {
userStopList.clear();
}
public void start(LiveConfigDatabaseBean bean, boolean isUser) {
if (!isUser && userStopList.contains(bean.getRoomId().toString())) {
return;
}
if (isUser) {
userStopList.remove(bean.getRoomId().toString());
}
if (videoRecord.check(bean.getRoomId().toString())) {
return;
}
BiliLiveNetApiManager.getInstance().getApi(bean.getRecordUid()).getRoomInfo(bean.getRoomId().toString()).enqueue(new HttpCallback<LiveRoomInfo>() {
@Override
public void onResponse(Headers headers, int code, String status, LiveRoomInfo response, String rawResponse) {
if (response.getLiveStatus() == 1) {
VideoTask task = new VideoTask(bean, response);
executor.execute(task);
} else {
Log.i("移除下载");
}
}
@Override
public void onFailure(Throwable throwable) {
Log.i("移除下载");
}
});
}
public void stop(String roomId, boolean isUser) {
if (isUser) {
userStopList.add(roomId);
}
videoRecord.kill(roomId);
}
public JSONArray getDownloadTasks() {
JSONArray array = new JSONArray();
array.addAll(videoRecord.getRoomIds());
return array;
}
public void stopAll() {
videoRecord.killAll();
}
private class VideoTask implements Runnable {
LiveConfigDatabaseBean bean;
boolean isDownload = true;
LiveApi api;
String savePath;
File rootPath;
LiveConfigDatabaseBean config;
BiliLiveDatabase database;
LiveVideoDatabaseBean videoDatabaseBean;
LiveRoomInfo roomInfo;
public VideoTask(LiveConfigDatabaseBean bean, LiveRoomInfo roomInfo) {
this.bean = bean;
this.roomInfo = roomInfo;
api = BiliLiveNetApiManager.getInstance().getApi(bean.getRecordUid());
}
@Override
public void run() {
if (roomInfo.getLiveStatus() == 1) {
String time = DateUtils.format(new Date().getTime(), DATE_FORMAT_10_DASH);
rootPath = new File(bean.getRecordPath() + File.separator + bean.getAnchorName() + File.separator + time + File.separator + roomInfo.getTitle());
savePath = rootPath.getAbsolutePath() + File.separator + "[" +
DateUtils.format(new Date(),
"yyyy-MM-dd HH-mm-ss") + "]" + roomInfo.getTitle() + ".flv";
if (!rootPath.exists()) {
rootPath.mkdirs();
}
record(bean, roomInfo);
} else {
stop();
}
}
private void stop() {
videoRecord.kill(bean.getRoomId().toString());
api.getRoomInfo(config.getRoomId().toString()).enqueue(new HttpCallback<LiveRoomInfo>() {
@Override
public void onResponse(Headers headers, int code, String status, LiveRoomInfo response, String rawResponse) {
if (response.getLiveStatus() == 1) {
LiveVideoService.this.start(bean, false);
} else {
LiveVideoService.this.stop(bean.getRoomId().toString(), false);
}
}
@Override
public void onFailure(Throwable throwable) {
}
});
}
private void record(LiveConfigDatabaseBean bean, LiveRoomInfo roomInfo) {
this.config = bean;
isDownload = true;
LiveRoomConfig config = new LiveRoomConfig();
config.setLoginUid(bean.getRecordUid());
config.setRoomId(bean.getRoomId());
config.setAnchorName(bean.getAnchorName());
config.setLogin(StringUtils.hasText(bean.getRecordUid()));
config.setRoomInfo(roomInfo);
config.setRootPath(bean.getRecordPath());
database = new BiliLiveDatabase(config);
HttpDownloadUtils.download(new HttpDownloadUtils.Builder().setUrl(roomInfo.getKeyframe())
.setPath(rootPath.getAbsolutePath())
.setFileName("poster.jpg"));
LiveInfoNfoTools.saveLiveInfoNfo(roomInfo, rootPath.getAbsolutePath(), new File(savePath).getName().replace(".flv", ".nfo"));
saveLiveInfo(roomInfo);
api.getLiveRoomPlayInfo(
bean.getRoomId().toString(),
LiveProtocol.getAll(),
LiveVideoFormat.getAll(),
LiveVideoCodec.getAll(),
LiveVideoDefinition.ORIGINAL.getValue()).enqueue(new HttpCallback<LiveRoomPlayInfo>() {
@Override
public void onResponse(Headers headers, int code, String status, LiveRoomPlayInfo response, String rawResponse) {
LiveRoomPlayInfo.Codec codec = response.getPlayurlInfo().getPlayurl().getStream().get(0).getFormat().get(0).getCodec().get(0);
String url = codec.getUrlInfo().get(0).getHost() + codec.getBaseUrl() + codec.getUrlInfo().get(0).getExtra();
if (bean.getRecordLiveModel() == 1) {
javaRecord(url, response);
} else {
ffmpeg(url, response);
}
}
@Override
public void onFailure(Throwable throwable) {
Log.e(throwable);
}
});
}
private void javaRecord(String url, LiveRoomPlayInfo playInfo) {
HttpDownloadUtils.download(new HttpDownloadUtils.Builder()
.setUrl(url)
.setPath(savePath)
.setDownloadInterface(new DownloadInterface() {
@Override
public void onDownloadStart() {
super.onDownloadStart();
VideoTask.this.onStart();
}
@Override
public boolean onDownloading(double soFarBytes, double totalBytes) {
return isDownload;
}
@Override
public void onDownload(File file) {
super.onDownload(file);
stop();
}
@Override
public void onError(Exception e) {
super.onError(e);
stop();
}
}));
}
private void ffmpeg(String url, LiveRoomPlayInfo playInfo) {
String ffmpegPath = ConfigTools.load(ConfigTools.CONFIG, "ffmpeg", String.class);
String cookie = "";
LoginCookieDatabaseBean ck = BiliBiliLoginDatabase.getInstance().getCookie(config.getRecordUid());
if (ck != null) {
cookie = ck.toCookieString();
}
FFmpegUtils.Builder builder = new FFmpegUtils.Builder()
.withParam("-user_agent", ConfigTools.getUserAgent())
.withParam("-headers", "Referer: https://live.bilibili.com")
// .withNotSymbolParam("-progress", "-")
.withNotSymbolParam("-threads", "8")
.withNotSymbolParam("-c:v", "copy")
.withNotSymbolParam("-y", "");
if (ck != null) {
builder = builder.withParam("-cookies", cookie);
}
FFmpegUtils command = builder.build(config.getRoomId(), ffmpegPath, url, savePath);
Log.i(command.getCommand());
try {
command.start(new DownloadInterface() {
@Override
public void onDownloadStart() {
super.onDownloadStart();
VideoTask.this.onStart();
}
@Override
public boolean onDownloading(double soFarBytes, double totalBytes) {
if (!isDownload) {
command.stop();
}
return super.onDownloading(soFarBytes, totalBytes);
}
@Override
public void onDownload(File file) {
super.onDownload(file);
Log.e("下载完成 ");
stop();
}
});
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private void onStart() {
videoDatabaseBean = new LiveVideoDatabaseBean();
videoDatabaseBean.setPath(savePath);
videoDatabaseBean.setRoomInfoJson(JSONObject.toJSONString(roomInfo));
videoDatabaseBean.setStartTime(new Date());
database.addLiveInfo(videoDatabaseBean);
}
}
private void saveLiveInfo(LiveRoomInfo roomInfo) {
}
public List<VideoFilePath> getAllVideoPath() {
BiliLiveConfigDatabase configDatabase = new BiliLiveConfigDatabase();
List<LiveConfigDatabaseBean> list = configDatabase.getAllConfig();
configDatabase.close();
List<VideoFilePath> filePathList = new ArrayList<>();
for (LiveConfigDatabaseBean bean : list) {
filePathList.addAll(getVideoFilePath(bean));
}
return filePathList;
}
public List<VideoFilePath> getVideoPath(String roomId) {
BiliLiveConfigDatabase configDatabase = new BiliLiveConfigDatabase();
LiveConfigDatabaseBean bean = configDatabase.getConfig(new String(roomId));
configDatabase.close();
return new ArrayList<>(getVideoFilePath(bean));
}
private List<VideoFilePath> getVideoFilePath(LiveConfigDatabaseBean configBean) {
List<VideoFilePath> filePathList = new ArrayList<>();
String recordPath = configBean.getRecordPath() + File.separator + configBean.getAnchorName();
File recordDir = new File(recordPath);
if (recordDir.exists()) {
BiliLiveDatabase database = new BiliLiveDatabase(LiveRoomConfig.buildConfig(configBean.getRoomId().toString()), recordDir.getAbsolutePath());
VideoFilePath path = createVideoRootFilePath(configBean, recordDir);
List<LiveVideoDatabaseBean> infos = database.getLiveInfos();
database.close();
path.setChildren(getVideoInfo(infos));
filePathList.add(path);
}
return filePathList;
}
private VideoFilePath createVideoRootFilePath(LiveConfigDatabaseBean config, File db) {
VideoFilePath path = new VideoFilePath();
path.setRoomId(config.getRoomId().toString());
path.setCover(config.getAnchorFace());
path.setName(config.getAnchorName());
path.setParent(true);
path.setPath(FileServerUtils.toUrl(db.getParent()));
return path;
}
private List<VideoFilePath> getVideoInfo(List<LiveVideoDatabaseBean> videoList) {
List<VideoFilePath> filePathList = new ArrayList<>();
for (LiveVideoDatabaseBean bean : videoList) {
VideoFilePath path = new VideoFilePath();
LiveRoomInfo roomInfo = JSONObject.parseObject(bean.getRoomInfoJson(), LiveRoomInfo.class);
path.setRoomId(roomInfo.getRoomId().toString());
path.setName(roomInfo.getTitle());
path.setPath(DateFormatUtils.format(bean.getSql_time()));
path.setCover(roomInfo.getKeyframe());
path.setParent(false);
path.setChildren(null);
filePathList.add(path);
}
return filePathList;
}
public static void main(String[] args) {
LiveVideoService service = new LiveVideoService();
List<VideoFilePath> path = service.getAllVideoPath();
Log.i("path.size() = " + path.size());
Log.i(JSONArray.toJSONString(path));
}
} }

View File

@ -1,27 +1,16 @@
package com.yutou.bilibili.services; package com.yutou.bilibili.services;
import com.yutou.biliapi.api.LiveApi;
import com.yutou.biliapi.bean.live.LiveRoomConfig;
import com.yutou.biliapi.bean.live.LiveRoomInfo;
import com.yutou.biliapi.bean.live.database.LiveConfigDatabaseBean; import com.yutou.biliapi.bean.live.database.LiveConfigDatabaseBean;
import com.yutou.biliapi.databases.BiliLiveConfigDatabase; import com.yutou.biliapi.databases.BiliLiveConfigDatabase;
import com.yutou.biliapi.net.BiliLiveNetApiManager;
import com.yutou.biliapi.net.WebSocketManager;
import com.yutou.bilibili.Tools.DateFormatUtils; import com.yutou.bilibili.Tools.DateFormatUtils;
import com.yutou.bilibili.databases.SystemConfigDatabases; import com.yutou.bilibili.databases.SystemConfigDatabases;
import com.yutou.bilibili.datas.SystemConfigDatabaseBean; import com.yutou.bilibili.datas.SystemConfigDatabaseBean;
import com.yutou.common.okhttp.HttpBody;
import com.yutou.common.utils.Log; import com.yutou.common.utils.Log;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import retrofit2.Response;
import java.io.IOException;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
@ -30,7 +19,7 @@ import java.util.concurrent.TimeUnit;
@Service @Service
public class SystemService { public class SystemService {
@Resource @Resource
LiveVideoService videoService; LiveVideoDownloadService videoService;
@Resource @Resource
LiveDanmuService danmuService; LiveDanmuService danmuService;
SystemConfigDatabases databases = new SystemConfigDatabases(); SystemConfigDatabases databases = new SystemConfigDatabases();
@ -59,7 +48,7 @@ public class SystemService {
scheduled = timer.scheduleAtFixedRate(() -> { scheduled = timer.scheduleAtFixedRate(() -> {
List<LiveConfigDatabaseBean> list = liveConfigDatabase.getAllConfig(); List<LiveConfigDatabaseBean> list = liveConfigDatabase.getAllConfig();
Log.i("循环任务:" + list.size()); Log.i("循环任务:" + list.size());
if(DateFormatUtils.checkTime(null,resetTimer)){ if (DateFormatUtils.checkTime(null, resetTimer)) {
videoService.clearUserStopList(); videoService.clearUserStopList();
danmuService.clearUserList(); danmuService.clearUserList();
} }
@ -67,6 +56,8 @@ public class SystemService {
try { try {
if (bean.isRecordDanmu() && bean.checkRecordDanmuTime()) { if (bean.isRecordDanmu() && bean.checkRecordDanmuTime()) {
recordDanmu(bean); recordDanmu(bean);
} else if (!bean.checkRecordDanmuTime()) {
stopRecordDanmu(bean);
} }
if (bean.isRecordLive() && bean.checkRecordLiveTime()) { if (bean.isRecordLive() && bean.checkRecordLiveTime()) {
recordVideo(bean); recordVideo(bean);
@ -79,6 +70,12 @@ public class SystemService {
}, 0, getLoopTimer(), TimeUnit.MILLISECONDS); }, 0, getLoopTimer(), TimeUnit.MILLISECONDS);
} }
private void stopRecordDanmu(LiveConfigDatabaseBean bean) {
if (!videoService.checkDownload(bean.getRoomId())) {
danmuService.stop(bean.getRoomId(), false);
}
}
public void stop() { public void stop() {
scheduled.cancel(true); scheduled.cancel(true);
videoService.stopAll(); videoService.stopAll();