完善切片存储
This commit is contained in:
parent
b5c2153ad0
commit
48a15c8769
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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());
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user