This commit is contained in:
zlzw 2024-11-02 18:24:16 +08:00
parent 579fd2eaf6
commit 51f961b054
18 changed files with 298 additions and 96 deletions

5
.gitignore vendored
View File

@ -31,3 +31,8 @@ build/
### VS Code ### ### VS Code ###
.vscode/ .vscode/
### dir ###
/live/
/databases/
/cache/

View File

@ -10,43 +10,57 @@
<body class="layui-bg-gray"> <body class="layui-bg-gray">
<div id="header"></div> <div id="header"></div>
<div class="layui-panel" style="width: 260px; margin: 16px;"> <div class="layui-row">
<ul class="layui-menu" id="menusss"> <div class="layui-col-xs2">
<!-- <div id="menuView"></div> --> <div class="grid-demo grid-demo-bg1">
<li class="layui-menu-item-group layui-menu-item-down" lay-options="{type: 'group'}"> <div class="layui-panel" style="width: auto; margin: 16px;">
<div class="layui-menu-body-title"> <ul class="layui-menu" id="menusss">
menu group <i class="layui-icon layui-icon-up"></i> <div id="menuView"></div>
</ul>
</div> </div>
<ul> </div>
<li lay-options="{id: 103}"> </div>
<div class="layui-menu-body-title">menu item 3-1</div> <div class="layui-col-xs9">
</li> <div class="grid-demo">
<li lay-options="{id: 102}"> <video id="videoElement" style="width: 80%; margin-top: 16px;" controls></video>
<div class="layui-menu-body-title">menu item 3-2</div> </div>
</li> </div>
</ul>
</li>
</ul>
</div> </div>
</body> </body>
<script id="menulist" type="text/html"> <script id="menulist" type="text/html">
<ul class="layui-tab-title"> <ul class="layui-tab-title">
{{# layui.each(d.data, function(index, item){ }}
<li lay-id="{{= item.live_room_id}}">{{= item.anchorName}}</li> {{# layui.each(Object.keys(d), function(index, item){ }}
<li class="layui-menu-item-group layui-menu-item-down" lay-options="{type: 'group'}">
<div class="layui-menu-body-title">
{{= item}} <i class="layui-icon layui-icon-up"></i>
</div>
<ul>
{{# layui.each(d[item], function(index, video){ }}
<li lay-options="{id: {{= video.path}} }">
<div class="layui-menu-body-title">{{= video.name}}</div>
</li>
{{# }); }}
</ul>
</li>
{{# }); }} {{# }); }}
{{# if(d.data.length === 0){ }}
无数据
{{# } }}
</ul> </ul>
</script> </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="/js/httpUtils.js"></script>
<script src="/layui/layui.js"></script> <script src="/layui/layui.js"></script>
<script src="https://cdn.jsdelivr.net/npm/hls.js@1"></script>
<script> <script>
headerModel = 2; headerModel = 2;
$('#header').load("/html/header.html"); $('#header').load("/html/header.html");
@ -62,28 +76,40 @@
var layer = layui.layer; var layer = layui.layer;
var laytpl = layui.laytpl; var laytpl = layui.laytpl;
function initTabs() { function initTabs() {
getVideo(roomId, pageIndex, pageMax) getVideo(roomId, 0, 0)
.then(data => { .then(data => {
initMenu(data) initMenu(data.data.children)
}) })
} }
dropdown.on('click(menusss)', function (options) { dropdown.on('click(menusss)', function (options) {
console.log(this, options); console.log(options);
// playVideo()
getPlayerVideo(roomId, options.id)
.then(data => {
playVideo(data.data)
})
}); });
function initMenu(data) { function initMenu(data) {
var view = $("#menuView").get(0); var view = $("#menuView").get(0);
laytpl($('#menulist').get(0).innerHTML).render(data, function (html) { laytpl($('#menulist').get(0).innerHTML).render(data, function (html) {
console.log(html)
view.innerHTML = html; view.innerHTML = html;
layer.close(loadIndex)
}); });
} }
function init() { function init() {
// initTabs() initTabs()
} }
function playVideo(url) {
var video = document.getElementById('videoElement');
var videoSrc = url;
var hls = new Hls();
hls.loadSource(videoSrc);
hls.attachMedia(video);
}
init() init()
}) })

View File

@ -135,6 +135,9 @@ function stopLiveVideo(roomId){
function getVideo(roomId,page,limit){ function getVideo(roomId,page,limit){
return get("/file/list?roomId="+roomId+"&page="+page+"&limit="+limit) return get("/file/list?roomId="+roomId+"&page="+page+"&limit="+limit)
} }
function getPlayerVideo(roomId,videoId){
return get('/video/play?roomId='+roomId+"&videoId="+videoId)
}
//----------------直播视频相关接口end //----------------直播视频相关接口end
//----------------弹幕相关接口 //----------------弹幕相关接口
function startLiveDanmu(roomId){ function startLiveDanmu(roomId){

9
Web/js/mpegts.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,55 @@
package com.yutou.biliapi.bean.live.database;
import com.alibaba.fastjson2.annotation.JSONField;
import com.yutou.biliapi.bean.websocket.live.WSGuardBuy;
import com.yutou.common.databases.AbsDatabasesBean;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class LiveGuardBuyBean extends AbsDatabasesBean {
@JSONField(name = "uid")
private String uid;
@JSONField(name = "username")
private String username;
@JSONField(name = "guard_level")
private long guardLevel;
@JSONField(name = "num")
private long num;
@JSONField(name = "price")
private long price;
@JSONField(name = "gift_id")
private long giftID;
@JSONField(name = "gift_name")
private String giftName;
@JSONField(name = "start_time")
private long startTime;
@JSONField(name = "end_time")
private long endTime;
public LiveGuardBuyBean() {
super("guardBuy", System.currentTimeMillis());
}
public LiveGuardBuyBean(WSGuardBuy guard) {
super("guardBuy", System.currentTimeMillis());
this.uid = guard.getUid();
this.username = guard.getUsername();
this.guardLevel = guard.getGuardLevel();
this.num = guard.getNum();
this.price = guard.getPrice();
this.giftID = guard.getGiftID();
this.giftName = guard.getGiftName();
this.startTime = guard.getStartTime();
this.endTime = guard.getEndTime();
}
}

View File

@ -14,7 +14,7 @@ public class LiveSuperChatDatabaseBean extends AbsDatabasesBean {
@JSONField(name = "price") @JSONField(name = "price")
private long price; private long price;
@JSONField(name = "uid") @JSONField(name = "uid")
private long uid; private String uid;
@JSONField(name = "start_time") @JSONField(name = "start_time")
private long start_time; private long start_time;
@JSONField(name = "end_time") @JSONField(name = "end_time")
@ -25,6 +25,10 @@ public class LiveSuperChatDatabaseBean extends AbsDatabasesBean {
private String message_trans; private String message_trans;
@JSONField(name = "message_font_color") @JSONField(name = "message_font_color")
private String message_font_color; private String message_font_color;
@JSONField(name ="user_name")
private String userName;
@JSONField(name ="user_avatar")
private String userAvatar;
public LiveSuperChatDatabaseBean() { public LiveSuperChatDatabaseBean() {
super("superChat",System.currentTimeMillis()); super("superChat",System.currentTimeMillis());

View File

@ -38,6 +38,7 @@ public class WSData implements Serializable, ISqlDatabaseBean {
case "SEND_GIFT" -> new WSSendGift(json); case "SEND_GIFT" -> new WSSendGift(json);
case "INTERACT_WORD" -> new WSInteractWord(json); case "INTERACT_WORD" -> new WSInteractWord(json);
case "GUARD_BUY" -> new WSGuardBuy(json); case "GUARD_BUY" -> new WSGuardBuy(json);
case "SUPER_CHAT_MESSAGE" -> new WSSuperChatMessage(json);
default -> new WSData(json); default -> new WSData(json);
}; };
} }

View File

@ -12,7 +12,7 @@ import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@Data @Data
public class WSGuardBuy extends WSData{ public class WSGuardBuy extends WSData{
private long uid; private String uid;
private String username; private String username;
private long guardLevel; private long guardLevel;
private long num; private long num;
@ -30,7 +30,7 @@ public class WSGuardBuy extends WSData{
public WSGuardBuy(JSONObject json) { public WSGuardBuy(JSONObject json) {
super(json); super(json);
JSONObject data = json.getJSONObject("data"); JSONObject data = json.getJSONObject("data");
uid = data.getLong("uid"); uid = data.getString("uid");
username = data.getString("username"); username = data.getString("username");
guardLevel = data.getLong("guard_level"); guardLevel = data.getLong("guard_level");
num = data.getLong("num"); num = data.getLong("num");

View File

@ -14,21 +14,33 @@ import lombok.EqualsAndHashCode;
public class WSSuperChatMessage extends WSData{ public class WSSuperChatMessage extends WSData{
private long price; private long price;
private long rate; private long rate;
private long uid; private String uid;
private long start_time; private long start_time;
private long end_time; private long end_time;
private String message; private String message;
private String message_trans; private String message_trans;
private String message_font_color; private String message_font_color;
private WSMedalInfo medal_info; private String userName;
private String userAvatar;
public static void main(String[] args) { public static void main(String[] args) {
JSONObject json=JSONObject.parseObject("{\"cmd\":\"SUPER_CHAT_MESSAGE\",\"data\":{\"background_bottom_color\":\"#2A60B2\",\"background_color\":\"#EDF5FF\",\"background_color_end\":\"#405D85\",\"background_color_start\":\"#3171D2\",\"background_icon\":\"\",\"background_image\":\"\",\"background_price_color\":\"#7497CD\",\"color_point\":0.7,\"dmscore\":616,\"end_time\":1724997230,\"gift\":{\"gift_id\":12000,\"gift_name\":\"醒目留言\",\"num\":1},\"group_medal\":{\"is_lighted\":0,\"medal_id\":0,\"name\":\"\"},\"id\":10427329,\"is_mystery\":false,\"is_ranked\":0,\"is_send_audit\":1,\"medal_info\":{\"anchor_roomid\":81004,\"anchor_uname\":\"艾尔莎_Channel\",\"guard_level\":0,\"icon_id\":0,\"is_lighted\":1,\"medal_color\":\"#1a544b\",\"medal_color_border\":1725515,\"medal_color_end\":5414290,\"medal_color_start\":1725515,\"medal_level\":21,\"medal_name\":\"艾薯条\",\"special\":\"\",\"target_id\":1521415},\"message\":\"莎莎,想安利你个植物大战僵尸的改版叫植物大战僵尸:肉鸽,具体情况私信你了,辛苦了\",\"message_font_color\":\"#A3F6FF\",\"message_trans\":\"サーシャ、あなたのPlantsvs.Zombiesの改版をPlantsvs.Zombiesと言いたい肉鳩、具体的な状況は私的にあなたを信じて、お疲れ様でした\",\"price\":30,\"rate\":1000,\"start_time\":1724997170,\"time\":60,\"token\":\"9925C118\",\"trans_mark\":0,\"ts\":1724997170,\"uid\":100002175,\"uinfo\":{\"base\":{\"face\":\"https://i1.hdslb.com/bfs/face/b5ec3b1f7025b5546225ae0f36941d55ddef405b.jpg\",\"is_mystery\":false,\"name\":\"中吴同学\",\"name_color\":0,\"name_color_str\":\"#666666\",\"official_info\":{\"desc\":\"\",\"role\":0,\"title\":\"\",\"type\":-1},\"origin_info\":{\"face\":\"https://i1.hdslb.com/bfs/face/b5ec3b1f7025b5546225ae0f36941d55ddef405b.jpg\",\"name\":\"中吴同学\"}},\"guard\":{\"expired_str\":\"\",\"level\":0},\"medal\":{\"color\":1725515,\"color_border\":1725515,\"color_end\":5414290,\"color_start\":1725515,\"guard_icon\":\"\",\"guard_level\":0,\"honor_icon\":\"\",\"id\":0,\"is_light\":1,\"level\":21,\"name\":\"艾薯条\",\"ruid\":1521415,\"score\":50001980,\"typ\":0,\"user_receive_count\":0,\"v2_medal_color_border\":\"#5FC7F4FF\",\"v2_medal_color_end\":\"#43B3E3CC\",\"v2_medal_color_level\":\"#00308C99\",\"v2_medal_color_start\":\"#43B3E3CC\",\"v2_medal_color_text\":\"#FFFFFFFF\"},\"title\":{\"old_title_css_id\":\"\",\"title_css_id\":\"\"},\"uid\":100002175},\"user_info\":{\"face\":\"https://i1.hdslb.com/bfs/face/b5ec3b1f7025b5546225ae0f36941d55ddef405b.jpg\",\"face_frame\":\"\",\"guard_level\":0,\"is_main_vip\":1,\"is_svip\":0,\"is_vip\":0,\"level_color\":\"#5896de\",\"manager\":0,\"name_color\":\"#666666\",\"title\":\"\",\"uname\":\"中吴同学\",\"user_level\":25}},\"is_report\":true,\"msg_id\":\"19106780029655552:1000:1000\",\"p_is_ack\":true,\"p_msg_type\":1,\"send_time\":1724997170767}"); JSONObject json=JSONObject.parseObject("{\"cmd\":\"SUPER_CHAT_MESSAGE\",\"data\":{\"background_bottom_color\":\"#E2B52B\",\"background_color\":\"#FFF1C5\",\"background_color_end\":\"#EEBE5C\",\"background_color_start\":\"#EAB400\",\"background_icon\":\"\",\"background_image\":\"\",\"background_price_color\":\"#ECCF75\",\"color_point\":0.7,\"dmscore\":714,\"end_time\":1730462758,\"gift\":{\"gift_id\":12000,\"gift_name\":\"醒目留言\",\"num\":1},\"group_medal\":{\"is_lighted\":0,\"medal_id\":0,\"name\":\"\"},\"id\":10855278,\"is_mystery\":false,\"is_ranked\":0,\"is_send_audit\":0,\"medal_info\":{\"anchor_roomid\":5265,\"anchor_uname\":\"Liyuu_\",\"guard_level\":3,\"icon_id\":0,\"is_lighted\":1,\"medal_color\":\"#06154c\",\"medal_color_border\":6809855,\"medal_color_end\":6850801,\"medal_color_start\":398668,\"medal_level\":25,\"medal_name\":\"水溅跃\",\"special\":\"\",\"target_id\":4549624},\"message\":\"芋泥泥最近在哪发财呢\",\"message_font_color\":\"#72110E\",\"message_trans\":\"\",\"price\":100,\"rate\":1000,\"start_time\":1730462458,\"time\":300,\"token\":\"D6F223DA\",\"trans_mark\":0,\"ts\":1730462458,\"uid\":19970343,\"uinfo\":{\"base\":{\"face\":\"https://i0.hdslb.com/bfs/face/e3b35f66d631f740770b2b64bd3bcc1e66322717.jpg\",\"is_mystery\":false,\"name\":\"蘭梅蛋糕\",\"name_color\":0,\"name_color_str\":\"#00D1F1\",\"official_info\":{\"desc\":\"\",\"role\":0,\"title\":\"\",\"type\":-1},\"origin_info\":{\"face\":\"https://i0.hdslb.com/bfs/face/e3b35f66d631f740770b2b64bd3bcc1e66322717.jpg\",\"name\":\"蘭梅蛋糕\"}},\"guard\":{\"expired_str\":\"2024-11-01 23:59:59\",\"level\":3},\"medal\":{\"color\":398668,\"color_border\":6809855,\"color_end\":6850801,\"color_start\":398668,\"guard_icon\":\"https://i0.hdslb.com/bfs/live/143f5ec3003b4080d1b5f817a9efdca46d631945.png\",\"guard_level\":3,\"honor_icon\":\"\",\"id\":0,\"is_light\":1,\"level\":25,\"name\":\"水溅跃\",\"ruid\":4549624,\"score\":50020367,\"typ\":0,\"user_receive_count\":0,\"v2_medal_color_border\":\"#58A1F8FF\",\"v2_medal_color_end\":\"#4775EFCC\",\"v2_medal_color_level\":\"#000B7099\",\"v2_medal_color_start\":\"#4775EFCC\",\"v2_medal_color_text\":\"#FFFFFFFF\"},\"title\":{\"old_title_css_id\":\"title-153-1\",\"title_css_id\":\"title-153-1\"},\"uid\":19970343},\"user_info\":{\"face\":\"https://i0.hdslb.com/bfs/face/e3b35f66d631f740770b2b64bd3bcc1e66322717.jpg\",\"face_frame\":\"https://i0.hdslb.com/bfs/live/80f732943cc3367029df65e267960d56736a82ee.png\",\"guard_level\":3,\"is_main_vip\":0,\"is_svip\":0,\"is_vip\":0,\"level_color\":\"#61c05a\",\"manager\":0,\"name_color\":\"#00D1F1\",\"title\":\"title-153-1\",\"uname\":\"蘭梅蛋糕\",\"user_level\":15}},\"is_report\":true,\"msg_id\":\"21972164819290113:1000:1000\",\"p_is_ack\":true,\"p_msg_type\":1,\"send_time\":1730462458528}");
WSSuperChatMessage message=new WSSuperChatMessage(json); WSSuperChatMessage message=new WSSuperChatMessage(json);
Log.i(message); Log.i(message);
} }
public WSSuperChatMessage(JSONObject json) { public WSSuperChatMessage(JSONObject json) {
super(json); super(json);
JSONObject data=json.getJSONObject("data");
setPrice(data.getLongValue("price"));
setRate(data.getLongValue("rate"));
setUid(data.getString("uid"));
setStart_time(data.getLongValue("start_time"));
setEnd_time(getStart_time()+(data.getIntValue("time")));
setMessage(data.getString("message"));
setMessage_trans(data.getString("message_trans"));
setMessage_font_color(data.getString("message_font_color"));
setUserName(data.getJSONObject("user_info").getString("uname"));
setUserAvatar(data.getJSONObject("user_info").getString("face"));
} }
} }

View File

@ -9,6 +9,7 @@ import com.yutou.common.databases.AbsDatabasesBean;
import com.yutou.common.databases.SQLiteManager; import com.yutou.common.databases.SQLiteManager;
import com.yutou.common.okhttp.HttpDownloadUtils; import com.yutou.common.okhttp.HttpDownloadUtils;
import com.yutou.common.utils.Log; import com.yutou.common.utils.Log;
import lombok.Getter;
import org.apache.poi.ss.usermodel.DataFormat; import org.apache.poi.ss.usermodel.DataFormat;
import java.io.File; import java.io.File;
@ -91,6 +92,8 @@ public class BiliLiveDatabase extends SQLiteManager {
add(new LiveGiftDatabaseBean((WSSendGift) bean)); add(new LiveGiftDatabaseBean((WSSendGift) bean));
} else if (bean instanceof WSSuperChatMessage) { } else if (bean instanceof WSSuperChatMessage) {
add(new LiveSuperChatDatabaseBean((WSSuperChatMessage) bean)); add(new LiveSuperChatDatabaseBean((WSSuperChatMessage) bean));
} else if (bean instanceof WSGuardBuy) {
add(new LiveGuardBuyBean((WSGuardBuy) bean));
} }
} }
@ -135,9 +138,17 @@ public class BiliLiveDatabase extends SQLiteManager {
} }
public static void main(String[] args) { public static void main(String[] args) {
/* List<LiveDanmuDatabaseBean> list = getInstance().get(-1, 1727515148800L, LiveDanmuDatabaseBean.class); BiliLiveDatabase biliLiveDatabase = new BiliLiveDatabase(LiveRoomConfig.buildConfig("5265"));
for (LiveDanmuDatabaseBean bean : list) { List<AbsDatabasesBean> list = List.of(
Log.i(bean.getSql_time() + "|" + bean); new LiveInfoDatabaseBean(),
}*/ new LiveDanmuDatabaseBean(),
new LiveGiftDatabaseBean(),
new LiveInteractWordDatabaseBean(),
new LiveSuperChatDatabaseBean()
);
for (AbsDatabasesBean item : list) {
biliLiveDatabase.clearTable(item.getTableName());
}
} }
} }

View File

@ -39,6 +39,11 @@ public class LiveDanmuController {
@ResponseBody @ResponseBody
@RequestMapping("/live/danmu/file/list") @RequestMapping("/live/danmu/file/list")
public JSONObject getDanmuList(String roomId) { public JSONObject getDanmuList(String roomId) {
return ResultData.success(service.getDanmuFileList(roomId)); return ResultData.success(ReturnCode.RC100);
}
@ResponseBody
@RequestMapping("/live/danmu/get")
public JSONObject getDanmu(String roomId,String videoId,String startTimer,long step) {
return ResultData.success(ReturnCode.RC100);
} }
} }

View File

@ -35,14 +35,8 @@ public class VideoFileController {
@ResponseBody @ResponseBody
@RequestMapping("/file/list") @RequestMapping("/file/list")
public JSONObject getFileList(int page,int limit,String roomId) { public JSONObject getFileList(int page, int limit, String roomId) {
List<VideoFilePath> list; return ResultData.success(videoService.getVideoPath(roomId));
if (StringUtils.hasText(roomId)) {
list = videoService.getVideoPath(roomId);
} else {
list = videoService.getAllVideoPath(page,limit);
}
return ResultData.success(list);
} }
@RequestMapping("/file/{base64}") @RequestMapping("/file/{base64}")
@ -74,6 +68,7 @@ public class VideoFileController {
} }
return null; return null;
} }
@RequestMapping(value = "/file/imgTmp", method = RequestMethod.POST) @RequestMapping(value = "/file/imgTmp", method = RequestMethod.POST)
@ResponseBody @ResponseBody
public String getTmpImg(String url) { public String getTmpImg(String url) {
@ -105,4 +100,9 @@ public class VideoFileController {
return ""; return "";
} }
@RequestMapping("/video/play")
@ResponseBody
public JSONObject getVideoUrl(String roomId, String videoId) {
return ResultData.success("/play/"+videoService.getVideoPlay(roomId, videoId));
}
} }

View File

@ -43,6 +43,10 @@ public class DateFormatUtils {
return null; return null;
} }
} }
public static String parseString(String date,String format){
Date time = parse(date, format);
return format(time,format);
}
public static boolean checkTime(List<String> weeks, String recordDate) { public static boolean checkTime(List<String> weeks, String recordDate) {
if (!StringUtils.hasText(recordDate)) { if (!StringUtils.hasText(recordDate)) {

View File

@ -3,6 +3,7 @@ package com.yutou.bilibili.datas;
import lombok.Data; import lombok.Data;
import java.util.List; import java.util.List;
import java.util.Map;
@Data @Data
public class VideoFilePath { public class VideoFilePath {
@ -12,5 +13,5 @@ public class VideoFilePath {
private String path; private String path;
private String cover; private String cover;
private boolean isParent; private boolean isParent;
private List<VideoFilePath> children; private Map<String, List<VideoFilePath>> children;
} }

View File

@ -1,10 +1,12 @@
package com.yutou.bilibili.services; package com.yutou.bilibili.services;
import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.yutou.biliapi.bean.live.LiveRoomConfig; import com.yutou.biliapi.bean.live.LiveRoomConfig;
import com.yutou.biliapi.bean.live.database.LiveConfigDatabaseBean; import com.yutou.biliapi.bean.live.database.LiveConfigDatabaseBean;
import com.yutou.biliapi.bean.live.database.LiveDanmuDatabaseBean; import com.yutou.biliapi.bean.live.database.LiveDanmuDatabaseBean;
import com.yutou.biliapi.bean.live.database.LiveVideoDatabaseBean; import com.yutou.biliapi.bean.live.database.LiveVideoDatabaseBean;
import com.yutou.biliapi.bean.websocket.live.WSData;
import com.yutou.biliapi.databases.BiliLiveConfigDatabase; import com.yutou.biliapi.databases.BiliLiveConfigDatabase;
import com.yutou.biliapi.databases.BiliLiveDatabase; import com.yutou.biliapi.databases.BiliLiveDatabase;
import com.yutou.biliapi.net.WebSocketManager; import com.yutou.biliapi.net.WebSocketManager;
@ -44,7 +46,7 @@ public class LiveDanmuService {
public List<File> getDanmuFileList(String roomId) { public List<File> getDanmuFileList(String roomId) {
BiliLiveConfigDatabase configDatabase=new BiliLiveConfigDatabase(); BiliLiveConfigDatabase configDatabase=new BiliLiveConfigDatabase();
LiveConfigDatabaseBean bean = configDatabase.getConfig(new String(roomId)); LiveConfigDatabaseBean bean = configDatabase.getConfig(roomId);
configDatabase.close(); configDatabase.close();
return Tools.scanFile(new File(bean.getRecordPath() + File.separator + bean.getAnchorName())); return Tools.scanFile(new File(bean.getRecordPath() + File.separator + bean.getAnchorName()));
} }
@ -76,12 +78,12 @@ public class LiveDanmuService {
} }
public static void main(String[] args) { public static void main(String[] args) {
LiveDanmuService service = new LiveDanmuService(); BiliLiveDatabase database = new BiliLiveDatabase(LiveRoomConfig.buildConfig("17961"));
List<File> files = service.getDanmuFileList("22047448"); for (LiveVideoDatabaseBean info : database.getLiveInfos()) {
for (File file : files) { System.out.println(info);
Log.i(file);
} }
WSData data = WSData.parse(JSONObject.parseObject("{\"cmd\":\"GUARD_BUY\",\"data\":{\"uid\":290721462,\"username\":\"BG7NOE型大地鱼干\",\"guard_level\":3,\"num\":1,\"price\":198000,\"gift_id\":10003,\"gift_name\":\"舰长\",\"start_time\":1730462544,\"end_time\":1730462544}}"));
System.out.println(data);
} }

View File

@ -299,26 +299,14 @@ public class LiveVideoDownloadService {
} }
public List<VideoFilePath> getAllVideoPath(int page, int limit) { public VideoFilePath getVideoPath(String roomId) {
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(); BiliLiveConfigDatabase configDatabase = new BiliLiveConfigDatabase();
LiveConfigDatabaseBean bean = configDatabase.getConfig(roomId); LiveConfigDatabaseBean bean = configDatabase.getConfig(roomId);
configDatabase.close(); configDatabase.close();
return new ArrayList<>(getVideoFilePath(bean)); return getVideoFilePath(bean);
} }
private List<VideoFilePath> getVideoFilePath(LiveConfigDatabaseBean configBean) { private VideoFilePath getVideoFilePath(LiveConfigDatabaseBean configBean) {
List<VideoFilePath> filePathList = new ArrayList<>();
String recordPath = configBean.getRecordPath() + File.separator + configBean.getAnchorName(); String recordPath = configBean.getRecordPath() + File.separator + configBean.getAnchorName();
File recordDir = new File(recordPath); File recordDir = new File(recordPath);
BiliLiveDatabase database = new BiliLiveDatabase(LiveRoomConfig.buildConfig(configBean.getRoomId()), recordDir.getAbsolutePath()); BiliLiveDatabase database = new BiliLiveDatabase(LiveRoomConfig.buildConfig(configBean.getRoomId()), recordDir.getAbsolutePath());
@ -328,8 +316,7 @@ public class LiveVideoDownloadService {
database.close(); database.close();
path.setChildren(getVideoInfo(infos)); path.setChildren(getVideoInfo(infos));
} }
filePathList.add(path); return path;
return filePathList;
} }
private VideoFilePath createVideoRootFilePath(LiveConfigDatabaseBean config, File db) { private VideoFilePath createVideoRootFilePath(LiveConfigDatabaseBean config, File db) {
@ -343,27 +330,59 @@ public class LiveVideoDownloadService {
return path; return path;
} }
private List<VideoFilePath> getVideoInfo(List<LiveVideoDatabaseBean> videoList) { private Map<String, List<VideoFilePath>> getVideoInfo(List<LiveVideoDatabaseBean> videoList) {
List<VideoFilePath> filePathList = new ArrayList<>(); Map<String, List<VideoFilePath>> map = new HashMap<>();
for (LiveVideoDatabaseBean bean : videoList) { for (LiveVideoDatabaseBean bean : videoList) {
String date = DateFormatUtils.format(bean.getSql_time(), "yyyy-MM-dd");
if (!map.containsKey(date)) {
map.put(date, new ArrayList<>());
}
VideoFilePath path = new VideoFilePath(); VideoFilePath path = new VideoFilePath();
LiveRoomInfo roomInfo = JSONObject.parseObject(bean.getRoomInfoJson(), LiveRoomInfo.class); LiveRoomInfo roomInfo = JSONObject.parseObject(bean.getRoomInfoJson(), LiveRoomInfo.class);
path.setRoomId(roomInfo.getRoomId()); path.setRoomId(roomInfo.getRoomId());
path.setName(roomInfo.getTitle()); path.setName(roomInfo.getTitle());
path.setUid(roomInfo.getUid()); path.setUid(roomInfo.getUid());
path.setPath(DateFormatUtils.format(bean.getSql_time())); path.setPath(String.valueOf(bean.getSql_time().getTime()));
path.setCover(roomInfo.getKeyframe()); path.setCover(roomInfo.getKeyframe());
path.setParent(false); path.setParent(false);
path.setChildren(null); path.setChildren(null);
filePathList.add(path); map.get(date).add(path);
} }
return filePathList; return map;
}
public String getVideoPlay(String roomId, String videoId) {
String ffmpegPath = ConfigTools.load(ConfigTools.CONFIG, "ffmpeg", String.class);
BiliLiveConfigDatabase configDatabase = new BiliLiveConfigDatabase();
LiveConfigDatabaseBean config = configDatabase.getConfig(roomId);
String recordPath = config.getRecordPath() + File.separator + config.getAnchorName();
configDatabase.close();
LiveVideoDatabaseBean videoInfo = null;
BiliLiveDatabase liveDatabase = new BiliLiveDatabase(LiveRoomConfig.buildConfig(roomId), new File(recordPath).getAbsolutePath());
for (LiveVideoDatabaseBean info : liveDatabase.getLiveInfos()) {
if (videoId.trim().equals(String.valueOf(info.getSql_time().getTime()))) {
videoInfo = info;
break;
}
}
if(videoInfo != null) {
FFmpegUtils ffmpeg = FFmpegUtils.segment(videoId, ffmpegPath, new File(videoInfo.getPath()), ConfigTools.load(ConfigTools.CONFIG, "outVideoPath", String.class));
System.out.println(ffmpeg.getCommand());
ffmpeg.start(new DownloadInterface() {
@Override
public void onDownload(File file) {
super.onDownload(file);
}
});
return ffmpeg.getOutputFilePath();
}
return null;
} }
public static void main(String[] args) { public static void main(String[] args) {
LiveVideoDownloadService service = new LiveVideoDownloadService(); LiveVideoDownloadService service=new LiveVideoDownloadService();
List<VideoFilePath> path = service.getAllVideoPath(1, 8); String play = service.getVideoPlay("17961", "1730363029293");
Log.i("path.size() = " + path.size()); System.out.println(play);
Log.i(JSONArray.toJSONString(path));
} }
} }

View File

@ -235,7 +235,7 @@ public abstract class SQLiteManager {
} }
protected int getCount(String table) { protected int getCount(String table) {
try (PreparedStatement preparedStatement = conn.prepareStatement("SELECT count(*) FROM "+table)) { try (PreparedStatement preparedStatement = conn.prepareStatement("SELECT count(*) FROM " + table)) {
try (ResultSet resultSet = preparedStatement.executeQuery()) { try (ResultSet resultSet = preparedStatement.executeQuery()) {
if (resultSet.next()) { if (resultSet.next()) {
return resultSet.getInt(1); return resultSet.getInt(1);
@ -287,6 +287,24 @@ public abstract class SQLiteManager {
} }
} }
/**
* 清空指定表中的所有数据
*
* @param tableName 要清空的表名
*/
public void clearTable(String tableName) {
try {
String sql = "DELETE FROM " + tableName;
try (Statement stmt = conn.createStatement()) {
int rowsDeleted = stmt.executeUpdate(sql);
stmt.close();
System.out.println("已删除 " + rowsDeleted + " 行数据从表 " + tableName);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void createSql(BuildSql build) { private void createSql(BuildSql build) {
try { try {

View File

@ -4,6 +4,8 @@ import com.yutou.bilibili.Tools.ProcessUtils;
import com.yutou.bilibili.interfaces.DownloadInterface; import com.yutou.bilibili.interfaces.DownloadInterface;
import com.yutou.common.record.AbsVideoRecord; import com.yutou.common.record.AbsVideoRecord;
import lombok.Getter; import lombok.Getter;
import org.apache.commons.io.FileUtils;
import org.springframework.util.StringUtils;
import java.io.*; import java.io.*;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -13,6 +15,8 @@ public class FFmpegUtils extends AbsVideoRecord {
private static final Map<String, Long> pidMap = new HashMap<>(); private static final Map<String, Long> pidMap = new HashMap<>();
@Getter @Getter
private String command; private String command;
@Getter
private String outputFilePath;
private String uid; private String uid;
InputStream inputStream; InputStream inputStream;
OutputStream outputStream; OutputStream outputStream;
@ -59,20 +63,45 @@ public class FFmpegUtils extends AbsVideoRecord {
pidMap.clear(); pidMap.clear();
} }
// ffmpeg.exe -i '.\[2024-11-01 19-56-06]喻黎黎来卷饼啦.flv' -f segment -segment_time 30 -segment_format mpegts -segment_list ..\..\..\..\Web\video\v.m3u8 -c copy -bsf:v h264_mp4toannexb -map 0 ..\..\..\..\Web\video\course-%04d.ts
//ffmpeg -i "[2024-10-31 16-23-48]学习柯学.flv" -f segment -segment_time 30 -segment_format mpegts -segment_list "C:\Users\583 \video.m3u8" -c copy -bsf:v h264_mp4toannexb -map 0 "C:\Users\58381\Documents\biliob\play\course-%04d.ts"
public static FFmpegUtils segment(String videoId, String ffmpegPath, File video, String outputPath) {
try {
FileUtils.deleteDirectory(new File(outputPath));
} catch (IOException e) {
throw new RuntimeException(e);
}
new File(outputPath).mkdirs();
FFmpegUtils ffmpeg = new FFmpegUtils();
ffmpeg.uid = videoId;
ffmpeg.command = new Builder().withNotSymbolParam("-f", "segment")
.withNotSymbolParam("-segment_time", "30")
.withNotSymbolParam("-segment_format", "mpegts")
.withParam("-segment_list", outputPath + File.separator + "video.m3u8")
.withNotSymbolParam("-c", "copy")
.withNotSymbolParam("-bsf:v", "h264_mp4toannexb")
.withNotSymbolParam("-map", "0")
.withParam("-y", outputPath + File.separator + "course-%04d.ts")
.getCommand(ffmpegPath, video.getAbsolutePath(), null);
ffmpeg.outputFilePath = "video.m3u8";
return ffmpeg;
}
// ffmpeg 切片
//
public static class Builder { public static class Builder {
private final Map<String, String> params = new LinkedHashMap<>(); private final LinkedHashMap<String, String> params = new LinkedHashMap<>();
private final Map<String, String> paramsNotSymbol = new LinkedHashMap<>();
public Builder withParam(String key, String value) { public Builder withParam(String key, String value) {
if (value != null) { if (value != null) {
params.put(key, value); params.put(key, "\"" + value + "\"");
} }
return this; return this;
} }
public Builder withNotSymbolParam(String key, String value) { public Builder withNotSymbolParam(String key, String value) {
if (value != null) { if (value != null) {
paramsNotSymbol.put(key, value); params.put(key, value);
} }
return this; return this;
} }
@ -80,22 +109,19 @@ public class FFmpegUtils extends AbsVideoRecord {
private String getCommand(String ffmpegPath, String inputUrl, String outputPath) { private String getCommand(String ffmpegPath, String inputUrl, String outputPath) {
StringBuilder command = new StringBuilder(ffmpegPath); StringBuilder command = new StringBuilder(ffmpegPath);
for (Map.Entry<String, String> entry : params.entrySet()) {
command.append(" ").append(entry.getKey());
if (entry.getValue() != null && !entry.getValue().isEmpty()) {
command.append(" ").append("\"").append(entry.getValue()).append("\"");
}
}
command.append(" -i ").append("\"").append(inputUrl).append("\""); command.append(" -i ").append("\"").append(inputUrl).append("\"");
for (Map.Entry<String, String> entry : paramsNotSymbol.entrySet()) { for (Map.Entry<String, String> entry : params.entrySet()) {
command.append(" ").append(entry.getKey()); if (StringUtils.hasText(entry.getKey())) {
command.append(" ");
command.append(entry.getKey());
}
if (entry.getValue() != null && !entry.getValue().isEmpty()) { if (entry.getValue() != null && !entry.getValue().isEmpty()) {
command.append(" ").append(entry.getValue()); command.append(" ").append(entry.getValue());
} }
} }
if (outputPath != null) {
command.append(" ").append("\"").append(outputPath).append("\""); command.append(" ").append("\"").append(outputPath).append("\"");
}
return command.toString(); return command.toString();
} }
@ -103,6 +129,7 @@ public class FFmpegUtils extends AbsVideoRecord {
public FFmpegUtils build(String uid, String ffmpegPath, String inputUrl, String outputPath) { public FFmpegUtils build(String uid, String ffmpegPath, String inputUrl, String outputPath) {
FFmpegUtils ffmpeg = new FFmpegUtils(); FFmpegUtils ffmpeg = new FFmpegUtils();
ffmpeg.command = getCommand(ffmpegPath, inputUrl, outputPath); ffmpeg.command = getCommand(ffmpegPath, inputUrl, outputPath);
ffmpeg.outputFilePath = outputPath;
ffmpeg.uid = uid; ffmpeg.uid = uid;
return ffmpeg; return ffmpeg;
} }