完善切片存储

This commit is contained in:
zlzw 2024-11-27 17:38:45 +08:00
parent b5c2153ad0
commit 48a15c8769
8 changed files with 49 additions and 55 deletions

View File

@ -14,6 +14,8 @@ public class LiveVideoDatabaseBean extends AbsDatabasesBean {
String roomInfoJson; String roomInfoJson;
@JSONField(name = "start_time") @JSONField(name = "start_time")
Date startTime; Date startTime;
@JSONField(name = "stop_time")
Date stopTime;
@JSONField(name = "path") @JSONField(name = "path")
String path; String path;

View File

@ -118,8 +118,6 @@ public class BiliLiveDatabase extends SQLiteManager {
} }
public JSONObject getGiftInfo(long startTimeLong, long endTimeLong) { public JSONObject getGiftInfo(long startTimeLong, long endTimeLong) {
String startTime = DateFormatUtils.getInstance().format(startTimeLong);
String endTime = DateFormatUtils.getInstance().format(endTimeLong);
String giftSql = "WITH filtered_gifts AS (" + String giftSql = "WITH filtered_gifts AS (" +
"SELECT " + "SELECT " +
"`gift_name`," + "`gift_name`," +
@ -132,8 +130,8 @@ public class BiliLiveDatabase extends SQLiteManager {
"FROM " + "FROM " +
"`gift` " + "`gift` " +
"WHERE " + "WHERE " +
"`sql_time` >= '" + startTime + "' " + "`sql_time` >= '" + startTimeLong + "' " +
"AND `sql_time` <= '" + endTime + "' " + "AND `sql_time` <= '" + endTimeLong + "' " +
"GROUP BY " + "GROUP BY " +
"`gift_name`, `coin_type`" + "`gift_name`, `coin_type`" +
")" + ")" +
@ -147,10 +145,10 @@ public class BiliLiveDatabase extends SQLiteManager {
"GROUP BY " + "GROUP BY " +
"`gift_name`, `icon`;"; "`gift_name`, `icon`;";
String guardSql = "SELECT `gift_name`, SUM(`num`) AS `total_num`,SUM(`price`*`num`) as `total_price`" + String guardSql = "SELECT `gift_name`, SUM(`num`) AS `total_num`,SUM(`price`*`num`) as `total_price`" +
"FROM `guardBuy` where `sql_time` >= '" + startTime + "' and `sql_time` <= '" + endTime + "'" + "FROM `guardBuy` where `sql_time` >= '" + startTimeLong + "' and `sql_time` <= '" + endTimeLong + "'" +
"GROUP BY `gift_name`;"; "GROUP BY `gift_name`;";
String superChatSql = "SELECT SUM(`price`*100) as `total_price`, count(`price`) as `total_count`" + String superChatSql = "SELECT SUM(`price`*100) as `total_price`, count(`price`) as `total_count`" +
"FROM `superChat` where `sql_time` >= '" + startTime + "' and `sql_time` <= '" + endTime + "';"; "FROM `superChat` where `sql_time` >= '" + startTimeLong + "' and `sql_time` <= '" + endTimeLong + "';";
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();
JSONArray giftInfo = get(giftSql); JSONArray giftInfo = get(giftSql);
JSONArray guardInfo = get(guardSql); JSONArray guardInfo = get(guardSql);
@ -177,15 +175,14 @@ public class BiliLiveDatabase extends SQLiteManager {
} }
private void createInfo(LiveVideoDatabaseBean bean) { private void createInfo(LiveVideoDatabaseBean bean) {
String format = DateFormatUtils.getInstance().format(bean.getSql_time()); if (get(bean.getTableName(), " `sql_time` = '" + bean.getSql_time().getTime() + "'", LiveVideoDatabaseBean.class).isEmpty()) {
if (get(bean.getTableName(), " `sql_time` = '" + format + "'", LiveVideoDatabaseBean.class).isEmpty()) {
add(bean); add(bean);
} else { } else {
update(bean); update(bean);
} }
} }
public <T extends AbsDatabasesBean> List<T> getOfTime(String startTime, String endTime, Class<T> clazz) { public <T extends AbsDatabasesBean> List<T> getOfTime(Long startTime, Long endTime, Class<T> clazz) {
String tableName = null; String tableName = null;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
String where = null; String where = null;

View File

@ -25,6 +25,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Base64; import java.util.Base64;
import java.util.List; import java.util.List;
@ -109,6 +110,13 @@ public class VideoFileController {
@RequestMapping("/video/play") @RequestMapping("/video/play")
@ResponseBody @ResponseBody
public JSONObject getVideoUrl(String roomId, String videoId) { public JSONObject getVideoUrl(String roomId, String videoId) {
return ResultData.success("/live/"+videoService.getVideoPlay(roomId, videoId)); String url = videoService.getVideoPlay(roomId, videoId);
/* String[] split = url.split("/");
StringBuilder sb=new StringBuilder();
for (String s : split) {
sb.append(URLEncoder.encode(s,StandardCharsets.UTF_8)).append("/");
}
sb.setLength(sb.length()-1);*/
return ResultData.success("/live"+url);
} }
} }

View File

@ -59,18 +59,21 @@ public class LiveDanmuService {
public void saveDanmuXML(LiveVideoDatabaseBean videoDatabaseBean, BiliLiveDatabase database) { public void saveDanmuXML(LiveVideoDatabaseBean videoDatabaseBean, BiliLiveDatabase database) {
File videoFile = new File(videoDatabaseBean.getPath()); File videoFile = new File(videoDatabaseBean.getPath());
long videoTime = FFmpegUtils.getVideoTime(videoFile) + videoDatabaseBean.getStartTime().getTime(); long videoTime;
if (videoDatabaseBean.getStopTime() == null) {
videoTime = System.currentTimeMillis();
} else {
videoTime = videoDatabaseBean.getStopTime().getTime();
}
Log.i("开始时间:" + videoDatabaseBean.getStartTime().getTime()); Log.i("开始时间:" + videoDatabaseBean.getStartTime().getTime());
Log.i("结束时间:" + videoTime); Log.i("结束时间:" + videoTime);
String startTime = DateFormatUtils.getInstance().format(videoDatabaseBean.getStartTime()); List<LiveDanmuDatabaseBean> danmus = database.getOfTime(videoDatabaseBean.getStartTime().getTime(), videoTime, LiveDanmuDatabaseBean.class);
String endTime = DateFormatUtils.getInstance().format(videoTime);
List<LiveDanmuDatabaseBean> danmus = database.getOfTime(startTime, endTime, LiveDanmuDatabaseBean.class);
Log.i("弹幕数量:" + danmus.size()); Log.i("弹幕数量:" + danmus.size());
AssTools assTools = new AssTools(videoFile.getName().replace(".flv", ""), videoDatabaseBean.getStartTime()); AssTools assTools = new AssTools(videoFile.getName().replace(".m3u8", ""), videoDatabaseBean.getStartTime());
for (LiveDanmuDatabaseBean dm : danmus) { for (LiveDanmuDatabaseBean dm : danmus) {
assTools.addDanmu(dm.createDanmuData()); assTools.addDanmu(dm.createDanmuData());
} }
assTools.saveDanmu(videoFile.getAbsolutePath().replace(".flv", ".ass")); assTools.saveDanmu(videoFile.getAbsolutePath().replace(".m3u8", ".ass"));
} }
public String toTimeString(long videoTime) { public String toTimeString(long videoTime) {
@ -90,19 +93,10 @@ public class LiveDanmuService {
if (videoBean == null) { if (videoBean == null) {
return new LiveVideoDanmu(); return new LiveVideoDanmu();
} }
File videoFile = new File(videoBean.getPath().replace(".flv", ".mp4"));
if (!videoFile.exists()) {
videoFile = new File(videoBean.getPath());
}
long videoTime = FFmpegUtils.getVideoTime(videoFile);
long startTime = Long.parseLong(videoId); long startTime = Long.parseLong(videoId);
long endTime = Long.parseLong(videoId) + videoTime; long endTime = videoBean.getStopTime() == null ? System.currentTimeMillis() : videoBean.getStopTime().getTime();
// videoTime = 0; List<LiveDanmuDatabaseBean> danmuList = liveDatabase.getOfTime(startTime, endTime, LiveDanmuDatabaseBean.class);
if (videoTime == 0) { List<LiveSuperChatDatabaseBean> superChatList = liveDatabase.getOfTime(startTime, endTime, LiveSuperChatDatabaseBean.class);
endTime = System.currentTimeMillis();
}
List<LiveDanmuDatabaseBean> danmuList = liveDatabase.getOfTime(DateFormatUtils.getInstance().format(startTime), DateFormatUtils.getInstance().format(endTime), LiveDanmuDatabaseBean.class);
List<LiveSuperChatDatabaseBean> superChatList = liveDatabase.getOfTime(DateFormatUtils.getInstance().format(startTime), DateFormatUtils.getInstance().format(endTime), LiveSuperChatDatabaseBean.class);
for (LiveDanmuDatabaseBean bean : danmuList) { for (LiveDanmuDatabaseBean bean : danmuList) {
LiveVideoDanmu.Danmu danmu = createDanmu(bean, startTime); LiveVideoDanmu.Danmu danmu = createDanmu(bean, startTime);
danmus.getDanmu().add(danmu); danmus.getDanmu().add(danmu);

View File

@ -87,7 +87,7 @@ public class LiveService {
if (info.getLiveTime() == 0) { if (info.getLiveTime() == 0) {
liveData.setLiveTime("未开播"); liveData.setLiveTime("未开播");
} else { } else {
liveData.setLiveTime(DateFormatUtils.getInstance().formatMillis(System.currentTimeMillis() - info.getLiveTime()*1000)); liveData.setLiveTime(DateFormatUtils.getInstance().formatMillis(System.currentTimeMillis() - info.getLiveTime() * 1000));
} }
liveData.setDownloadVideo(videoDownloadService.checkDownload(info.getRoomId())); liveData.setDownloadVideo(videoDownloadService.checkDownload(info.getRoomId()));
liveData.setDanmu(danmuService.check(info.getRoomId())); liveData.setDanmu(danmuService.check(info.getRoomId()));
@ -113,16 +113,8 @@ public class LiveService {
if (videoBean == null) { if (videoBean == null) {
return null; return null;
} }
File videoFile = new File(videoBean.getPath().replace(".flv", ".mp4")); long startTime = videoBean.getStartTime().getTime();
if (!videoFile.exists()) { long endTime = videoBean.getStopTime() == null ? System.currentTimeMillis() : videoBean.getStopTime().getTime();
videoFile = new File(videoBean.getPath());
}
long videoTime = FFmpegUtils.getVideoTime(videoFile);
long startTime = Long.parseLong(videoId);
long endTime = Long.parseLong(videoId) + videoTime;
if(videoTime==0){
endTime=System.currentTimeMillis();
}
return database.getGiftInfo(startTime, endTime); return database.getGiftInfo(startTime, endTime);
} }

View File

@ -120,7 +120,7 @@ public class LiveVideoDownloadService {
File rootPath; File rootPath;
LiveConfigDatabaseBean config; LiveConfigDatabaseBean config;
BiliLiveDatabase database; BiliLiveDatabase database;
LiveVideoDatabaseBean videoDatabaseBean; LiveVideoDatabaseBean videoDatabaseBean = null;
LiveRoomInfo roomInfo; LiveRoomInfo roomInfo;
public VideoTask(LiveConfigDatabaseBean bean, LiveRoomInfo roomInfo) { public VideoTask(LiveConfigDatabaseBean bean, LiveRoomInfo roomInfo) {
@ -136,8 +136,8 @@ public class LiveVideoDownloadService {
String time = DateUtils.format(new Date().getTime(), DATE_FORMAT_10_DASH); String time = DateUtils.format(new Date().getTime(), DATE_FORMAT_10_DASH);
rootPath = new File(bean.getRecordPath() + File.separator + bean.getAnchorName() + File.separator + time + File.separator + "[" + rootPath = new File(bean.getRecordPath() + File.separator + bean.getAnchorName() + File.separator + time + File.separator + "[" +
DateUtils.format(new Date(), DateUtils.format(new Date(),
"yyyy-MM-dd HH-mm-ss") + "]" + roomInfo.getTitle()); "HH-mm-ss") + "]" + roomInfo.getTitle());
savePath = rootPath.getAbsolutePath() + File.separator + roomInfo.getTitle() + "-%04d.ts"; savePath = rootPath.getAbsolutePath() + File.separator + roomInfo.getTitle() + ".m3u8";
if (!rootPath.exists()) { if (!rootPath.exists()) {
rootPath.mkdirs(); rootPath.mkdirs();
} }
@ -148,14 +148,14 @@ public class LiveVideoDownloadService {
} }
private void stop() { private void stop() {
videoRecord.kill(bean.getRoomId().toString()); videoRecord.kill(bean.getRoomId());
api.getRoomInfo(config.getRoomId().toString()).enqueue(new HttpCallback<LiveRoomInfo>() { api.getRoomInfo(config.getRoomId()).enqueue(new HttpCallback<LiveRoomInfo>() {
@Override @Override
public void onResponse(Headers headers, int code, String status, LiveRoomInfo response, String rawResponse) { public void onResponse(Headers headers, int code, String status, LiveRoomInfo response, String rawResponse) {
if (response.getLiveStatus() == 1) { if (response.getLiveStatus() == 1) {
LiveVideoDownloadService.this.start(bean, false); LiveVideoDownloadService.this.start(bean, false);
} else { } else {
LiveVideoDownloadService.this.stop(bean.getRoomId().toString(), false); LiveVideoDownloadService.this.stop(bean.getRoomId(), false);
} }
} }
@ -289,20 +289,19 @@ public class LiveVideoDownloadService {
// .withNotSymbolParam("-bufsize", "10M") // .withNotSymbolParam("-bufsize", "10M")
.withNotSymbolParam("-f", "segment") .withNotSymbolParam("-f", "segment")
.withNotSymbolParam("-segment_time", "60") .withNotSymbolParam("-segment_time", "60")
.withNotSymbolParam("-segment_format", "flv") .withNotSymbolParam("-segment_format", "mpegts")
.withParam("-segment_list", rootPath + File.separator + roomInfo.getTitle() + ".m3u8") .withNotSymbolParam("-map", "0")
.withParam("-segment_list", savePath)
.withNotSymbolParam("-c", "copy") .withNotSymbolParam("-c", "copy")
.withNotSymbolParam("-bsf:a", "aac_adtstoasc") .withNotSymbolParam("-bsf:a", "aac_adtstoasc")
// .withNotSymbolParam("-loglevel", "debug") // .withNotSymbolParam("-loglevel", "debug")
.withNotSymbolParam("-y", "") .withNotSymbolParam("-y", "")
//-reconnect 1 -reconnect_at_eof 1 -reconnect_streamed 1 -reconnect_delay_max 2
// .withNotSymbolParam("-progress",new File("cache",config.getRoomId()+".txt").getAbsolutePath()); //输出进度日志,暂时没啥用 // .withNotSymbolParam("-progress",new File("cache",config.getRoomId()+".txt").getAbsolutePath()); //输出进度日志,暂时没啥用
; ;
if (ck != null) { if (ck != null) {
// builder = builder.withParam("-cookies", cookie); // builder = builder.withParam("-cookies", cookie);
} }
FFmpegUtils command = builder.build(config.getRoomId(), ffmpegPath, url, savePath); FFmpegUtils command = builder.build(config.getRoomId(), ffmpegPath, url, savePath.replace(".m3u8","-%04d.ts"));
Log.i(command.getCommandDecode()); Log.i(command.getCommandDecode());
try { try {
command.start(new DownloadInterface() { command.start(new DownloadInterface() {
@ -335,6 +334,10 @@ public class LiveVideoDownloadService {
task.cancel(); task.cancel();
task = null; task = null;
} }
if (videoDatabaseBean != null) {
videoDatabaseBean.setStopTime(new Date());
database.addLiveInfo(videoDatabaseBean);
}
} }
}); });
@ -430,8 +433,8 @@ public class LiveVideoDownloadService {
File videoFile = new File(videoInfo.getPath().replace("-%04d.ts", ".m3u8")); File videoFile = new File(videoInfo.getPath().replace("-%04d.ts", ".m3u8"));
if (!videoFile.exists()) { if (!videoFile.exists()) {
videoFile = new File(videoInfo.getPath()); videoFile = new File(videoInfo.getPath());
}else{ } else {
return videoInfo.getPath().replace(new File("live").getAbsolutePath(),"").replace(File.separator,"/").replace("-%04d.ts", ".m3u8"); return videoInfo.getPath().replace(new File("live").getAbsolutePath(), "").replace(File.separator, "/").replace("-%04d.ts", ".m3u8");
} }
FFmpegUtils ffmpeg = FFmpegUtils.segment(videoId, ffmpegPath, videoFile, ConfigTools.load(ConfigTools.CONFIG, "outVideoPath", String.class)); FFmpegUtils ffmpeg = FFmpegUtils.segment(videoId, ffmpegPath, videoFile, ConfigTools.load(ConfigTools.CONFIG, "outVideoPath", String.class));
System.out.println(ffmpeg.getCommandDecode()); System.out.println(ffmpeg.getCommandDecode());

View File

@ -380,11 +380,10 @@ public abstract class SQLiteManager {
protected <T extends AbsDatabasesBean> boolean delete(T t) { protected <T extends AbsDatabasesBean> boolean delete(T t) {
Statement statement = null; Statement statement = null;
try { try {
String id = DateUtils.format(t.getSql_time(), "yyyy-MM-dd HH:mm:ss.SSS");
statement = getConnection().createStatement(); statement = getConnection().createStatement();
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("DELETE FROM `").append(t.getTableName()).append("` "); sb.append("DELETE FROM `").append(t.getTableName()).append("` ");
sb.append(" WHERE `sql_time` = ").append("'").append(id).append("'"); sb.append(" WHERE `sql_time` = ").append("'").append(t.getSql_time().getTime()).append("'");
int ret = statement.executeUpdate(sb.toString()); int ret = statement.executeUpdate(sb.toString());
return ret != 0; return ret != 0;
} catch (Exception e) { } catch (Exception e) {

View File

@ -182,7 +182,6 @@ public class FFmpegUtils extends AbsVideoRecord {
process.exitValue(); process.exitValue();
return (long) (Double.parseDouble(data) * 1000); return (long) (Double.parseDouble(data) * 1000);
} catch (Exception e) { } catch (Exception e) {
Log.e(e);
return 0; return 0;
} }
} }