新增FFmpeg录制方法,但如果意外中断会存储失败
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
package com.yutou.bilibili.BiliBili.Datas;
|
||||
|
||||
public class AppData {
|
||||
public static String FFMPEG="";
|
||||
public static String BILIBILI_HEADERS = "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36 Referer:https://live.bilibili.com";
|
||||
public static boolean LIVE_SAVE_FFMPEG=false;
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.yutou.bilibili.BiliBili.Tools;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.yutou.bilibili.BiliBili.Datas.AppData;
|
||||
import com.yutou.bilibili.BiliBili.Live;
|
||||
import com.yutou.bilibili.BiliBili.LiveUtils;
|
||||
import com.yutou.bilibili.QQBot.QQBotManager;
|
||||
@@ -122,38 +123,11 @@ public class SaveLive {
|
||||
super.run();
|
||||
String url = getLiveUrl(roomId);
|
||||
try {
|
||||
com.yutou.bilibili.Tools.Log.i("开始录制:" + roomId);
|
||||
QQBotManager.getInstance().sendMessage(roomId + " 已启动录制");
|
||||
HttpURLConnection connection = LiveUtils.getBiliHttpGet(url, LiveUtils.getCookie());
|
||||
connection.setReadTimeout(5000);
|
||||
connection.setConnectTimeout(5000);
|
||||
heartbeat = new Timer();
|
||||
//Heartbeat beat = new Heartbeat();
|
||||
heartbeat.schedule(new Heartbeat(), 0, 30000);
|
||||
heartbeats.put(roomId, heartbeat);
|
||||
//heartbeats.add(beat);
|
||||
InputStream inputStream = connection.getInputStream();
|
||||
liveFile = new File(String.format("live%s%s%s[%s]%d.mp4",
|
||||
File.separator,
|
||||
AppTools.getToDayTime(),
|
||||
File.separator,
|
||||
AppTools.getToDayNowTimeToString().replace(":", ""),
|
||||
roomId));
|
||||
if (!liveFile.exists()) {
|
||||
liveFile.mkdirs();
|
||||
liveFile.delete();
|
||||
if(AppData.LIVE_SAVE_FFMPEG){
|
||||
ffmpegDownload(url);
|
||||
}else {
|
||||
httpDownload(url);
|
||||
}
|
||||
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();
|
||||
}
|
||||
outputStream.close();
|
||||
inputStream.close();
|
||||
com.yutou.bilibili.Tools.Log.i("录制完成:" + roomId + " save = " + isSave + " len = " + len);
|
||||
QQBotManager.getInstance().sendMessage("录制完成:" + roomId + " save = " + isSave + " len = " + len);
|
||||
} catch (Exception e) {
|
||||
com.yutou.bilibili.Tools.Log.e(e);
|
||||
Log.i("录制发生意外:" + e.getMessage());
|
||||
@@ -164,6 +138,74 @@ public class SaveLive {
|
||||
|
||||
}
|
||||
|
||||
private void ffmpegDownload(String url) throws Exception {
|
||||
liveFile = new File(String.format("live%s%s%s[%s]%d.mp4",
|
||||
File.separator,
|
||||
AppTools.getToDayTime(),
|
||||
File.separator,
|
||||
AppTools.getToDayNowTimeToString().replace(":", ""),
|
||||
roomId));
|
||||
if (!liveFile.exists()) {
|
||||
liveFile.mkdirs();
|
||||
liveFile.delete();
|
||||
}
|
||||
String exec = String.format("%s -user_agent \"%s\" -cookies \"%s\" -headers \"%s\" -i \"%s\" -threads 8 -c:v copy -y \"%s\" %s ",
|
||||
AppData.FFMPEG,
|
||||
AppData.BILIBILI_HEADERS,
|
||||
LiveUtils.getCookie(),
|
||||
"Referer:https://live.bilibili.com",
|
||||
url,
|
||||
liveFile.getAbsolutePath(),
|
||||
""
|
||||
);
|
||||
System.out.println(exec);
|
||||
Process process=AppTools.exec(exec);
|
||||
InputStream inputStream = process.getErrorStream();
|
||||
byte[] bytes = new byte[2048];
|
||||
while (inputStream.read(bytes) > -1) {
|
||||
System.out.println(new String(bytes,StandardCharsets.UTF_8));
|
||||
}
|
||||
System.out.println("----------------stop ffmpeg");
|
||||
inputStream.close();
|
||||
com.yutou.bilibili.Tools.Log.i("录制完成:" + roomId);
|
||||
QQBotManager.getInstance().sendMessage("录制完成:" + roomId);
|
||||
}
|
||||
|
||||
private void httpDownload(String url) throws Exception {
|
||||
com.yutou.bilibili.Tools.Log.i("开始录制:" + roomId);
|
||||
QQBotManager.getInstance().sendMessage(roomId + " 已启动录制");
|
||||
HttpURLConnection connection = LiveUtils.getBiliHttpGet(url, LiveUtils.getCookie());
|
||||
connection.setReadTimeout(5000);
|
||||
connection.setConnectTimeout(5000);
|
||||
heartbeat = new Timer();
|
||||
//Heartbeat beat = new Heartbeat();
|
||||
heartbeat.schedule(new Heartbeat(), 0, 30000);
|
||||
heartbeats.put(roomId, heartbeat);
|
||||
//heartbeats.add(beat);
|
||||
InputStream inputStream = connection.getInputStream();
|
||||
liveFile = new File(String.format("live%s%s%s[%s]%d.mp4",
|
||||
File.separator,
|
||||
AppTools.getToDayTime(),
|
||||
File.separator,
|
||||
AppTools.getToDayNowTimeToString().replace(":", ""),
|
||||
roomId));
|
||||
if (!liveFile.exists()) {
|
||||
liveFile.mkdirs();
|
||||
liveFile.delete();
|
||||
}
|
||||
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();
|
||||
}
|
||||
outputStream.close();
|
||||
inputStream.close();
|
||||
com.yutou.bilibili.Tools.Log.i("录制完成:" + roomId + " save = " + isSave + " len = " + len);
|
||||
QQBotManager.getInstance().sendMessage("录制完成:" + roomId + " save = " + isSave + " len = " + len);
|
||||
}
|
||||
|
||||
private class Heartbeat extends TimerTask {
|
||||
int nextInterval = 1;
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package com.yutou.bilibili.Controllers;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.yutou.bilibili.BiliBili.Datas.AppData;
|
||||
import com.yutou.bilibili.QQBot.QQBotManager;
|
||||
import com.yutou.bilibili.Services.ISystemConfigService;
|
||||
import com.yutou.bilibili.Tools.Config;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
@@ -21,7 +23,7 @@ public class SystemConfigController {
|
||||
@ResponseBody
|
||||
public JSONObject getRegUser() {
|
||||
JSONObject json = new JSONObject();
|
||||
JSONObject data=new JSONObject();
|
||||
JSONObject data = new JSONObject();
|
||||
String reg = configService.getConfig(Config.USER_REG);
|
||||
String bLive = configService.getConfig(Config.BILI_LIVE_FLAG);
|
||||
if (reg == null) {
|
||||
@@ -31,68 +33,103 @@ public class SystemConfigController {
|
||||
bLive = "0";
|
||||
}
|
||||
data.put(Config.USER_REG, reg);
|
||||
data.put(Config.BILI_LIVE_FLAG,bLive);
|
||||
json.put("code",0);
|
||||
json.put("data",data);
|
||||
data.put(Config.BILI_LIVE_FLAG, bLive);
|
||||
json.put("code", 0);
|
||||
json.put("data", data);
|
||||
return json;
|
||||
}
|
||||
|
||||
@RequestMapping("/system/set/config.do")
|
||||
@ResponseBody
|
||||
public JSONObject setConfig(String key,String value){
|
||||
public JSONObject setConfig(String key, String value) {
|
||||
configService.setConfig(key, value);
|
||||
JSONObject json=new JSONObject();
|
||||
json.put("code",0);
|
||||
json.put("msg","ok");
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("code", 0);
|
||||
json.put("msg", "ok");
|
||||
return json;
|
||||
}
|
||||
|
||||
@RequestMapping("/system/public/reg.do")
|
||||
@ResponseBody
|
||||
public JSONObject getRegModel(){
|
||||
public JSONObject getRegModel() {
|
||||
JSONObject json = new JSONObject();
|
||||
JSONObject data=new JSONObject();
|
||||
JSONObject data = new JSONObject();
|
||||
String reg = configService.getConfig(Config.USER_REG);
|
||||
boolean model=false;
|
||||
boolean model = false;
|
||||
if (reg == null) {
|
||||
reg = "0";
|
||||
}
|
||||
if(reg.equals("1")){
|
||||
model=true;
|
||||
if (reg.equals("1")) {
|
||||
model = true;
|
||||
}
|
||||
data.put(Config.USER_REG, model);
|
||||
json.put("code",0);
|
||||
json.put("data",data);
|
||||
json.put("code", 0);
|
||||
json.put("data", data);
|
||||
return json;
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@RequestMapping("/system/set/ffmpeg.do")
|
||||
public JSONObject setFFmpeg(String ffmpeg) throws UnsupportedEncodingException {
|
||||
ffmpeg= URLDecoder.decode(ffmpeg,"UTF-8");
|
||||
configService.setConfig(Config.SYSTEM_VIDEO_FFMPEG,ffmpeg);
|
||||
JSONObject json=new JSONObject();
|
||||
json.put("code",0);
|
||||
json.put("msg","ok");
|
||||
ffmpeg = URLDecoder.decode(ffmpeg, "UTF-8");
|
||||
configService.setConfig(Config.SYSTEM_VIDEO_FFMPEG, ffmpeg);
|
||||
AppData.FFMPEG = ffmpeg;
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("code", 0);
|
||||
json.put("msg", "ok");
|
||||
return json;
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@RequestMapping("/system/get/ffmpeg.do")
|
||||
public JSONObject getFFmpeg(){
|
||||
public JSONObject getFFmpeg() {
|
||||
JSONObject json = new JSONObject();
|
||||
JSONObject data=new JSONObject();
|
||||
JSONObject data = new JSONObject();
|
||||
String reg = configService.getConfig(Config.SYSTEM_VIDEO_FFMPEG);
|
||||
data.put(Config.SYSTEM_VIDEO_FFMPEG, reg);
|
||||
json.put("code",0);
|
||||
json.put("data",data);
|
||||
json.put("code", 0);
|
||||
json.put("data", data);
|
||||
return json;
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@RequestMapping("/system/set/savelive.do")
|
||||
public JSONObject setSaveLive(String model) throws UnsupportedEncodingException {
|
||||
JSONObject json = new JSONObject();
|
||||
if (StringUtils.isEmpty(configService.getConfig(Config.SYSTEM_VIDEO_FFMPEG))) {
|
||||
json.put("code", 404);
|
||||
json.put("msg", "请先设置FFmpeg路径");
|
||||
return json;
|
||||
}
|
||||
model = URLDecoder.decode(model, "UTF-8");
|
||||
configService.setConfig(Config.SYSTEM_VIDEO_SAVE_MODEL, model);
|
||||
AppData.LIVE_SAVE_FFMPEG = model.equals("ffmpeg");
|
||||
json.put("code", 0);
|
||||
json.put("msg", "ok");
|
||||
return json;
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@RequestMapping("/system/get/savelive.do")
|
||||
public JSONObject getSaveLiveModel() {
|
||||
JSONObject json = new JSONObject();
|
||||
JSONObject data = new JSONObject();
|
||||
String reg = configService.getConfig(Config.SYSTEM_VIDEO_SAVE_MODEL);
|
||||
System.out.println(reg);
|
||||
data.put(Config.SYSTEM_VIDEO_SAVE_MODEL, (!StringUtils.isEmpty(reg) && reg.equals("ffmpeg")));
|
||||
json.put("code", 0);
|
||||
json.put("data", data);
|
||||
return json;
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@RequestMapping("/system/qq/login.do")
|
||||
public JSONObject loginQQ(){
|
||||
public JSONObject loginQQ() {
|
||||
QQBotManager.getInstance().stop();
|
||||
QQBotManager.getInstance().init();
|
||||
JSONObject json=new JSONObject();
|
||||
json.put("code",0);
|
||||
json.put("msg","ok");
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("code", 0);
|
||||
json.put("msg", "ok");
|
||||
return json;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -307,4 +307,26 @@ public class AppTools {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isRuntimeSystemOfWindow(){
|
||||
return System.getProperty ("os.name").contains("Windows");
|
||||
}
|
||||
|
||||
public static Process exec(String exec)throws Exception{
|
||||
if(AppTools.isRuntimeSystemOfWindow()) {
|
||||
return Runtime.getRuntime().exec(new String[]{
|
||||
"cmd",
|
||||
"/c",
|
||||
exec
|
||||
}
|
||||
);
|
||||
}else{
|
||||
return Runtime.getRuntime().exec(new String[]{
|
||||
"sh",
|
||||
"-c",
|
||||
exec
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
13
src/main/java/com/yutou/bilibili/Tools/ApplicationClose.java
Normal file
13
src/main/java/com/yutou/bilibili/Tools/ApplicationClose.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package com.yutou.bilibili.Tools;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextClosedEvent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class ApplicationClose implements ApplicationListener<ContextClosedEvent> {
|
||||
@Override
|
||||
public void onApplicationEvent(ContextClosedEvent contextClosedEvent) {
|
||||
Log.i("服务结束");
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
package com.yutou.bilibili.Tools;
|
||||
|
||||
import com.yutou.bilibili.BiliBili.Datas.AppData;
|
||||
import com.yutou.bilibili.BiliBili.Datas.LiveData;
|
||||
import com.yutou.bilibili.BiliBili.Live;
|
||||
import com.yutou.bilibili.BiliBili.LiveUtils;
|
||||
import com.yutou.bilibili.BiliBili.Services.IBiliBiliLiveService;
|
||||
import com.yutou.bilibili.Services.ISystemConfigService;
|
||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliLiveInfo;
|
||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliUpInfo;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
@@ -27,12 +29,16 @@ import java.util.TimerTask;
|
||||
public class ApplicationInit implements ApplicationRunner {
|
||||
@Resource
|
||||
IBiliBiliLiveService service;
|
||||
@Resource
|
||||
ISystemConfigService configService;
|
||||
private Timer timer;
|
||||
|
||||
|
||||
@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");
|
||||
startTimer();
|
||||
}
|
||||
|
||||
|
||||
@@ -4,4 +4,5 @@ public class Config {
|
||||
public static final String USER_REG="userReg";
|
||||
public static final String BILI_LIVE_FLAG="biliLive";
|
||||
public static final String SYSTEM_VIDEO_FFMPEG="ffmpeg_path";
|
||||
public static final String SYSTEM_VIDEO_SAVE_MODEL="save_live_model";
|
||||
}
|
||||
|
||||
@@ -39,12 +39,7 @@ public class FFmpegUtils {
|
||||
file.getAbsolutePath(),
|
||||
out.getAbsolutePath() + File.separator + file.getName());
|
||||
com.yutou.bilibili.Tools.Log.i(exec);
|
||||
Process process = Runtime.getRuntime().exec(new String[]{
|
||||
"cmd",
|
||||
"/c",
|
||||
exec
|
||||
}
|
||||
);
|
||||
Process process=AppTools.exec(exec);
|
||||
InputStream inputStream = process.getErrorStream();
|
||||
byte[] bytes = new byte[1024];
|
||||
while (inputStream.read(bytes) > -1) {
|
||||
|
||||
Reference in New Issue
Block a user