From 4474da490f7e9d666419e42c498879f95af559eb Mon Sep 17 00:00:00 2001 From: zlzw <583819556@qq.com> Date: Thu, 28 Nov 2024 17:54:26 +0800 Subject: [PATCH] =?UTF-8?q?update=20=E8=B0=83=E6=95=B4=E5=BC=B9=E5=B9=95?= =?UTF-8?q?=E6=8C=89=E6=89=B9=E6=AC=A1=E5=8A=A0=E8=BD=BD=EF=BC=8C=E9=98=B2?= =?UTF-8?q?=E6=AD=A2=E8=BF=87=E5=A4=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Web/html/body/data.html | 48 +++++++++- Web/html/body/live.html | 2 +- Web/html/body/video.html | 89 +++++++++++-------- Web/html/header.html | 3 + Web/html/ui/createConfig.html | 47 +++++++--- Web/js/httpUtils.js | 10 +-- .../live/database/LiveConfigDatabaseBean.java | 2 + .../live/database/LiveDanmuDatabaseBean.java | 7 +- .../biliapi/databases/BiliLiveDatabase.java | 36 +++++++- ...nager.java => WebSocketClientManager.java} | 67 +++++++------- .../Controllers/LiveConfigController.java | 4 +- .../Controllers/LiveDanmuController.java | 6 +- .../bilibili/datas/web/LiveVideoDanmu.java | 5 +- .../bilibili/services/LiveDanmuService.java | 46 ++++++---- .../services/LiveVideoDownloadService.java | 53 ++++++----- .../bilibili/services/SystemService.java | 14 ++- 16 files changed, 289 insertions(+), 150 deletions(-) rename src/main/java/com/yutou/biliapi/net/{WebSocketManager.java => WebSocketClientManager.java} (83%) diff --git a/Web/html/body/data.html b/Web/html/body/data.html index f51078a..1e4cb07 100644 --- a/Web/html/body/data.html +++ b/Web/html/body/data.html @@ -1,5 +1,6 @@ + @@ -11,15 +12,56 @@ 不想做了,鸽 - + + + + + - + + \ No newline at end of file diff --git a/Web/html/body/live.html b/Web/html/body/live.html index 164a7c3..73d809c 100644 --- a/Web/html/body/live.html +++ b/Web/html/body/live.html @@ -91,10 +91,10 @@ { field: 'recordPath', title: '保存路径', width: 120 }, { field: 'recordDanmu', title: '录制弹幕', width: 120, sort: true }, { field: 'recordLive', title: '录制视频', width: 120, sort: true }, + { field: 'syncDanmuForLive', title: '同步录制', width: 120, sort: true }, { field: 'recordDanmuDate', title: '弹幕录制预定时间', width: 100, sort: true }, { field: 'recordLiveDate', title: '视频录制预定时间', width: 100, sort: true }, { field: 'recordUid', title: '录制账号', width: 120, sort: true, templet: '
{{= d.recordUid}}' }, - { field: 'recordDanmu', title: '录制弹幕', width: 120, sort: true }, { field: 'sql_time', title: '添加时间', width: 100 }, { fixed: "right", title: "操作", width: 190, align: "center", toolbar: "#toolDemo" } ]], diff --git a/Web/html/body/video.html b/Web/html/body/video.html index d557258..7545fdb 100644 --- a/Web/html/body/video.html +++ b/Web/html/body/video.html @@ -6,11 +6,7 @@ 视频中心 - + @@ -27,36 +23,44 @@
-
- +
+
+ +
+
+
+
+ +
+
+  
+ 弹幕透明度 +
+
+ 弹幕装载数:你猜 +
-
-

Super Chat 列表

-
-
-
-
-
 
-
- -
-
-  
- 弹幕透明度 -
-
- 弹幕装载数:你猜 +
+
+
+ +
+
+
+
+

Super Chat 列表

+
+
+ +
-
-
 
-
- -
-
-
+ + + \ No newline at end of file diff --git a/Web/html/ui/createConfig.html b/Web/html/ui/createConfig.html index deb3d1b..9cdfbd2 100644 --- a/Web/html/ui/createConfig.html +++ b/Web/html/ui/createConfig.html @@ -29,16 +29,26 @@
+
+ +

+ + +
+
+
+ +
- - - - - - - + + + + + + +
@@ -96,6 +106,10 @@ layer.tips('仅在当前时间范围内录制,如遇到正在直播,则延迟到下播时停止录制', that); } + } + function timeTips2(that) { + layer.tips('启用后,录制视频时会同步录制弹幕,下播后会同步停止录制.同时上面录制弹幕按钮将失效', that); + } var roomId = getParam("roomId"); var editArray = getParam("array") @@ -125,7 +139,7 @@ field.weeks = weeks; console.log(field) if (editArray === null) { - var loadIndex=showLoadingDialog(); + var loadIndex = showLoadingDialog(); addRoomConfig(field) .then(json => { layer.close(loadIndex) @@ -141,7 +155,7 @@ editArray.split(',').forEach(element => { array.push(element) }); - var loadIndex=showLoadingDialog(); + var loadIndex = showLoadingDialog(); setArrayRoomConfig(array, field) .then(json => { layer.close(loadIndex) @@ -170,6 +184,14 @@ type: 'time', range: true }); + form.on('switch(switchSync)', function (data) { + if (form.val('form-filter').syncDanmuForLive === 'on') { + $("[name='recordDanmu']").prop("disabled", true); + } else { + $("[name='recordDanmu']").prop("disabled", false); + } + form.render(); + }); function init() { getUserInfo(); if (roomId !== null) { @@ -202,13 +224,18 @@ 'recordDanmu': json.recordDanmu, 'recordDanmuDate': json.recordDanmuDate, 'recordLiveDate': json.recordLiveDate, + 'syncDanmuForLive': json.syncDanmuForLive, }; for (let i = 0; i < json.weeks.length; i++) { result[`week_${json.weeks[i]}`] = true; } form.val('form-filter', result); - + if (json.syncDanmuForLive) { + $("[name='recordDanmu']").prop("disabled", true); + } else { + $("[name='recordDanmu']").prop("disabled", false); + } $('#url').get(0).disabled = true; } }) diff --git a/Web/js/httpUtils.js b/Web/js/httpUtils.js index 3f7c0d3..dde458e 100644 --- a/Web/js/httpUtils.js +++ b/Web/js/httpUtils.js @@ -13,8 +13,8 @@ function get(url) { return error; }); } -function post(url, formData, isJSON) { - return sendPost(url,true,formData,isJSON) +function post(url, formData, isJSON) { + return sendPost(url, true, formData, isJSON) } function sendPost(url, isFormData, formData, isJSON) { var obj = {}; @@ -129,7 +129,7 @@ function setArrayRoomConfig(rooms, config) { return sendPost("/live/config/set/array", false, json, true) } function deleteArrayRoomConfig(rooms) { - return sendPost("/live/config/delete/array", false,rooms, true) + return sendPost("/live/config/delete/array", false, rooms, true) } function deleteAllRoomConfig() { return get("/live/config/delete/all") @@ -192,8 +192,8 @@ function startLiveDanmu(roomId) { function stopLiveDanmu(roomId) { return get("/live/danmu/stop?roomId=" + roomId) } -function getDanmu(roomId, videoId) { - return get("/live/danmu/get?roomId=" + roomId + "&videoId=" + videoId) +function getDanmu(roomId, videoId, page) { + return get("/live/danmu/get?roomId=" + roomId + "&videoId=" + videoId + "&page=" + page) } //----------------弹幕相关接口end //----------------用户相关接口 diff --git a/src/main/java/com/yutou/biliapi/bean/live/database/LiveConfigDatabaseBean.java b/src/main/java/com/yutou/biliapi/bean/live/database/LiveConfigDatabaseBean.java index 88f7cca..47e113b 100644 --- a/src/main/java/com/yutou/biliapi/bean/live/database/LiveConfigDatabaseBean.java +++ b/src/main/java/com/yutou/biliapi/bean/live/database/LiveConfigDatabaseBean.java @@ -34,6 +34,8 @@ public class LiveConfigDatabaseBean extends AbsDatabasesBean { private boolean isRecordLive; @JSONField(name = "recordDanmu") private boolean isRecordDanmu; + @JSONField(name = "syncDanmuForLive") + private boolean isSyncDanmuForLive; @JSONField(name = "keyword") private List keywordList; @JSONField(name = "weeks") diff --git a/src/main/java/com/yutou/biliapi/bean/live/database/LiveDanmuDatabaseBean.java b/src/main/java/com/yutou/biliapi/bean/live/database/LiveDanmuDatabaseBean.java index 9b469b9..66297b4 100644 --- a/src/main/java/com/yutou/biliapi/bean/live/database/LiveDanmuDatabaseBean.java +++ b/src/main/java/com/yutou/biliapi/bean/live/database/LiveDanmuDatabaseBean.java @@ -8,6 +8,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import java.math.BigInteger; +import java.util.Date; @EqualsAndHashCode(callSuper = true) @Data @@ -23,7 +24,7 @@ public class LiveDanmuDatabaseBean extends AbsDatabasesBean { @JSONField(name = "color") private String fontColor; @JSONField(name = "time") - private long time; + private Date time; @JSONField(name = "uid") private String uid; @JSONField(name = "uname") @@ -40,7 +41,7 @@ public class LiveDanmuDatabaseBean extends AbsDatabasesBean { model = danmu.getModel(); fontSize = danmu.getFontSize(); fontColor = danmu.getFontColor(); - time = danmu.getTime(); + time = new Date(danmu.getTime()); uid = danmu.getUid(); uname = danmu.getUname(); } @@ -52,7 +53,7 @@ public class LiveDanmuDatabaseBean extends AbsDatabasesBean { data.setModel(model); data.setFontSize(fontSize); data.setFontColor(fontColor); - data.setTime(time); + data.setTime(time.getTime()); return data; } } diff --git a/src/main/java/com/yutou/biliapi/databases/BiliLiveDatabase.java b/src/main/java/com/yutou/biliapi/databases/BiliLiveDatabase.java index 7af770e..d55fc56 100644 --- a/src/main/java/com/yutou/biliapi/databases/BiliLiveDatabase.java +++ b/src/main/java/com/yutou/biliapi/databases/BiliLiveDatabase.java @@ -207,9 +207,39 @@ public class BiliLiveDatabase extends SQLiteManager { return super.get(tableName, where, clazz); } + public List getOfTime(Long startTime, Long endTime, int page,int pageSize, Class clazz) { + String tableName = null; + StringBuilder sb = new StringBuilder(); + String where = null; + if (startTime != null) { + sb.append(" `sql_time` >= ").append("\"").append(startTime).append("\""); + } + if (endTime != null) { + if (!sb.isEmpty()) { + sb.append(" and "); + } + sb.append(" `sql_time` <= ").append("\"").append(endTime).append("\""); + } + sb.append("ORDER BY `sql_time` LIMIT ").append(page).append("*").append(pageSize).append(",").append(pageSize); + if (!sb.isEmpty()) { + where = sb.toString(); + } + for (AbsDatabasesBean bean : getDataBean()) { + if (bean.getClass() == clazz) { + tableName = bean.getTableName(); + break; + } + } + return super.get(tableName, where, clazz); + } + + @Override + public int getCount(String table) { + return super.getCount(table); + } + public LiveVideoDatabaseBean getVideo(String videoId) { for (LiveVideoDatabaseBean info : getLiveInfos()) { - System.out.println(videoId + " " + info.getSql_time().getTime()); if (videoId.trim().equals(String.valueOf(info.getSql_time().getTime()))) { return info; } @@ -241,8 +271,8 @@ public class BiliLiveDatabase extends SQLiteManager { } public static void main(String[] args) { - BiliLiveDatabase biliLiveDatabase = new BiliLiveDatabase(LiveRoomConfig.buildConfig("7688602")); - biliLiveDatabase.resetSQL(); + BiliLiveDatabase biliLiveDatabase = new BiliLiveDatabase(LiveRoomConfig.buildConfig("33989")); + // biliLiveDatabase.resetSQL(); biliLiveDatabase.resetData(); } diff --git a/src/main/java/com/yutou/biliapi/net/WebSocketManager.java b/src/main/java/com/yutou/biliapi/net/WebSocketClientManager.java similarity index 83% rename from src/main/java/com/yutou/biliapi/net/WebSocketManager.java rename to src/main/java/com/yutou/biliapi/net/WebSocketClientManager.java index 5da78ab..11d3f82 100644 --- a/src/main/java/com/yutou/biliapi/net/WebSocketManager.java +++ b/src/main/java/com/yutou/biliapi/net/WebSocketClientManager.java @@ -16,7 +16,6 @@ import com.yutou.biliapi.bean.websocket.WebSocketHeader; import com.yutou.biliapi.bean.websocket.live.WSData; import com.yutou.biliapi.databases.BiliBiliLoginDatabase; import com.yutou.biliapi.databases.BiliLiveDatabase; -import com.yutou.biliapi.utils.BiliUserUtils; import com.yutou.biliapi.utils.BytesUtils; import com.yutou.common.okhttp.HttpBody; import com.yutou.common.okhttp.HttpCallback; @@ -39,20 +38,20 @@ import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; -public class WebSocketManager { +public class WebSocketClientManager { ThreadPoolExecutor executor; - private static WebSocketManager instance; + private static WebSocketClientManager instance; Map roomMap; private final List userStopList = new ArrayList<>();//手动停止列表 - private WebSocketManager() { + private WebSocketClientManager() { roomMap = new HashMap<>(); executor = new ThreadPoolExecutor(2, 4, Long.MAX_VALUE, TimeUnit.SECONDS, new ArrayBlockingQueue(100)); } - public static WebSocketManager getInstance() { + public static WebSocketClientManager getInstance() { if (instance == null) { - instance = new WebSocketManager(); + instance = new WebSocketClientManager(); } return instance; } @@ -105,7 +104,7 @@ public class WebSocketManager { public DanmuTask(LiveRoomConfig config) { this.roomConfig = config; - WebSocketManager.getInstance().roomMap.put(roomConfig, this); + WebSocketClientManager.getInstance().roomMap.put(roomConfig, this); } @Override @@ -118,7 +117,7 @@ public class WebSocketManager { roomConfig.setRoomInfo(execute.body() != null ? execute.body().getData() : null); } } catch (IOException e) { - WebSocketManager.getInstance().roomMap.remove(roomConfig); + WebSocketClientManager.getInstance().roomMap.remove(roomConfig); throw new RuntimeException(e); } api.getLiveRoomDanmuInfo(String.valueOf(roomConfig.getRoomId())).enqueue(new HttpCallback() { @@ -132,7 +131,7 @@ public class WebSocketManager { roomConfig.setLiveInfo(response); client = new WebSocketClientTh(new URI(url), roomConfig); } catch (URISyntaxException e) { - WebSocketManager.getInstance().roomMap.remove(roomConfig); + WebSocketClientManager.getInstance().roomMap.remove(roomConfig); throw new RuntimeException(e); } } @@ -140,7 +139,7 @@ public class WebSocketManager { @Override public void onFailure(Throwable throwable) { - WebSocketManager.getInstance().roomMap.remove(roomConfig); + WebSocketClientManager.getInstance().roomMap.remove(roomConfig); Log.e(throwable); } }); @@ -152,10 +151,9 @@ public class WebSocketManager { } private static class WebSocketClientTh extends WebSocketClient { - private LiveRoomConfig roomConfig; - private HeartbeatTask heartbeatTask; + private final LiveRoomConfig roomConfig; + private final HeartbeatTask heartbeatTask; BiliLiveDatabase liveDatabase; - private boolean itTmp = true; public WebSocketClientTh(URI serverUri, LiveRoomConfig roomId) { super(serverUri); @@ -192,7 +190,7 @@ public class WebSocketManager { @Override public void onClose(int i, String s, boolean b) { Log.e("WebSocketClientTh.onClose", "i = " + i + ", s = " + s + ", b = " + b, roomConfig.getRoomId(), heartbeatTask.socket.isOpen()); - WebSocketManager.getInstance().roomMap.remove(roomConfig); + WebSocketClientManager.getInstance().roomMap.remove(roomConfig); liveDatabase.close(); heartbeatTask.cancel(); } @@ -201,7 +199,7 @@ public class WebSocketManager { public void onError(Exception e) { Log.i("WebSocketClientTh.onError", roomConfig.getRoomId()); Log.e(e); - WebSocketManager.getInstance().roomMap.remove(roomConfig); + WebSocketClientManager.getInstance().roomMap.remove(roomConfig); liveDatabase.close(); heartbeatTask.cancel(); } @@ -285,30 +283,25 @@ public class WebSocketManager { } LoginCookieDatabaseBean cookie = BiliBiliLoginDatabase.getInstance().getCookie(roomConfig.getLoginUid()); Log.d("cookie:", cookie, "RoomId:" + roomConfig); - String buvid = BiliUserUtils.getBuvid(cookie); - if (buvid != null) { - try { - json.put("roomid", new BigInteger(roomConfig.getRoomId())); - json.put("protover", 3); - json.put("buvid", buvid); - json.put("platform", "web"); - json.put("type", 2); - json.put("key", roomConfig.getLiveInfo().getToken()); - byte[] bytes = {0, 16, 0, 1, 0, 0, 0, 7, 0, 0, 0, 1}; - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + try { + json.put("roomid", new BigInteger(roomConfig.getRoomId())); + json.put("protover", 3); + json.put("platform", "web"); + json.put("type", 2); + json.put("key", roomConfig.getLiveInfo().getToken()); + byte[] bytes = {0, 16, 0, 1, 0, 0, 0, 7, 0, 0, 0, 1}; + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); // Log.i("bytes.length = " + bytes.length); - Log.i(json); - outputStream.write(BytesUtils.toLH(json.toString().length() + 16)); - outputStream.write(bytes); - outputStream.write(json.toJSONString().getBytes(StandardCharsets.UTF_8)); - outputStream.flush(); + Log.i(json); + outputStream.write(BytesUtils.toLH(json.toString().length() + 16)); + outputStream.write(bytes); + outputStream.write(json.toJSONString().getBytes(StandardCharsets.UTF_8)); + outputStream.flush(); // BytesUtils.printHex(outputStream.toByteArray()); - Log.i(socket.isOpen(), json.toString()); - socket.send(outputStream.toByteArray()); - - } catch (Exception e) { - Log.e(e); - } + Log.i(socket.isOpen(), json.toString()); + socket.send(outputStream.toByteArray()); + } catch (Exception e) { + Log.e(e); } diff --git a/src/main/java/com/yutou/bilibili/Controllers/LiveConfigController.java b/src/main/java/com/yutou/bilibili/Controllers/LiveConfigController.java index 8b33ffa..7424907 100644 --- a/src/main/java/com/yutou/bilibili/Controllers/LiveConfigController.java +++ b/src/main/java/com/yutou/bilibili/Controllers/LiveConfigController.java @@ -14,7 +14,6 @@ import com.yutou.bilibili.services.LiveConfigService; import com.yutou.bilibili.services.LiveLoginService; import com.yutou.bilibili.services.LiveUserService; import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletRequest; import org.springframework.core.io.FileSystemResource; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; @@ -154,6 +153,9 @@ public class LiveConfigController { if("on".equals(config.getString("recordLive"))){ bean.setRecordLive(true); } + if("on".equals(config.getString("syncDanmuForLive"))){ + bean.setSyncDanmuForLive(true); + } JSONArray jsonArray = jsonObject.getJSONArray("array"); List list = jsonArray.stream().map(roomId -> configService.addConfig(roomId.toString(), bean)).toList(); int countNull = list.stream().filter(Objects::isNull).toList().size(); diff --git a/src/main/java/com/yutou/bilibili/Controllers/LiveDanmuController.java b/src/main/java/com/yutou/bilibili/Controllers/LiveDanmuController.java index 36b905d..c668b9c 100644 --- a/src/main/java/com/yutou/bilibili/Controllers/LiveDanmuController.java +++ b/src/main/java/com/yutou/bilibili/Controllers/LiveDanmuController.java @@ -1,8 +1,6 @@ package com.yutou.bilibili.Controllers; import com.alibaba.fastjson2.JSONObject; -import com.yutou.biliapi.bean.live.LiveRoomConfig; -import com.yutou.biliapi.net.WebSocketManager; import com.yutou.bilibili.datas.ResultData; import com.yutou.bilibili.datas.ReturnCode; import com.yutou.bilibili.services.LiveDanmuService; @@ -44,7 +42,7 @@ public class LiveDanmuController { @ResponseBody @RequestMapping("/live/danmu/get") - public JSONObject getDanmu(String roomId, String videoId) { - return ResultData.success(service.getDanmu(roomId, videoId)); + public JSONObject getDanmu(String roomId, String videoId, int page) { + return ResultData.success(service.getDanmu(roomId, videoId, page)); } } diff --git a/src/main/java/com/yutou/bilibili/datas/web/LiveVideoDanmu.java b/src/main/java/com/yutou/bilibili/datas/web/LiveVideoDanmu.java index 79593df..e4568b7 100644 --- a/src/main/java/com/yutou/bilibili/datas/web/LiveVideoDanmu.java +++ b/src/main/java/com/yutou/bilibili/datas/web/LiveVideoDanmu.java @@ -11,7 +11,8 @@ public class LiveVideoDanmu { List danmu = new ArrayList<>(); List superChat = new ArrayList<>(); - + boolean isNextDanmu = false; + long danmuCount = 0; @Data public static class Addition { @@ -60,7 +61,7 @@ public class LiveVideoDanmu { this.backgroundBottomColor = bean.getBackgroundBottomColor(); this.userName = bean.getUserName(); this.userAvatar = bean.getUserAvatar(); - this.userNameColor=bean.getUserNameColor(); + this.userNameColor = bean.getUserNameColor(); } } } diff --git a/src/main/java/com/yutou/bilibili/services/LiveDanmuService.java b/src/main/java/com/yutou/bilibili/services/LiveDanmuService.java index 82dd7dd..ed7037d 100644 --- a/src/main/java/com/yutou/bilibili/services/LiveDanmuService.java +++ b/src/main/java/com/yutou/bilibili/services/LiveDanmuService.java @@ -10,44 +10,44 @@ 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.BiliLiveDatabase; -import com.yutou.biliapi.net.WebSocketManager; +import com.yutou.biliapi.net.WebSocketClientManager; import com.yutou.bilibili.Tools.AssTools; -import com.yutou.bilibili.Tools.DateFormatUtils; import com.yutou.bilibili.Tools.Tools; import com.yutou.bilibili.datas.web.LiveVideoDanmu; -import com.yutou.common.utils.FFmpegUtils; import com.yutou.common.utils.Log; import org.jetbrains.annotations.NotNull; import org.springframework.stereotype.Service; import java.io.File; -import java.math.BigInteger; -import java.util.ArrayList; import java.util.List; @Service public class LiveDanmuService { public void start(String roomId, boolean isUser) { - WebSocketManager.getInstance().addRoom(LiveRoomConfig.buildConfig(roomId), isUser); + WebSocketClientManager.getInstance().addRoom(LiveRoomConfig.buildConfig(roomId), isUser); + } + + public void start(LiveConfigDatabaseBean roomId, boolean isUser) { + WebSocketClientManager.getInstance().addRoom(LiveRoomConfig.buildConfig(roomId.getRoomId()), isUser); } public boolean check(String roomId) { LiveRoomConfig roomConfig = new LiveRoomConfig(); roomConfig.setRoomId(roomId); - return WebSocketManager.getInstance().checkRoom(roomConfig); + return WebSocketClientManager.getInstance().checkRoom(roomConfig); } public void stop(String roomId, boolean isUser) { - WebSocketManager.getInstance().stopRoom(roomId, isUser); + WebSocketClientManager.getInstance().stopRoom(roomId, isUser); } public JSONArray getLiveRoomList() { - return WebSocketManager.getInstance().getLiveRoomList(); + return WebSocketClientManager.getInstance().getLiveRoomList(); } public void clearUserList() { - WebSocketManager.getInstance().clearUserStopList(); + WebSocketClientManager.getInstance().clearUserStopList(); } public List getDanmuFileList(String roomId) { @@ -86,21 +86,33 @@ public class LiveDanmuService { return String.format("%d小时%d分钟%d秒", hours, minutes, finalRemainingSeconds); } - public LiveVideoDanmu getDanmu(String roomId, String videoId) { + public LiveVideoDanmu getDanmu(String roomId, String videoId, int page) { LiveVideoDanmu danmus = new LiveVideoDanmu(); BiliLiveDatabase liveDatabase = new BiliLiveDatabase(LiveRoomConfig.buildConfig(roomId)); LiveVideoDatabaseBean videoBean = liveDatabase.getVideo(videoId); if (videoBean == null) { return new LiveVideoDanmu(); } - long startTime = Long.parseLong(videoId); + long startTime = videoBean.getStartTime().getTime(); long endTime = videoBean.getStopTime() == null ? System.currentTimeMillis() : videoBean.getStopTime().getTime(); - List danmuList = liveDatabase.getOfTime(startTime, endTime, LiveDanmuDatabaseBean.class); List superChatList = liveDatabase.getOfTime(startTime, endTime, LiveSuperChatDatabaseBean.class); - for (LiveDanmuDatabaseBean bean : danmuList) { - LiveVideoDanmu.Danmu danmu = createDanmu(bean, startTime); - danmus.getDanmu().add(danmu); + + long count = liveDatabase.getCount(new LiveDanmuDatabaseBean().getTableName()); + int pageSize = 10000; + int pageCount = (int) Math.ceil((double) count / pageSize); + + List danmuList = liveDatabase.getOfTime(startTime, endTime, page, pageSize, LiveDanmuDatabaseBean.class) + .stream() + .map(item -> createDanmu(item, startTime)) + .filter(item-> item.getTime()>=0) + .toList(); + danmus.getDanmu().addAll(danmuList); + danmus.setDanmuCount(count); + if (page < pageCount) { + danmus.setNextDanmu(true); } + + for (LiveSuperChatDatabaseBean bean : superChatList) { LiveVideoDanmu.SuperChat superChat = new LiveVideoDanmu.SuperChat(startTime, bean); danmus.getSuperChat().add(superChat); @@ -117,7 +129,7 @@ public class LiveDanmuService { danmu.setText(bean.getDanmu()); danmu.setColor("#" + bean.getFontColor()); danmu.setFontSize(bean.getFontSize()); - danmu.setTime(bean.getTime() - startTime); + danmu.setTime(bean.getTime().getTime() - startTime); if (bean.getModel() < 4) { danmu.setBarrageType(LiveVideoDanmu.Danmu.DANMU_TYPE_SCROLL); } else if (bean.getModel() == 4) { diff --git a/src/main/java/com/yutou/bilibili/services/LiveVideoDownloadService.java b/src/main/java/com/yutou/bilibili/services/LiveVideoDownloadService.java index 08da3cb..fd2e995 100644 --- a/src/main/java/com/yutou/bilibili/services/LiveVideoDownloadService.java +++ b/src/main/java/com/yutou/bilibili/services/LiveVideoDownloadService.java @@ -18,11 +18,9 @@ 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.WebSignManager; +import com.yutou.biliapi.net.WebSocketClientManager; import com.yutou.bilibili.Tools.DateFormatUtils; import com.yutou.bilibili.Tools.FileServerUtils; -import com.yutou.bilibili.Tools.LiveInfoNfoTools; -import com.yutou.bilibili.Tools.ProcessUtils; import com.yutou.bilibili.datas.VideoFilePath; import com.yutou.bilibili.interfaces.DownloadInterface; import com.yutou.common.okhttp.HttpCallback; @@ -32,13 +30,14 @@ import com.yutou.common.utils.ConfigTools; import com.yutou.common.utils.FFmpegUtils; import com.yutou.common.utils.Log; import okhttp3.Headers; +import org.apache.commons.io.FileUtils; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import java.io.File; +import java.io.IOException; import java.util.*; import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -65,16 +64,16 @@ public class LiveVideoDownloadService { } public void start(LiveConfigDatabaseBean bean, boolean isUser) { - if (!isUser && userStopList.contains(bean.getRoomId().toString())) { + if (!isUser && userStopList.contains(bean.getRoomId())) { return; } if (isUser) { - userStopList.remove(bean.getRoomId().toString()); + userStopList.remove(bean.getRoomId()); } - if (videoRecord.check(bean.getRoomId().toString())) { + if (videoRecord.check(bean.getRoomId())) { return; } - BiliLiveNetApiManager.getInstance().getApi(bean.getRecordUid()).getRoomInfo(bean.getRoomId().toString()).enqueue(new HttpCallback() { + BiliLiveNetApiManager.getInstance().getApi(bean.getRecordUid()).getRoomInfo(bean.getRoomId()).enqueue(new HttpCallback() { @Override public void onResponse(Headers headers, int code, String status, LiveRoomInfo response, String rawResponse) { if (response.getLiveStatus() == 1) { @@ -178,20 +177,9 @@ public class LiveVideoDownloadService { config.setRoomInfo(roomInfo); config.setRootPath(bean.getRecordPath()); database = new BiliLiveDatabase(config); - try { - var keyframe = roomInfo.getKeyframe(); - if (!StringUtils.hasText(keyframe)) { - keyframe = roomInfo.getUserCover(); - } - HttpDownloadUtils.download(new HttpDownloadUtils.Builder().setUrl(keyframe) - .setPath(rootPath.getAbsolutePath()) - .setFileName("poster.jpg")); - } catch (Exception e) { - e.printStackTrace(); - } saveLiveInfo(roomInfo); api.getLiveRoomPlayInfo( - bean.getRoomId().toString(), + bean.getRoomId(), LiveProtocol.getAll(), LiveVideoFormat.getAll(), LiveVideoCodec.getAll(), @@ -285,7 +273,7 @@ public class LiveVideoDownloadService { // .withNotSymbolParam("-loglevel", "error") // .withNotSymbolParam("-progress", "-") // .withNotSymbolParam("-fflags", "+genpts") - .withNotSymbolParam("-threads", "8") +// .withNotSymbolParam("-threads", "8")//看bili-go也没有加这个,改成设置好了 // .withNotSymbolParam("-bufsize", "10M") .withNotSymbolParam("-f", "segment") .withNotSymbolParam("-segment_time", "60") @@ -301,7 +289,7 @@ public class LiveVideoDownloadService { if (ck != null) { // builder = builder.withParam("-cookies", cookie); } - FFmpegUtils command = builder.build(config.getRoomId(), ffmpegPath, url, savePath.replace(".m3u8","-%04d.ts")); + FFmpegUtils command = builder.build(config.getRoomId(), ffmpegPath, url, savePath.replace(".m3u8", "-%04d.ts")); Log.i(command.getCommandDecode()); try { command.start(new DownloadInterface() { @@ -316,6 +304,7 @@ public class LiveVideoDownloadService { VideoTask.this.onStart(); Log.i("启动录制:" + playInfo.getRoomId()); task = null; + cancel(); } }; @@ -333,11 +322,18 @@ public class LiveVideoDownloadService { if (task != null) { task.cancel(); task = null; + try { + FileUtils.deleteDirectory(rootPath); + } catch (IOException e) { + Log.i(rootPath.getAbsolutePath()); + Log.e(e); + } } if (videoDatabaseBean != null) { videoDatabaseBean.setStopTime(new Date()); database.addLiveInfo(videoDatabaseBean); } + stopRecordDanmu(); } }); @@ -353,8 +349,21 @@ public class LiveVideoDownloadService { videoDatabaseBean.setRoomInfoJson(JSONObject.toJSONString(roomInfo)); videoDatabaseBean.setStartTime(new Date()); database.addLiveInfo(videoDatabaseBean); + recordDanmu(); // LiveInfoNfoTools.saveLiveInfoNfo(roomInfo, rootPath.getAbsolutePath(), new File(savePath).getName().replace(".flv", ".nfo")); + } + //录制弹幕 + private void recordDanmu() { + if (bean.isSyncDanmuForLive() && !WebSocketClientManager.getInstance().checkRoom(LiveRoomConfig.buildConfig(bean.getRoomId()))) { + WebSocketClientManager.getInstance().addRoom(LiveRoomConfig.buildConfig(bean.getRoomId()), true); + } + } + + private void stopRecordDanmu() { + if (bean.isSyncDanmuForLive() && WebSocketClientManager.getInstance().checkRoom(LiveRoomConfig.buildConfig(bean.getRoomId()))) { + WebSocketClientManager.getInstance().stopRoom(bean.getRoomId(), false); + } } } diff --git a/src/main/java/com/yutou/bilibili/services/SystemService.java b/src/main/java/com/yutou/bilibili/services/SystemService.java index 9458013..5bd82fe 100644 --- a/src/main/java/com/yutou/bilibili/services/SystemService.java +++ b/src/main/java/com/yutou/bilibili/services/SystemService.java @@ -54,12 +54,20 @@ public class SystemService { } for (LiveConfigDatabaseBean bean : list) { try { - if (bean.isRecordDanmu() && bean.checkRecordDanmuTime()) { + // 如果bean需要录制弹幕,并且检查录制弹幕时间,并且不需要同步直播弹幕,则录制弹幕 + if (bean.isRecordDanmu() && bean.checkRecordDanmuTime() && !bean.isSyncDanmuForLive()) { recordDanmu(bean); - } else if (!bean.checkRecordDanmuTime()) { + } else if (!bean.checkRecordDanmuTime() && !bean.isSyncDanmuForLive()) { + // 如果不在录制弹幕时间,并且不需要同步直播弹幕,则停止录制弹幕 stopRecordDanmu(bean); } + // 如果bean需要录制直播,并且检查录制直播时间 if (bean.isRecordLive() && bean.checkRecordLiveTime()) { + // 如果需要同步直播弹幕,则录制弹幕 + if (bean.isSyncDanmuForLive()) { + recordDanmu(bean); + } + // 录制视频 recordVideo(bean); } } catch (Exception e) { @@ -83,7 +91,7 @@ public class SystemService { // 录制弹幕 private void recordDanmu(LiveConfigDatabaseBean bean) { - danmuService.start(bean.getRoomId().toString(), false); + danmuService.start(bean, false); } // 录制视频