diff --git a/Web/html/body/video.html b/Web/html/body/video.html index 5d1b3da..1847525 100644 --- a/Web/html/body/video.html +++ b/Web/html/body/video.html @@ -250,7 +250,7 @@ }); new Chart($('#giftChart').get(0), { - type: 'bar', + type: 'pie', data: { labels: lables, datasets: [{ diff --git a/Web/index.html b/Web/index.html index 93fc06b..6a0c6a8 100644 --- a/Web/index.html +++ b/Web/index.html @@ -59,7 +59,7 @@
-
+
{{= item.title}}

开播时长:{{= item.liveTime}}

@@ -194,6 +194,13 @@ }); } setTimeout(() => { + // data.data.forEach(item =>{ + // if(document.getElementById(item.data)!==null){ + // document.getElementById(item.data).innerHTML=item.message; + // } + + + // }) initFollowStatus(true) }, 1000); diff --git a/src/main/java/com/yutou/BilibiliApplication.java b/src/main/java/com/yutou/BilibiliApplication.java index 2895946..504ca95 100644 --- a/src/main/java/com/yutou/BilibiliApplication.java +++ b/src/main/java/com/yutou/BilibiliApplication.java @@ -13,10 +13,10 @@ public class BilibiliApplication { HttpLoggingInterceptor.setLog(false); SpringApplication.run(BilibiliApplication.class, args); } - //TODO 优化 1 手动中断录制后,没有时间戳问题需要解决,看是提示转码还是有什么其他解决方案 + //TODO 优化 1 手动中断录制后,没有时间戳问题需要解决,看是提示转码还是有什么其他解决方案 | 改成了通过q来退出 //TODO 优化 2 创建nfo文件看看要不要改成录制后生成,或者触发打包指令再生成 //TODO 优化 3 录制完成前应该也允许查看礼物信息和SC以及弹幕,未停止录制改成从开始时间到当前时间的弹幕和礼物信息,已停止录制则询问是否转码 - //TODO 优化 4 视频页面礼物的图标,有数据计算错误以及单项猛增的话导致其他项目无法查看的问题(可参考泛式死亡笔记录播) + //TODO 优化 4 视频页面礼物的图标,有数据计算错误以及单项猛增的话导致其他项目无法查看的问题(可参考泛式死亡笔记录播) | 换成饼状图 //TODO 修复 1 开播时有概率连续触发创建nfo和记录视频到数据宽度问题. //TODO 测试 1 需要测试网络中断下,弹幕重连机制 //TODO 测试 2 在导出jar包后再测试完整的录制功能 diff --git a/src/main/java/com/yutou/biliapi/net/WebSocketManager.java b/src/main/java/com/yutou/biliapi/net/WebSocketManager.java index 021502b..6a0253c 100644 --- a/src/main/java/com/yutou/biliapi/net/WebSocketManager.java +++ b/src/main/java/com/yutou/biliapi/net/WebSocketManager.java @@ -18,7 +18,6 @@ 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.bilibili.Tools.Tools; import com.yutou.common.okhttp.HttpBody; import com.yutou.common.okhttp.HttpCallback; import com.yutou.common.utils.ConfigTools; @@ -119,6 +118,7 @@ public class WebSocketManager { roomConfig.setRoomInfo(execute.body() != null ? execute.body().getData() : null); } } catch (IOException e) { + WebSocketManager.getInstance().roomMap.remove(roomConfig); throw new RuntimeException(e); } api.getLiveRoomDanmuInfo(String.valueOf(roomConfig.getRoomId())).enqueue(new HttpCallback() { @@ -132,6 +132,7 @@ public class WebSocketManager { roomConfig.setLiveInfo(response); client = new WebSocketClientTh(new URI(url), roomConfig); } catch (URISyntaxException e) { + WebSocketManager.getInstance().roomMap.remove(roomConfig); throw new RuntimeException(e); } } @@ -139,6 +140,7 @@ public class WebSocketManager { @Override public void onFailure(Throwable throwable) { + WebSocketManager.getInstance().roomMap.remove(roomConfig); Log.e(throwable); } }); diff --git a/src/main/java/com/yutou/bilibili/Tools/FFmpegUtils.java b/src/main/java/com/yutou/bilibili/Tools/FFmpegUtils.java deleted file mode 100644 index e64a0a2..0000000 --- a/src/main/java/com/yutou/bilibili/Tools/FFmpegUtils.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.yutou.bilibili.Tools; - -import com.yutou.common.utils.AppTools; -import com.yutou.common.utils.Log; - -import java.io.File; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; - -public class FFmpegUtils { - private static final List nowFFmpegList = new ArrayList<>(); - - public static int add(String ffmpeg, File file, File out) { - if (nowFFmpegList.contains(file)) { - return 2; - } - if (file.getName().contains("ffmpeg")) { - return 1; - } else { - startFFmpeg(ffmpeg, file, out); - } - - return 0; - } - - private synchronized static void startFFmpeg(String ffmpeg, File file, File out) { - if (nowFFmpegList.contains(file)) { - return; - } - nowFFmpegList.add(file); - new Thread(new Runnable() { - @Override - public void run() { - try { - if (!out.exists()) { - out.mkdirs(); - } - String exec = String.format( - "%s -i \"%s\" -c:v copy -y \"%s\" ", - ffmpeg, - file.getAbsolutePath(), - out.getAbsolutePath() + File.separator + file.getName()); - Log.i(exec); - Process process = ProcessUtils.exec(ffmpeg, "-i", file.getAbsolutePath(), "-c:v", "copy", "-y", out.getAbsolutePath() + File.separator + file.getName()); - InputStream inputStream = process.getErrorStream(); - byte[] bytes = new byte[1024]; - while (inputStream.read(bytes) > -1) { - } - inputStream.close(); - AppTools.copyFileToName(out.getAbsolutePath() + File.separator + file.getName(), file.getParent() + File.separator, file.getName().replace(".mp4", "_ffmpeg.mp4"), true); - file.delete(); - new File(out.getAbsolutePath() + File.separator + file.getName()).delete(); - } catch (Exception e) { - Log.e(e); - } - nowFFmpegList.remove(file); - } - }).start(); - } - - public static void main(String[] args) { - File file = new File("D:\\ieda\\bilibili\\live\\2021-03-20\\[2021-03-20 003537]1064046.mp4"); - int i = -1; - while (i != 1) { - i = add("D:\\ffmpeg-4.3.1-2020-11-19-full_build\\bin\\ffmpeg.exe", file.getAbsoluteFile(), new File("ffmpeg_out")); - Log.i(i); - try { - Thread.sleep(300); - } catch (InterruptedException e) { - Log.e(e); - } - } - Log.i("转码完成"); - } -} diff --git a/src/main/java/com/yutou/bilibili/services/LiveDanmuService.java b/src/main/java/com/yutou/bilibili/services/LiveDanmuService.java index 023dca5..e6a6c64 100644 --- a/src/main/java/com/yutou/bilibili/services/LiveDanmuService.java +++ b/src/main/java/com/yutou/bilibili/services/LiveDanmuService.java @@ -97,6 +97,10 @@ public class LiveDanmuService { long videoTime = FFmpegUtils.getVideoTime(videoFile); long startTime = Long.parseLong(videoId); long endTime = Long.parseLong(videoId) + videoTime; + // videoTime = 0; + if (videoTime == 0) { + endTime = System.currentTimeMillis(); + } List danmuList = liveDatabase.getOfTime(DateFormatUtils.getInstance().format(startTime), DateFormatUtils.getInstance().format(endTime), LiveDanmuDatabaseBean.class); List superChatList = liveDatabase.getOfTime(DateFormatUtils.getInstance().format(startTime), DateFormatUtils.getInstance().format(endTime), LiveSuperChatDatabaseBean.class); for (LiveDanmuDatabaseBean bean : danmuList) { @@ -104,7 +108,7 @@ public class LiveDanmuService { danmus.getDanmu().add(danmu); } for (LiveSuperChatDatabaseBean bean : superChatList) { - LiveVideoDanmu.SuperChat superChat = new LiveVideoDanmu.SuperChat(startTime,bean); + LiveVideoDanmu.SuperChat superChat = new LiveVideoDanmu.SuperChat(startTime, bean); danmus.getSuperChat().add(superChat); } diff --git a/src/main/java/com/yutou/bilibili/services/LiveVideoDownloadService.java b/src/main/java/com/yutou/bilibili/services/LiveVideoDownloadService.java index f77f83c..14df37c 100644 --- a/src/main/java/com/yutou/bilibili/services/LiveVideoDownloadService.java +++ b/src/main/java/com/yutou/bilibili/services/LiveVideoDownloadService.java @@ -257,6 +257,7 @@ public class LiveVideoDownloadService { // .withNotSymbolParam("-progress", "-") .withNotSymbolParam("-threads", "8") .withNotSymbolParam("-c:v", "copy") + .withNotSymbolParam("-fflags","+genpts") .withNotSymbolParam("-y", ""); if (ck != null) { builder = builder.withParam("-cookies", cookie); @@ -299,7 +300,7 @@ public class LiveVideoDownloadService { videoDatabaseBean.setRoomInfoJson(JSONObject.toJSONString(roomInfo)); videoDatabaseBean.setStartTime(new Date()); database.addLiveInfo(videoDatabaseBean); - LiveInfoNfoTools.saveLiveInfoNfo(roomInfo, rootPath.getAbsolutePath(), new File(savePath).getName().replace(".flv", ".nfo")); + // LiveInfoNfoTools.saveLiveInfoNfo(roomInfo, rootPath.getAbsolutePath(), new File(savePath).getName().replace(".flv", ".nfo")); } } diff --git a/src/main/java/com/yutou/common/utils/FFmpegUtils.java b/src/main/java/com/yutou/common/utils/FFmpegUtils.java index 225c5ae..6bac42d 100644 --- a/src/main/java/com/yutou/common/utils/FFmpegUtils.java +++ b/src/main/java/com/yutou/common/utils/FFmpegUtils.java @@ -12,14 +12,12 @@ import java.nio.charset.StandardCharsets; import java.util.*; public class FFmpegUtils extends AbsVideoRecord { - private static final Map pidMap = new HashMap<>(); + private static final Map pidMap = new HashMap<>(); @Getter private String command; @Getter private String outputFilePath; private String uid; - InputStream inputStream; - OutputStream outputStream; public FFmpegUtils() { } @@ -33,7 +31,10 @@ public class FFmpegUtils extends AbsVideoRecord { @Override public boolean check(String roomId) { try { - return ProcessUtils.isProcessRunning(pidMap.get(roomId)); + if(!pidMap.containsKey(roomId)){ + return false; + } + return ProcessUtils.isProcessRunning(pidMap.get(roomId).pid); } catch (Exception e) { Log.e(e); throw new RuntimeException(e); @@ -43,8 +44,11 @@ public class FFmpegUtils extends AbsVideoRecord { @Override public void kill(String roomId) { try { - ProcessUtils.killProcess(pidMap.get(roomId)); - pidMap.remove(roomId); + // ProcessUtils.killProcess(pidMap.get(roomId).pid); + Task utils = pidMap.get(roomId); + if(utils != null) { + utils.kill(); + } } catch (Exception e) { Log.e(e); throw new RuntimeException(e); @@ -53,9 +57,9 @@ public class FFmpegUtils extends AbsVideoRecord { @Override public void killAll() { - for (Long pid : pidMap.values()) { + for (Task pid : pidMap.values()) { try { - ProcessUtils.killProcess(pid); + pid.kill(); } catch (Exception e) { Log.e(e); } @@ -137,47 +141,12 @@ public class FFmpegUtils extends AbsVideoRecord { @Override public void start(DownloadInterface downloadInterface) { - new Thread(() -> { - try { - if (check(uid)) { - kill(uid); - } - Process process = ProcessUtils.exec(command.split(" ")); - long pid = process.toHandle().pid(); - Log.i("进程id " + pid); - inputStream = process.getErrorStream(); - outputStream = process.getOutputStream(); - byte[] bytes = new byte[2048]; - if (downloadInterface != null) { - downloadInterface.onDownloadStart(); - } - pidMap.put(uid, pid); - while (inputStream.read(bytes) > -1) { - if (downloadInterface != null) { - downloadInterface.onDownloading(0, 0); - } - } - pidMap.remove(uid); - //获取视频时长:ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 input.mp4 - //获取到结果:5372.432000 - if (downloadInterface != null) { - Log.i("触发下载完成",command); - downloadInterface.onDownload(null); - } - } catch (Exception e) { - throw new RuntimeException(e); - } - }).start(); + new Task(downloadInterface).start(); } @Override public void stop() { - try { - outputStream.write("q".getBytes()); - outputStream.flush(); - } catch (IOException e) { - throw new RuntimeException(e); - } + pidMap.get(uid).kill(); } /** @@ -206,4 +175,63 @@ public class FFmpegUtils extends AbsVideoRecord { throw new RuntimeException(e); } } + + private class Task extends Thread { + private long pid; + InputStream inputStream; + OutputStream outputStream; + DownloadInterface downloadInterface; + + public Task(DownloadInterface downloadInterface) { + this.downloadInterface = downloadInterface; + } + + @Override + public void run() { + super.run(); + try { + if (check(uid)) { + kill(); + } + Process process = ProcessUtils.exec(command.split(" ")); + pid = process.toHandle().pid(); + Log.i("进程id " + pid); + inputStream = process.getErrorStream(); + outputStream = process.getOutputStream(); + byte[] bytes = new byte[2048]; + if (downloadInterface != null) { + downloadInterface.onDownloadStart(); + } + pidMap.put(uid, this); + while (inputStream.read(bytes) > -1) { + if (downloadInterface != null) { + downloadInterface.onDownloading(0, 0); + } + } + pidMap.remove(uid); + //获取视频时长:ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 input.mp4 + //获取到结果:5372.432000 + if (downloadInterface != null) { + Log.i("触发下载完成", command); + downloadInterface.onDownload(null); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public void kill() { + try { + outputStream.write("q".getBytes()); + outputStream.flush(); + Thread.sleep(1000); + if (check(uid)) { + ProcessUtils.killProcess(pid); + } + pidMap.remove(uid); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } }