新增弹幕转ass工具(未上线至网页)

修改获取直播状态的方法
新增主播uid字段
This commit is contained in:
Yutousama 2022-04-24 20:57:46 +08:00
parent 8dff5bf7bf
commit a1382ff7be
18 changed files with 662 additions and 194 deletions

View File

@ -156,7 +156,7 @@
, {field: "right", width: 200, toolbar: '#listTools'}
]]
, done: function (res, curr, count) {
let index=layer.load()
let index = layer.load()
$('#htitle').on('click', function () {
var that = this;
layer.tips('当名字变成绿色则代表后台正在统计中,为黑色则代表未统计,如果需要统计请打开统计开关后刷新查看结果', that, {
@ -196,25 +196,27 @@
$.post('/upinfo/get/liveInfo.do', function (json) {
if (json.code === 0) {
$('#online').text("当前正在直播:" + json.data.online)
for (let i in json.data.info) {
console.log('input[name="liveCheckbox' + json.data.info[i].roomid + '"]')
$('input[name="liveCheckbox' + json.data.info[i].roomid + '"]').prop('checked', true);
}
for (let i in json.data.live) {
$('#' + json.data.live[i].roomid).css('color', '#8FE18F')
console.log('绿了:'+json.data.live[i].roomid)
console.log('input[name="liveCheckbox' + json.data.live[i].roomid + '"]')
$('input[name="liveCheckbox' + json.data.live[i].roomid + '"]').prop('checked', true);
}
for (let i in json.data.info) {
if (json.data.info[i].listen === 1) {
$('#' + json.data.info[i].roomid).css('color', '#8FE18F')
console.log('绿了:' + json.data.info[i].roomid)
}
}
$.post('/user/get/test.do',function (json) {
$.post('/user/get/test.do', function (json) {
console.log(json.data.power)
if(json.data.power.indexOf(-1)===-1&&json.data.power.indexOf(4)===-1){
$('input[type="checkbox"]').prop('disabled',true)
if (json.data.power.indexOf(-1) === -1 && json.data.power.indexOf(4) === -1) {
$('input[type="checkbox"]').prop('disabled', true)
}
layer.close(index);
form.render();
})
}else{
} else {
layer.msg("close")
layer.close();
}
@ -254,7 +256,7 @@
title: '请输入房间号或直播地址(直播地址请勿包含参数 如http://live.bilibili.com/110?abcd)',
area: ['350px', '30px'] //自定义文本域宽高
}, function (value, index, elem) {
let dialogIndex=layer.load();
let dialogIndex = layer.load();
queryUpInfo(obj.data.roomid, function (udata) {
udata.url = value;
udata.offlinelistening = udata.offlinelistening ? 1 : 0;
@ -263,7 +265,7 @@
console.log(udata)
$.post("/upinfo/update.do", udata, function (json) {
layer.close(dialogIndex);
layer.msg(json.msg,function () {
layer.msg(json.msg, function () {
window.location.reload();
})
layer.close(index)

View File

@ -30,16 +30,16 @@ public class UpInfoController {
@RequestMapping("/upinfo/get/list.do")
@ResponseBody
public JSONObject upInfoList(HttpServletRequest request) {
String token= AppTools.getLoginToken(request);
UUser user= userService.getUserToToken(token);
String token = AppTools.getLoginToken(request);
UUser user = userService.getUserToToken(token);
JSONObject json = new JSONObject();
if(user==null){
json.put("code",-1);
json.put("msg","未登录");
json.put("data","[]");
if (user == null) {
json.put("code", -1);
json.put("msg", "未登录");
json.put("data", "[]");
return json;
}
List<BilibiliUpInfo> upDataList =service.getUpInfo(user.getId(),user.getPower());
List<BilibiliUpInfo> upDataList = service.getUpInfo(user.getId(), user.getPower());
com.yutou.bilibili.Tools.Log.i("UP用户数:" + upDataList.size());
json.put("code", 0);
json.put("data", JSONArray.toJSON(upDataList));
@ -73,7 +73,7 @@ public class UpInfoController {
@RequestMapping("/upinfo/set/update.do")
public JSONObject update(BilibiliUpInfo upData) {
JSONObject json = new JSONObject();
com.yutou.bilibili.Tools.Log.i("old data ="+upData);
com.yutou.bilibili.Tools.Log.i("old data =" + upData);
BilibiliUpInfo old = service.queryUp(upData);
if (!old.getUrl().equals(upData.getUrl())) {
upData = BiliTools.checkout(upData);
@ -83,7 +83,7 @@ public class UpInfoController {
upData.setOfflinelistening(0);
}
}
com.yutou.bilibili.Tools.Log.i("save data = "+upData);
com.yutou.bilibili.Tools.Log.i("save data = " + upData);
boolean flag = service.updateUpInfo(upData);
if (flag) {
LiveController.getInstance().updateUpInfo(upData);
@ -127,20 +127,21 @@ public class UpInfoController {
JSONObject data = new JSONObject();
JSONArray info = new JSONArray();
JSONArray liveArray = new JSONArray();
int online=0;
int online = 0;
JSONObject infoByUid = LiveUtils.getStatusInfoByUid(list);
JSONObject infoData = infoByUid.getJSONObject("data");
for (BilibiliUpInfo up : list) {
if (LiveUtils.isLivePlayer(up.getRoomid())) {
JSONObject user = infoData.getJSONObject(up.getMid() + "");
up.setLive(user.getInteger("live_status"));
if (up.checkLiveStatus() == 1) {
online++;
if(LiveUtils.liveContains(up)==null){
up.setLive(0);
}else{
up.setLive(1);
}
info.add(JSON.toJSON(up));
}
JSONObject item= (JSONObject) JSON.toJSON(up);
item.put("listen",Live.lives.get(up.getRoomid())!=null);
info.add(JSON.toJSON(up));
}
for (Live live : Live.lives.values()) {
if(live.geData().getLive()==1){
if (live.geData().getLive() == 1) {
liveArray.add(JSON.toJSON(live.geData()));
}
}

View File

@ -13,13 +13,14 @@ public class DanmuData {
private long time;
private String uCode;
private String danmu;
private int uid;
private long uid;
private String uname;
public Date getTimeDate(){
public Date getTimeDate() {
return new Date(time);
}
public String getFontColorHex(){
public String getFontColorHex() {
return Integer.toHexString(fontColor);
}
}

View File

@ -132,14 +132,12 @@ public class Live implements ApplicationContextAware {
*/
private void start() throws Exception {
run = true;
if (LiveUtils.isLivePlayer(roomId)) {
upData.setLive(-1);
}
String url = LiveUtils.getLiveUrl(roomId);
if (url == null) {
stop();
return;
}
upData.checkLiveStatus();
startTime = new Date();
HashMap<String, String> header = new HashMap<>();
header.put("Sec-WebSocket-Extensions", "permessage-deflate; client_max_window_bits");
@ -325,7 +323,7 @@ public class Live implements ApplicationContextAware {
}
public void checkLive() {
boolean isLive = LiveUtils.isLivePlayer(roomId);
boolean isLive = upData.checkLiveStatus() == 1;
if (SaveLive.getInstance().checkLive(roomId)) {
return;
}
@ -489,19 +487,17 @@ public class Live implements ApplicationContextAware {
service.addLiveData(liveData);
break;
case "LIVE"://开始直播,不过有在心跳包上做检测了所以也无所谓
if (upData.getLive() == 1) {
break;
}
upData.setLive(1);
JSONObject liveInfo = LiveUtils.getLiveInfo(roomId);
JSONObject liveInfo = LiveUtils.getLiveInfo(upData);
if (liveInfo == null) {
break;
}
upData.setLive(liveInfo.getInteger("live_status"));
LiveInfo info = new LiveInfo();
info.setTitle(liveInfo.getJSONObject("data").getJSONObject("room_info").getString("title"));
info.setKeyframe(liveInfo.getJSONObject("data").getJSONObject("room_info").getString("keyframe"));
info.setRoomId(liveInfo.getJSONObject("data").getJSONObject("room_info").getInteger("room_id"));
info.setShortId(liveInfo.getJSONObject("data").getJSONObject("room_info").getInteger("short_id"));
info.setTitle(liveInfo.getString("title"));
info.setKeyframe(liveInfo.getString("keyframe"));
info.setRoomId(liveInfo.getInteger("room_id"));
info.setShortId(liveInfo.getInteger("short_id"));
info.setInfo(liveInfo);
setLiveInfo(info);
StringBuilder builder = new StringBuilder();
@ -520,8 +516,8 @@ public class Live implements ApplicationContextAware {
break;
case "WATCHED_CHANGE"://人气值
try {
Live.this.info.setPopular(Integer.getInteger(json.getJSONObject("data").getString("text_small")));
}catch (Exception ignored){
Live.this.info.setPopular(Integer.getInteger(json.getJSONObject("data").getString("text_small")));
} catch (Exception ignored) {
}
break;
case "SUPER_CHAT_MESSAGE_JPN":
@ -624,7 +620,7 @@ public class Live implements ApplicationContextAware {
}
updateUpInfo();
if (upData.getOfflinelistening() != 1) {
if (!LiveUtils.isLivePlayer(upData.getRoomid())) {
if (upData.getLive() == 0) {
stop();
}
}

View File

@ -8,6 +8,7 @@ import com.alibaba.fastjson.JSONObject;
import com.yutou.bilibili.BiliBili.Services.IBiliBiliLiveService;
import com.yutou.bilibili.BiliBili.Tools.SaveLive;
import com.yutou.bilibili.Tools.AppTools;
import com.yutou.bilibili.Tools.HttpTools;
import com.yutou.bilibili.Tools.Log;
import com.yutou.bilibili.Tools.RedisTools;
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliUpInfo;
@ -348,11 +349,26 @@ public class LiveUtils {
return null;
}
public static JSONObject getLiveInfo(int roomId) {
return http_get("https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByRoom?room_id=" + roomId + "&protocol=0,1&format=0,1,2&codec=0,1&qn=10000&platform=web&ptype=8");
public static long getMid(int roomId) {
JSONObject http_get = http_get("http://api.live.bilibili.com/room/v1/Room/room_init?id=" + roomId);
if (http_get == null) {
return -1;
}
if (http_get.getInteger("code") == 0) {
return http_get.getJSONObject("data").getLong("uid");
}
return -1;
}
public static JSONObject getLiveRoomInfo(int roomId){
String url="https://api.live.bilibili.com/xlive/web-room/v2/index/getRoomPlayInfo?room_id="+ roomId + "&protocol=0,1&format=0,1,2&codec=0,1&qn=10000&platform=web&ptype=8";
public static JSONObject getLiveInfo(BilibiliUpInfo info) {
List<BilibiliUpInfo> list = new ArrayList<>();
list.add(info);
JSONObject infoByUid = getStatusInfoByUid(list);
return infoByUid.getJSONObject("data").getJSONObject(info.getMid() + "");
}
public static JSONObject getLiveRoomInfo(int roomId) {
String url = "https://api.live.bilibili.com/xlive/web-room/v2/index/getRoomPlayInfo?room_id=" + roomId + "&protocol=0,1&format=0,1,2&codec=0,1&qn=10000&platform=web&ptype=8";
return http_get(url);
}
@ -360,42 +376,37 @@ public class LiveUtils {
return liveStateMap.getOrDefault(roomId, false);
}
public static void reloadLiveState(int roomId) {
JSONObject json = getLiveRoomInfo(roomId);
if (json != null) {
try {
liveStateMap.put(roomId, json.getJSONObject("data").getInteger("live_status") == 1);
} catch (Exception e) {
Log.i("live state = "+json);
public static JSONObject getStatusInfoByUid(List<BilibiliUpInfo> list) {
JSONArray userId = new JSONArray();
for (BilibiliUpInfo info : list) {
userId.add(info.getMid());
}
JSONObject json=new JSONObject();
json.put("uids",userId);
return JSONObject.parseObject(HttpTools.post("https://api.live.bilibili.com/room/v1/Room/get_status_info_by_uids", json.toJSONString().getBytes(StandardCharsets.UTF_8)));
}
public static void reloadLiveState(List<BilibiliUpInfo> list) {
JSONObject json = getStatusInfoByUid(list);
try {
if (json.getInteger("code") == 0) {
JSONObject data = json.getJSONObject("data");
for (BilibiliUpInfo info : list) {
if (data.containsKey(info.getMid() + "")) {
liveStateMap.put(info.getRoomid(), data.getJSONObject(info.getMid()+"").getInteger("live_status") == 1);
}
}
}
} catch (Exception e) {
Log.i("live state = " + json);
}
}
public static String getLiveTitle(int roomId) {
JSONObject json = getLiveInfo(roomId);
if (json != null) {
return json.getJSONObject("data").getJSONObject("room_info").getString("title");
}
return null;
}
public static boolean isLivePlayer(int roomId) {
return getLiveState(roomId);
return getLiveState(roomId);
}
private static void checkLiveSave(int roomId) {
BilibiliUpInfo upData = new BilibiliUpInfo();
upData.setRoomid(roomId);
Live live = liveContains(upData);
if (live == null) {
live = new Live();
live.add(roomId, !StringUtils.isEmpty(AppTools.readFile(new File("cookies.json"))));
}
if (!SaveLive.getInstance().checkLive(roomId)) {
SaveLive.getInstance().addLive(roomId);
}
}
public static class LiveGiftConfig {
@Resource
@ -428,8 +439,12 @@ public class LiveUtils {
}
public static void main(String[] args) {
LiveUtils.reloadLiveState(22047448);
System.out.println(LiveUtils.getLiveState(22047448));
List<BilibiliUpInfo> list=new ArrayList<>();
BilibiliUpInfo info=new BilibiliUpInfo();
info.setMid(402417817L);
list.add(info);
JSONObject infoByUid = getStatusInfoByUid(list);
System.out.println(infoByUid);
}
}

View File

@ -31,11 +31,10 @@ public class BiliTools {
com.yutou.bilibili.Tools.Log.i(json);
String roomId = json.getJSONObject("data").getJSONObject("room_info").getInteger("room_id") + "";
String name = json.getJSONObject("data").getJSONObject("anchor_info").getJSONObject("base_info").getString("uname");
com.yutou.bilibili.Tools.Log.i(roomId);
com.yutou.bilibili.Tools.Log.i(name);
upData.setRoomid(Integer.parseInt(roomId));
upData.setName(name);
upData.setUrl(url);
upData.setMid(LiveUtils.getMid(upData.getRoomid()));
return upData;
}
}

View File

@ -20,7 +20,6 @@ public class SaveLive {
private final Map<Integer, Timer> heartbeats = new HashMap<>();
public static void main(String[] args) {
SaveLive.getInstance().addLive(3715397);
}
private SaveLive() {
@ -34,7 +33,13 @@ public class SaveLive {
}
public void addLive(Live live) {
addLive(live.geData().getRoomid());
if (saveList.contains(live.getInfo().getRoomid() + "")) {
return;
}
if (live.geData().checkLiveStatus() == 0) {
return;
}
start(live.getInfo().getRoomid());
}
public void startLive(int roomId) {
@ -42,15 +47,6 @@ public class SaveLive {
saveList.add(roomId + "");
}
public void addLive(int roomId) {
if (saveList.contains(roomId + "")) {
return;
}
if (!LiveUtils.isLivePlayer(roomId)) {
return;
}
start(roomId);
}
public boolean checkLive(int roomId) {
return saveList.contains(roomId + "");
@ -120,9 +116,9 @@ public class SaveLive {
super.run();
String url = getLiveUrl(roomId);
try {
if(AppData.LIVE_SAVE_FFMPEG){
if (AppData.LIVE_SAVE_FFMPEG) {
ffmpegDownload(url);
}else {
} else {
httpDownload(url);
}
} catch (Exception e) {
@ -138,7 +134,7 @@ public class SaveLive {
private void ffmpegDownload(String url) throws Exception {
liveFile = new File(String.format("%slive%s%s%s[%s]%d.mp4",
ConfigTools.load(ConfigTools.CONFIG,"liveSavePath"),
ConfigTools.load(ConfigTools.CONFIG, "liveSavePath"),
File.separator,
AppTools.getToDayTime(),
File.separator,
@ -158,16 +154,16 @@ public class SaveLive {
""
);
System.out.println(exec);
boolean isPrint=false;
Process process=AppTools.exec(exec);
boolean isPrint = false;
Process process = AppTools.exec(exec);
InputStream inputStream = process.getErrorStream();
byte[] bytes = new byte[2048];
while (inputStream.read(bytes) > -1&&isSave) {
while (inputStream.read(bytes) > -1 && isSave) {
//System.out.println(new String(bytes,StandardCharsets.UTF_8));
if(!isPrint){
if (!isPrint) {
com.yutou.bilibili.Tools.Log.i("开始录制:" + roomId);
QQBotManager.getInstance().sendMessage(roomId + " 已启动录制");
isPrint=true;
isPrint = true;
}
}
process.destroy();
@ -188,7 +184,7 @@ public class SaveLive {
//heartbeats.add(beat);
InputStream inputStream = connection.getInputStream();
liveFile = new File(String.format("%slive%s%s%s[%s]%d.mp4",
ConfigTools.load(ConfigTools.CONFIG,"liveSavePath"),
ConfigTools.load(ConfigTools.CONFIG, "liveSavePath"),
File.separator,
AppTools.getToDayTime(),
File.separator,
@ -198,17 +194,17 @@ public class SaveLive {
liveFile.mkdirs();
liveFile.delete();
}
boolean isPrint=false;
boolean isPrint = false;
FileOutputStream outputStream = new FileOutputStream(liveFile);
int len;
byte[] bytes = new byte[1024];
while ((len = inputStream.read(bytes)) != -1 && isSave) {
outputStream.write(bytes, 0, len);
outputStream.flush();
if(!isPrint){
if (!isPrint) {
com.yutou.bilibili.Tools.Log.i("开始录制:" + roomId);
QQBotManager.getInstance().sendMessage(roomId + " 已启动录制");
isPrint=true;
isPrint = true;
}
}
outputStream.close();

View File

@ -13,7 +13,7 @@ import org.springframework.context.annotation.Import;
@SpringBootApplication
public class BilibiliApplication {
public static String version="0.8.3";
public static String version="0.8.4";
public static void main(String[] args) {
QQBotManager.getInstance().init();

View File

@ -37,8 +37,8 @@ public class ApplicationInit implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
LiveUtils.LiveGiftConfig.getInstance();
AppData.FFMPEG=configService.getConfig(Config.SYSTEM_VIDEO_FFMPEG);
AppData.LIVE_SAVE_FFMPEG= configService.getConfig(Config.SYSTEM_VIDEO_SAVE_MODEL) != null && configService.getConfig(Config.SYSTEM_VIDEO_SAVE_MODEL).equals("ffmpeg");
AppData.FFMPEG = configService.getConfig(Config.SYSTEM_VIDEO_FFMPEG);
AppData.LIVE_SAVE_FFMPEG = configService.getConfig(Config.SYSTEM_VIDEO_SAVE_MODEL) != null && configService.getConfig(Config.SYSTEM_VIDEO_SAVE_MODEL).equals("ffmpeg");
startTimer();
}
@ -93,10 +93,11 @@ public class ApplicationInit implements ApplicationRunner {
}
private void checkLive() {
for (BilibiliUpInfo info : service.getUpInfo()) {
LiveUtils.reloadLiveState(info.getRoomid());
List<BilibiliUpInfo> list = service.getUpInfo();
LiveUtils.reloadLiveState(list);
for (BilibiliUpInfo info : list) {
if (info.getOfflinelistening() == 1) {
if (info.getEnable() == 1) {
if (info.getEnable() == 1 && LiveUtils.isLivePlayer(info.getRoomid())) {
Live live = LiveUtils.liveContains(info);
if (live == null) {
live = new Live();
@ -106,7 +107,7 @@ public class ApplicationInit implements ApplicationRunner {
}
}
}
}, 0, 2*60 * 1000);
}, 0, 2 * 60 * 1000);
}
}

View File

@ -0,0 +1,158 @@
package com.yutou.bilibili.Tools;
import com.yutou.bilibili.BiliBili.Datas.DanmuData;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class AssTools {
private final StringBuilder builder;
private final Date startTime;
private int y = 0;
private List<String> filters = new ArrayList<>();
private String alpha="80";
/**
* 弹幕转换ass
* @param title 标题
* @param startTime 录像起始时间
*/
public AssTools(String title, Date startTime) {
builder = new StringBuilder();
this.startTime = startTime;
initAssHeader(title);
}
/**
* 弹幕过滤器
* @param filter 过滤词
*/
public void addFilter(String... filter) {
filters.addAll(Arrays.asList(filter));
}
/**
* 弹幕透明度
* @param alpha 0 完全不透明 255 完全透明
*/
public void setAlpha(int alpha){
this.alpha=Integer.toHexString(alpha);
}
private void addBuilder(String txt) {
builder.append(txt).append("\n");
}
private void initAssHeader(String title) {
addBuilder("[Script Info]");
addBuilder("Title: " + title);
addBuilder("Original Script: 本字幕由@yutou生成");
addBuilder("ScriptType: v4.00+");
addBuilder("Collisions: Normal");
addBuilder("PlayResX: 560");
addBuilder("PlayResY: 420");
addBuilder("Timer: 10.0000");
addBuilder("");
addBuilder("[V4+ Styles]");
addBuilder("Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, ");
addBuilder("MarginL, MarginR, MarginV, Encoding");
addBuilder("Style: Fix,Microsoft YaHei UI,25,&H66FFFFFF,&H66FFFFFF,&H66000000,&H66000000,1,0,0,0,100,100,0,0,1,2,0,2,20,20,2,0");
addBuilder("Style: R2L,Microsoft YaHei UI,25,&H66FFFFFF,&H66FFFFFF,&H66000000,&H66000000,1,0,0,0,100,100,0,0,1,2,0,2,20,20,2,0");
addBuilder("");
addBuilder("[Events]");
addBuilder("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text");
}
/**
* 保存弹幕文件
* @param savePath 存储路径
* @return 存储结果
*/
public boolean saveDanmu(String savePath) {
System.out.println("savePath = " + savePath);
File file = new File(savePath);
try {
if (file.exists()) {
if (!file.delete()) {
return false;
}
}
boolean mkdirs = file.mkdirs();
boolean delete = file.delete();
if (!mkdirs || !delete) {
return false;
}
if (!file.createNewFile()) {
return false;
}
FileWriter writer = new FileWriter(file);
writer.write(builder.toString());
writer.flush();
writer.close();
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
/**
* 添加弹幕
* @param danmuData 弹幕
*/
public void addDanmu(DanmuData danmuData) {
if (filters.contains(danmuData.getDanmu())) {
return;
}
addY();
long _time = (danmuData.getTime() - startTime.getTime());
long h = TimeUnit.MILLISECONDS.toHours(_time);
long m = TimeUnit.MILLISECONDS.toMinutes(_time) % 60;
long s = TimeUnit.MILLISECONDS.toSeconds(_time) % 60;
String sTime = String.format("%s:%s:%s.0",
new DecimalFormat("00").format(h),
new DecimalFormat("00").format(m),
new DecimalFormat("00").format(s));
if (s >= 52) {
s = (s + 8) - 60;
m++;
} else {
s += 8;
}
String eTime = String.format("%s:%s:%s.0",
new DecimalFormat("00").format(h),
new DecimalFormat("00").format(m),
new DecimalFormat("00").format(s));
float x1, x2;
x1 = 560 + (danmuData.getDanmu().length() * 12.5f);
x2 = 0 - (danmuData.getDanmu().length() * 12.5f);
String ass = String.format("Dialogue: 0,%s,%s,R2L,,20,20,2,,{\\move(%.1f,%d,%.1f,%d)\\c&%s\\alpha&H%s}%s",
sTime,
eTime,
x1,
y,
x2,
y,
danmuData.getFontColorHex(),
alpha,
danmuData.getDanmu()
);
addBuilder(ass);
}
private void addY() {
y += 25;
if (y >= 420) {
y = 25;
}
}
}

View File

@ -0,0 +1,66 @@
package com.yutou.bilibili.Tools;
import com.yutou.bilibili.BiliBili.Datas.DanmuData;
import com.yutou.bilibili.sqlite.BiliBiliLiveDatabasesManager;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DanmuTools {
public static File danmuToAss(File live, File danmu, boolean useFileNameData, String... filterDanmu) {
BiliBiliLiveDatabasesManager manager = new BiliBiliLiveDatabasesManager();
try {
FileTime creationTime = Files.readAttributes(Paths.get(live.getAbsolutePath()), BasicFileAttributes.class).creationTime();
FileTime lastModifiedTime = Files.readAttributes(Paths.get(live.getAbsolutePath()), BasicFileAttributes.class).lastModifiedTime();
Date startTime;
if (useFileNameData) {
startTime = getLiveDate(live.getName());
} else {
startTime = new Date(creationTime.toMillis());
}
manager.init(danmu);
List<DanmuData> danmuData = manager.queryDanmu(startTime, new Date(lastModifiedTime.toMillis()));
AssTools assTools = new AssTools(live.getName(), startTime);
assTools.addFilter(filterDanmu);
assTools.setAlpha(128);
for (DanmuData danmuDatum : danmuData) {
assTools.addDanmu(danmuDatum);
}
assTools.saveDanmu(live.getAbsolutePath().replace(live.getName().substring(live.getName().lastIndexOf(".")), ".ass"));
} catch (Exception e) {
e.printStackTrace();
} finally {
manager.close();
}
return null;
}
private static Date getLiveDate(String fileName) {
Pattern pattern = Pattern.compile("(\\[.*\\]).");
Matcher matcher = pattern.matcher(fileName);
if (matcher.find()) {
String str = matcher.group(1);
try {
return new SimpleDateFormat("[yyyy-MM-dd HHmmss]").parse(str);
} catch (ParseException e) {
e.printStackTrace();
}
}
return null;
}
public static void main(String[] args) {
File live = new File("Z:\\BiliBiliLive\\2021年7月10日BML-Sp\\[2021-07-10 165521]22408644.mp4");
File danmu = new File("Z:\\BiliBiliLive\\2021年7月10日BML-Sp\\[2021-07-10]22408644.db");
danmuToAss(live, danmu,true, "老板大气!点点红包抽礼物!");
}
}

View File

@ -1,86 +1,104 @@
package com.yutou.bilibili.Tools;
import com.alibaba.fastjson.JSONObject;
import com.yutou.bilibili.interfaces.NetworkInterface;
import com.yutou.bilibili.interfaces.DownloadInterface;
import org.springframework.util.StringUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Set;
public class HttpTools {
private static final int HttpRequestIndex = 3;
public static String get(String url) {
return https_get(url, null);
}
public static String post(final String url, final byte[] body) {
return http_post(url, body, 0, null);
}
public static File syncDownload(final String url, final String saveName) {
return new HttpTools().http_syncDownload(url, saveName);
}
public static String https_get(String url, Map<String, String> header) {
try {
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestProperty("User-Agent", getKuKuUA());
URLConnection connection;
connection = new URL(url).openConnection();
connection.setConnectTimeout(60*1000);
connection.setReadTimeout(60*1000);
connection.setRequestProperty("User-Agent", getExtUa());
if (header != null) {
for (String key : header.keySet()) {
connection.addRequestProperty(key, header.get(key));
}
}
connection.connect();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder str = new StringBuilder();
String tmp;
while ((tmp = reader.readLine()) != null) {
str.append(tmp);
str.append(tmp).append("\n");
}
reader.close();
connection.disconnect();
return str.toString();
} catch (Exception e) {
com.yutou.bilibili.Tools.Log.e(e);
System.err.println("error url = " + url);
e.printStackTrace();
}
return null;
}
public synchronized static void post(final String url, final byte[] body, final NetworkInterface networkInterface) {
new Thread(new Runnable() {
@Override
public void run() {
String tmp;
StringBuilder str = new StringBuilder();
try {
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setConnectTimeout(5 * 1000);
connection.setReadTimeout(10 * 1000);
connection.addRequestProperty("Connection", "keep-alive");
connection.addRequestProperty("Accept", "*/*");
connection.addRequestProperty("User-Agent", getExtUa());
//connection.addRequestProperty("content-type", "application/json");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.addRequestProperty("charset", "UTF-8");
OutputStream outputStream = connection.getOutputStream();
outputStream.write(body);
outputStream.write("\n".getBytes(StandardCharsets.UTF_8));
outputStream.flush();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
while ((tmp = reader.readLine()) != null) {
str.append(tmp);
}
// com.yutou.bilibili.Tools.Log.i( "[" + url + "?" + new String(body,StandardCharsets.UTF_8) + "]body:" + str + " (" + connection.getResponseCode() + ")");
if (networkInterface != null) {
try {
networkInterface.httpGetData(str.toString(), connection.getResponseCode());
} catch (IOException e) {
com.yutou.bilibili.Tools.Log.e(e);
}
networkInterface.onCookie(connection.getHeaderField("Set-Cookie"));
}
connection.disconnect();
outputStream.close();
reader.close();
} catch (Exception e) {
networkInterface.httpError(e);
public static String http_post(String url, byte[] body, int index, Map<String, String> headers) {
String tmp;
StringBuilder str = new StringBuilder();
try {
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestMethod("POST");
if (headers != null) {
for (String key : headers.keySet()) {
connection.addRequestProperty(key, headers.get(key));
}
}
}).start();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.addRequestProperty("User-Agent", getExtUa());
connection.setConnectTimeout(5 * 1000);
connection.setReadTimeout(10 * 1000);
//connection.addRequestProperty("Connection", "keep-alive");
//connection.addRequestProperty("User-Agent", getExtUa());
connection.addRequestProperty("content-type", "application/json");
//connection.addRequestProperty("charset", "UTF-8");
OutputStream outputStream = connection.getOutputStream();
//System.out.println(new String(body));
outputStream.write(body);
outputStream.flush();
outputStream.close();
connection.connect();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
while ((tmp = reader.readLine()) != null) {
str.append(tmp);
}
String finalStr = str.toString();
connection.disconnect();
reader.close();
return finalStr;
} catch (Exception e) {
if (index < HttpRequestIndex) {
return http_post(url, body, index + 1, headers);
} else {
e.printStackTrace();
return null;
}
}
}
private static String getExtUa() {
@ -96,11 +114,11 @@ public class HttpTools {
Set<String> keys = json.keySet();
for (String key : keys) {
try {
string.append("&").append(key).append("=").append(URLEncoder.encode(json.getString(key), "UTF-8"));
string.append("&").append(key).append("=").append(URLEncoder.encode(json.getString(key),"utf-8"));
} catch (Exception e) {
com.yutou.bilibili.Tools.Log.e(e);
e.printStackTrace();
try {
string.append("&").append(URLEncoder.encode(key, "UTF-8")).append("=");
string.append("&").append(URLEncoder.encode(key, "utf-8")).append("=");
// string += "&" + key + "=";
} catch (Exception e1) {
string.append("&").append(key).append("=");
@ -130,7 +148,114 @@ public class HttpTools {
}
});
}*/
com.yutou.bilibili.Tools.Log.i(url);
//String str=get(url);
}
private static String donwloadPath = "tmp" + File.separator;
public synchronized static void download(final String url, final String saveName, final DownloadInterface downloadInterface) {
new Thread(new Runnable() {
@Override
public void run() {
File jar = null;
try {
File savePath = new File(donwloadPath);
if (!savePath.exists()) {
savePath.mkdirs();
}
Log.i("DOWNLOAD", "下载文件:" + url + " 保存文件:" + saveName);
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.addRequestProperty("User-Agent", getExtUa());
// Log.i(TAG,"获取到网络请求:"+connection.getResponseCode());
InputStream inputStream = connection.getInputStream();
jar = new File(donwloadPath + saveName + "_tmp.tmp");
jar.createNewFile();
Log.i("DOWNLOAD", "临时保存文件:" + jar.getAbsolutePath());
OutputStream outputStream = new FileOutputStream(jar);
byte[] bytes = new byte[1024];
double size = connection.getContentLength();
double downSize = 0;
int len;
while ((len = inputStream.read(bytes)) > 0) {
outputStream.write(bytes, 0, len);
downSize += len;
if (downloadInterface != null) {
downloadInterface.onDownloading(downSize, size);
}
}
outputStream.close();
inputStream.close();
File oldJar = new File(donwloadPath + saveName);
if (oldJar.exists()) {
oldJar.delete();
}
jar.renameTo(oldJar);
Log.i("DOWNLOAD", "实际保存:" + oldJar.getAbsolutePath() + " " + oldJar.getName());
if (downloadInterface != null) {
downloadInterface.onDownload(oldJar);
}
} catch (Exception e) {
e.printStackTrace();
if (jar != null) {
jar.delete();
}
if (downloadInterface != null) {
downloadInterface.onError(e);
}
}
}
}).start();
}
public synchronized File http_syncDownload(final String url, final String saveName) {
if (StringUtils.isEmpty(url)) {
return null;
}
File jar = null;
try {
File savePath = new File(donwloadPath);
if (!savePath.exists()) {
savePath.mkdirs();
}
Log.i("DOWNLOAD", "下载文件:" + url + " 保存文件:" + saveName);
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.addRequestProperty("User-Agent", getExtUa());
// Log.i(TAG,"获取到网络请求:"+connection.getResponseCode());
InputStream inputStream = connection.getInputStream();
jar = new File(donwloadPath + saveName + "_tmp.tmp");
jar.createNewFile();
Log.i("DOWNLOAD", "临时保存文件:" + jar.getAbsolutePath());
OutputStream outputStream = new FileOutputStream(jar);
byte[] bytes = new byte[1024];
double size = connection.getContentLength();
double downSize = 0;
int len;
while ((len = inputStream.read(bytes)) > 0) {
outputStream.write(bytes, 0, len);
downSize += len;
}
outputStream.close();
inputStream.close();
File oldJar = new File(donwloadPath + saveName);
if (oldJar.exists()) {
oldJar.delete();
}
connection.disconnect();
jar.renameTo(oldJar);
Log.i("DOWNLOAD", "实际保存:" + oldJar.getAbsolutePath() + " " + oldJar.getName());
return oldJar;
} catch (Exception e) {
e.printStackTrace();
if (jar != null) {
jar.delete();
}
return null;
}
}
}

View File

@ -10,6 +10,9 @@ import java.util.logging.Logger;
public class Log {
private static Logger logger;
public static void i(String tag, Object log) {
i('[' + tag + ']' + log);
}
public static void i(Object log) {
if (!((boolean) ConfigTools.load(ConfigTools.CONFIG, "logout"))) {
return;

View File

@ -1,6 +1,8 @@
package com.yutou.bilibili.mybatis.Bili.mybatis.model;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.yutou.bilibili.BiliBili.LiveUtils;
import lombok.Data;
@ -23,6 +25,8 @@ public class BilibiliUpInfo implements Serializable {
*/
private String url;
private Long mid=0L;
/**
* 房间号
*/
@ -43,8 +47,14 @@ public class BilibiliUpInfo implements Serializable {
private static final long serialVersionUID = 1L;
public Integer checkLiveStatus(){
List<BilibiliUpInfo> list=new ArrayList<>();
list.add(this);
live= LiveUtils.getStatusInfoByUid(list).getJSONObject("data").getJSONObject(mid+"").getInteger("live_status");
return live;
}
public Integer getLive() {
live= LiveUtils.getLiveState(roomid)?1:0;
return live;
}
}

View File

@ -304,6 +304,66 @@ public class BilibiliUpInfoExample {
return (Criteria) this;
}
public Criteria andMidIsNull() {
addCriterion("mid is null");
return (Criteria) this;
}
public Criteria andMidIsNotNull() {
addCriterion("mid is not null");
return (Criteria) this;
}
public Criteria andMidEqualTo(Integer value) {
addCriterion("mid =", value, "mid");
return (Criteria) this;
}
public Criteria andMidNotEqualTo(Integer value) {
addCriterion("mid <>", value, "mid");
return (Criteria) this;
}
public Criteria andMidGreaterThan(Integer value) {
addCriterion("mid >", value, "mid");
return (Criteria) this;
}
public Criteria andMidGreaterThanOrEqualTo(Integer value) {
addCriterion("mid >=", value, "mid");
return (Criteria) this;
}
public Criteria andMidLessThan(Integer value) {
addCriterion("mid <", value, "mid");
return (Criteria) this;
}
public Criteria andMidLessThanOrEqualTo(Integer value) {
addCriterion("mid <=", value, "mid");
return (Criteria) this;
}
public Criteria andMidIn(List<Integer> values) {
addCriterion("mid in", values, "mid");
return (Criteria) this;
}
public Criteria andMidNotIn(List<Integer> values) {
addCriterion("mid not in", values, "mid");
return (Criteria) this;
}
public Criteria andMidBetween(Integer value1, Integer value2) {
addCriterion("mid between", value1, value2, "mid");
return (Criteria) this;
}
public Criteria andMidNotBetween(Integer value1, Integer value2) {
addCriterion("mid not between", value1, value2, "mid");
return (Criteria) this;
}
public Criteria andRoomidIsNull() {
addCriterion("roomid is null");
return (Criteria) this;

View File

@ -10,6 +10,7 @@ import com.yutou.bilibili.Tools.AppTools;
import com.yutou.bilibili.Tools.Log;
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliLiveData;
import java.io.File;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
@ -23,11 +24,21 @@ public class BiliBiliLiveDatabasesManager extends SQLiteManager {
super();
}
private JSONObject getInitJSON(){
return JSONObject.parseObject("{\"file\":\"bilibili.db\",\"table\":[{\"name\":\"danmu\",\"item\":[{\"name\":\"id\",\"type\":\"int\",\"isNull\":false,\"isKey\":true},{\"name\":\"model\",\"type\":\"int\",\"isNull\":false,\"isKey\":false},{\"name\":\"fontSize\",\"type\":\"int\",\"isNull\":false,\"isKey\":false},{\"name\":\"fontColor\",\"type\":\"int\",\"isNull\":false,\"isKey\":false},{\"name\":\"time\",\"type\":\"int\",\"isNull\":false,\"isKey\":false},{\"name\":\"uCode\",\"type\":\"String\",\"isNull\":false,\"isKey\":false},{\"name\":\"danmu\",\"type\":\"String\",\"isNull\":false,\"isKey\":false},{\"name\":\"uid\",\"type\":\"int\",\"isNull\":false,\"isKey\":false},{\"name\":\"uname\",\"type\":\"String\",\"isNull\":false,\"isKey\":false}]}]}");
}
public void init(String fileName){
JSONObject json = JSONObject.parseObject("{\"file\":\"bilibili.db\",\"table\":[{\"name\":\"danmu\",\"item\":[{\"name\":\"id\",\"type\":\"int\",\"isNull\":false,\"isKey\":true},{\"name\":\"model\",\"type\":\"int\",\"isNull\":false,\"isKey\":false},{\"name\":\"fontSize\",\"type\":\"int\",\"isNull\":false,\"isKey\":false},{\"name\":\"fontColor\",\"type\":\"int\",\"isNull\":false,\"isKey\":false},{\"name\":\"time\",\"type\":\"int\",\"isNull\":false,\"isKey\":false},{\"name\":\"uCode\",\"type\":\"String\",\"isNull\":false,\"isKey\":false},{\"name\":\"danmu\",\"type\":\"String\",\"isNull\":false,\"isKey\":false},{\"name\":\"uid\",\"type\":\"int\",\"isNull\":false,\"isKey\":false},{\"name\":\"uname\",\"type\":\"String\",\"isNull\":false,\"isKey\":false}]}]}");
JSONObject json = getInitJSON();
json.put("model","create");
json.put("file",fileName+".db");
build(json);
}
public void init(File file){
JSONObject json = getInitJSON();
json.put("model","load");
json.put("file",file.getAbsolutePath());
build(json);
}
/**
* 添加弹幕
@ -72,10 +83,10 @@ public class BiliBiliLiveDatabasesManager extends SQLiteManager {
data.setModel(set.getInt("model"));
data.setFontSize(set.getInt("fontSize"));
data.setFontColor(set.getInt("fontColor"));
data.setTime(set.getInt("time"));
data.setTime(set.getLong("time"));
data.setUCode(set.getString("uCode"));
data.setDanmu(set.getString("danmu"));
data.setUid(set.getInt("uid"));
data.setUid(set.getLong("uid"));
data.setUname(set.getString("uname"));
list.add(data);
}

View File

@ -30,7 +30,8 @@ public class SQLiteManager {
com.yutou.bilibili.Tools.Log.e(e);
}
}
public void close(){
public void close() {
try {
conn.close();
} catch (SQLException throwables) {
@ -49,22 +50,24 @@ public class SQLiteManager {
protected SQLiteManager() {
}
private void createSql(JSONObject json){
private void createSql(JSONObject json) {
try {
sql.mkdirs();
sql.delete();
conn = DriverManager.getConnection(url + sql.getAbsolutePath());
}catch (Exception e){
} catch (Exception e) {
com.yutou.bilibili.Tools.Log.e(e);
}
startBatch();
JSONArray array=json.getJSONArray("table");
JSONArray array = json.getJSONArray("table");
for (Object o : array) {
com.yutou.bilibili.Tools.Log.i("创建表:"+((JSONObject)o).getString("name"));
com.yutou.bilibili.Tools.Log.i("创建表:" + ((JSONObject) o).getString("name"));
createSqlOfTable((JSONObject) o);
}
closeBatch();
}
private void createSqlOfTable(JSONObject table) {
String tableName = table.getString("name");
try {
@ -109,7 +112,11 @@ public class SQLiteManager {
protected void build(JSONObject json) {
try {
Class.forName("org.sqlite.JDBC");
sql = new File("databases" + File.separator + json.getString("file"));
if ("load".equals(json.getString("model"))) {
sql = new File(json.getString("file"));
} else {
sql = new File("databases" + File.separator + json.getString("file"));
}
if (!sql.exists()) {
createSql(json);
} else {

View File

@ -5,6 +5,7 @@
<id column="id" jdbcType="INTEGER" property="id" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="url" jdbcType="VARCHAR" property="url" />
<result column="mid" jdbcType="INTEGER" property="mid" />
<result column="roomid" jdbcType="INTEGER" property="roomid" />
<result column="offlineListening" jdbcType="INTEGER" property="offlinelistening" />
<result column="saveDanmu" jdbcType="INTEGER" property="savedanmu" />
@ -71,7 +72,7 @@
</where>
</sql>
<sql id="Base_Column_List">
id, `name`, url, roomid, offlineListening, saveDanmu, `enable`, live, saveLive
id, `name`, url, mid, roomid, offlineListening, saveDanmu, `enable`, live, saveLive
</sql>
<select id="selectByExample" parameterType="com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliUpInfoExample" resultMap="BaseResultMap">
select
@ -104,12 +105,14 @@
</if>
</delete>
<insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliUpInfo" useGeneratedKeys="true">
insert into bilibili_up_info (`name`, url, roomid,
offlineListening, saveDanmu, `enable`,
live, saveLive)
values (#{name,jdbcType=VARCHAR}, #{url,jdbcType=VARCHAR}, #{roomid,jdbcType=INTEGER},
#{offlinelistening,jdbcType=INTEGER}, #{savedanmu,jdbcType=INTEGER}, #{enable,jdbcType=INTEGER},
#{live,jdbcType=INTEGER}, #{savelive,jdbcType=INTEGER})
insert into bilibili_up_info (`name`, url, mid,
roomid, offlineListening, saveDanmu,
`enable`, live, saveLive
)
values (#{name,jdbcType=VARCHAR}, #{url,jdbcType=VARCHAR}, #{mid,jdbcType=INTEGER},
#{roomid,jdbcType=INTEGER}, #{offlinelistening,jdbcType=INTEGER}, #{savedanmu,jdbcType=INTEGER},
#{enable,jdbcType=INTEGER}, #{live,jdbcType=INTEGER}, #{savelive,jdbcType=INTEGER}
)
</insert>
<insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliUpInfo" useGeneratedKeys="true">
insert into bilibili_up_info
@ -120,6 +123,9 @@
<if test="url != null">
url,
</if>
<if test="mid != null">
mid,
</if>
<if test="roomid != null">
roomid,
</if>
@ -146,6 +152,9 @@
<if test="url != null">
#{url,jdbcType=VARCHAR},
</if>
<if test="mid != null">
#{mid,jdbcType=INTEGER},
</if>
<if test="roomid != null">
#{roomid,jdbcType=INTEGER},
</if>
@ -184,6 +193,9 @@
<if test="record.url != null">
url = #{record.url,jdbcType=VARCHAR},
</if>
<if test="record.mid != null">
mid = #{record.mid,jdbcType=INTEGER},
</if>
<if test="record.roomid != null">
roomid = #{record.roomid,jdbcType=INTEGER},
</if>
@ -212,6 +224,7 @@
set id = #{record.id,jdbcType=INTEGER},
`name` = #{record.name,jdbcType=VARCHAR},
url = #{record.url,jdbcType=VARCHAR},
mid = #{record.mid,jdbcType=INTEGER},
roomid = #{record.roomid,jdbcType=INTEGER},
offlineListening = #{record.offlinelistening,jdbcType=INTEGER},
saveDanmu = #{record.savedanmu,jdbcType=INTEGER},
@ -231,6 +244,9 @@
<if test="url != null">
url = #{url,jdbcType=VARCHAR},
</if>
<if test="mid != null">
mid = #{mid,jdbcType=INTEGER},
</if>
<if test="roomid != null">
roomid = #{roomid,jdbcType=INTEGER},
</if>
@ -256,6 +272,7 @@
update bilibili_up_info
set `name` = #{name,jdbcType=VARCHAR},
url = #{url,jdbcType=VARCHAR},
mid = #{mid,jdbcType=INTEGER},
roomid = #{roomid,jdbcType=INTEGER},
offlineListening = #{offlinelistening,jdbcType=INTEGER},
saveDanmu = #{savedanmu,jdbcType=INTEGER},