优化下载
This commit is contained in:
parent
44d23b6bac
commit
d9919f4d26
@ -45,7 +45,7 @@ public class LiveRoomConfig {
|
|||||||
public static LiveRoomConfig buildConfig(String roomId){
|
public static LiveRoomConfig buildConfig(String roomId){
|
||||||
BiliLiveConfigDatabase database = new BiliLiveConfigDatabase();
|
BiliLiveConfigDatabase database = new BiliLiveConfigDatabase();
|
||||||
LiveConfigDatabaseBean bean = database.getConfig(new String(roomId));
|
LiveConfigDatabaseBean bean = database.getConfig(new String(roomId));
|
||||||
|
database.close();
|
||||||
LiveRoomConfig config = new LiveRoomConfig();
|
LiveRoomConfig config = new LiveRoomConfig();
|
||||||
config.setLoginUid(bean.getRecordUid());
|
config.setLoginUid(bean.getRecordUid());
|
||||||
config.setRoomId(bean.getRoomId());
|
config.setRoomId(bean.getRoomId());
|
||||||
|
@ -35,6 +35,6 @@ public class LoginCookieDatabaseBean extends AbsDatabasesBean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String toCookieString() {
|
public String toCookieString() {
|
||||||
return "SESSDATA=" + sessdta + "; Path=" + path + "; DedeUserID=" + dedeUserID + "; DedeUserID__ckMd5=" + dedeUserIDCkMd5 + "; bili_jct=" + biliJct + "; Expires=" + expires + "; Domain=" + domain + "; sid=" + sid + "; gourl=" + gourl;
|
return "SESSDATA=" + sessdta + "; Path=" + path + "; DedeUserID=" + dedeUserID + "; DedeUserID__ckMd5=" + dedeUserIDCkMd5 + "; bili_jct=" + biliJct + "; Expires=" + expires + "; Domain=" + domain + "; sid=" + sid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@ public class BiliLiveDatabase extends SQLiteManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void addSource(WSData bean) {
|
public void addSource(WSData bean) {
|
||||||
Log.i("BiliLiveDatabase.addSource", config.getRoomId());
|
// Log.i("BiliLiveDatabase.addSource", config.getRoomId());
|
||||||
add(new LiveSourceDatabaseBean(bean));
|
add(new LiveSourceDatabaseBean(bean));
|
||||||
addData(bean);
|
addData(bean);
|
||||||
}
|
}
|
||||||
|
@ -174,7 +174,7 @@ public class WebSocketManager {
|
|||||||
heartbeatTask.setSocket(this);
|
heartbeatTask.setSocket(this);
|
||||||
heartbeatTask.sendInitAuthData();
|
heartbeatTask.sendInitAuthData();
|
||||||
new Timer().schedule(heartbeatTask, 1000, 30000);
|
new Timer().schedule(heartbeatTask, 1000, 30000);
|
||||||
Log.i("WebSocketClientTh.onOpen", roomConfig);
|
Log.i("WebSocketClientTh.onOpen", roomConfig.getRoomId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -296,7 +296,7 @@ public class WebSocketManager {
|
|||||||
json.put("key", roomConfig.getLiveInfo().getToken());
|
json.put("key", roomConfig.getLiveInfo().getToken());
|
||||||
byte[] bytes = {0, 16, 0, 1, 0, 0, 0, 7, 0, 0, 0, 1};
|
byte[] bytes = {0, 16, 0, 1, 0, 0, 0, 7, 0, 0, 0, 1};
|
||||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
Log.i("bytes.length = " + bytes.length);
|
// Log.i("bytes.length = " + bytes.length);
|
||||||
Log.i(json);
|
Log.i(json);
|
||||||
outputStream.write(BytesUtils.toLH(json.toString().length() + 16));
|
outputStream.write(BytesUtils.toLH(json.toString().length() + 16));
|
||||||
outputStream.write(bytes);
|
outputStream.write(bytes);
|
||||||
|
@ -36,6 +36,7 @@ public class LiveVideoController {
|
|||||||
public JSONObject startDownload(String roomId) {
|
public JSONObject startDownload(String roomId) {
|
||||||
BiliLiveConfigDatabase liveConfigDatabase = new BiliLiveConfigDatabase();
|
BiliLiveConfigDatabase liveConfigDatabase = new BiliLiveConfigDatabase();
|
||||||
List<LiveConfigDatabaseBean> list = liveConfigDatabase.getAllConfig();
|
List<LiveConfigDatabaseBean> list = liveConfigDatabase.getAllConfig();
|
||||||
|
liveConfigDatabase.close();
|
||||||
for (LiveConfigDatabaseBean bean : list) {
|
for (LiveConfigDatabaseBean bean : list) {
|
||||||
if (bean.getRoomId().toString().equals(roomId)) {
|
if (bean.getRoomId().toString().equals(roomId)) {
|
||||||
videoService.start(bean, true);
|
videoService.start(bean, true);
|
||||||
|
@ -62,6 +62,9 @@ public class DateFormatUtils {
|
|||||||
|
|
||||||
public Date parse(String date, String format) {
|
public Date parse(String date, String format) {
|
||||||
try {
|
try {
|
||||||
|
if(date.startsWith("1")){
|
||||||
|
return new Date(Long.parseLong(date));
|
||||||
|
}
|
||||||
return getFormat(format).parse(date);
|
return getFormat(format).parse(date);
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
System.err.println("Error parsing date: " + e.getMessage());
|
System.err.println("Error parsing date: " + e.getMessage());
|
||||||
|
@ -1,9 +1,15 @@
|
|||||||
package com.yutou.bilibili.Tools;
|
package com.yutou.bilibili.Tools;
|
||||||
|
|
||||||
import com.yutou.common.utils.AppTools;
|
import com.yutou.common.utils.AppTools;
|
||||||
|
import com.yutou.common.utils.Base64Tools;
|
||||||
|
import com.yutou.common.utils.Log;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
public class ProcessUtils {
|
public class ProcessUtils {
|
||||||
@ -31,35 +37,46 @@ public class ProcessUtils {
|
|||||||
if (pid == null) {
|
if (pid == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
String command;
|
String[] command;
|
||||||
if (isRuntimeSystemOfWindow()) {
|
if (isRuntimeSystemOfWindow()) {
|
||||||
// Windows 操作系统
|
// Windows 操作系统
|
||||||
command = "tasklist /FI \"PID eq " + pid + "\"";
|
command = new String[]{"cmd.exe", "/c", "tasklist /FI \"PID eq " + pid + "\""};
|
||||||
} else {
|
} else {
|
||||||
// Unix/Linux 操作系统
|
// Unix/Linux 操作系统
|
||||||
command = "ps -p " + pid;
|
command = new String[]{"sh", "-c", "ps -p " + pid};
|
||||||
}
|
}
|
||||||
|
|
||||||
Process process = exec(command);
|
Process process = Runtime.getRuntime().exec(command);
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
boolean isRunning = false;
|
||||||
|
try {
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8));
|
||||||
String line;
|
String line;
|
||||||
while ((line = reader.readLine()) != null) {
|
while ((line = reader.readLine()) != null) {
|
||||||
if (line.contains(Long.toString(pid))) {
|
if (line.contains(String.valueOf(pid))) {
|
||||||
return true;
|
isRunning = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
reader.close();
|
||||||
|
process.destroy();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return isRunning;
|
||||||
|
}
|
||||||
|
|
||||||
public static Process exec(String exec) throws Exception {
|
public static Process exec(String exec) throws Exception {
|
||||||
if(isRuntimeSystemOfWindow()){
|
if (isRuntimeSystemOfWindow()) {
|
||||||
return exec("cmd.exe","/c",exec);
|
return exec("cmd.exe", "/c", exec);
|
||||||
}else{
|
} else {
|
||||||
return exec("sh","-c",exec);
|
return exec("sh", "-c", exec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Process exec(String... command) throws Exception {
|
public static Process exec(String... command) throws Exception {
|
||||||
ProcessBuilder pb;
|
ProcessBuilder pb;
|
||||||
pb = new ProcessBuilder(command);
|
List<String> list = Arrays.stream(command).map(Base64Tools::decode).toList();
|
||||||
|
pb = new ProcessBuilder(list);
|
||||||
return pb.start();
|
return pb.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,9 +18,11 @@ import com.yutou.biliapi.enums.LiveVideoCodec;
|
|||||||
import com.yutou.biliapi.enums.LiveVideoDefinition;
|
import com.yutou.biliapi.enums.LiveVideoDefinition;
|
||||||
import com.yutou.biliapi.enums.LiveVideoFormat;
|
import com.yutou.biliapi.enums.LiveVideoFormat;
|
||||||
import com.yutou.biliapi.net.BiliLiveNetApiManager;
|
import com.yutou.biliapi.net.BiliLiveNetApiManager;
|
||||||
|
import com.yutou.biliapi.net.WebSignManager;
|
||||||
import com.yutou.bilibili.Tools.DateFormatUtils;
|
import com.yutou.bilibili.Tools.DateFormatUtils;
|
||||||
import com.yutou.bilibili.Tools.FileServerUtils;
|
import com.yutou.bilibili.Tools.FileServerUtils;
|
||||||
import com.yutou.bilibili.Tools.LiveInfoNfoTools;
|
import com.yutou.bilibili.Tools.LiveInfoNfoTools;
|
||||||
|
import com.yutou.bilibili.Tools.ProcessUtils;
|
||||||
import com.yutou.bilibili.datas.VideoFilePath;
|
import com.yutou.bilibili.datas.VideoFilePath;
|
||||||
import com.yutou.bilibili.interfaces.DownloadInterface;
|
import com.yutou.bilibili.interfaces.DownloadInterface;
|
||||||
import com.yutou.common.okhttp.HttpCallback;
|
import com.yutou.common.okhttp.HttpCallback;
|
||||||
@ -36,6 +38,7 @@ import org.springframework.util.StringUtils;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ArrayBlockingQueue;
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@ -78,13 +81,13 @@ public class LiveVideoDownloadService {
|
|||||||
VideoTask task = new VideoTask(bean, response);
|
VideoTask task = new VideoTask(bean, response);
|
||||||
executor.execute(task);
|
executor.execute(task);
|
||||||
} else {
|
} else {
|
||||||
Log.i("移除下载");
|
Log.i(bean.getRoomId(), "没有开播");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(Throwable throwable) {
|
public void onFailure(Throwable throwable) {
|
||||||
Log.i("移除下载");
|
Log.e(throwable, "移除下载");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -195,8 +198,29 @@ public class LiveVideoDownloadService {
|
|||||||
LiveVideoDefinition.ORIGINAL.getValue()).enqueue(new HttpCallback<LiveRoomPlayInfo>() {
|
LiveVideoDefinition.ORIGINAL.getValue()).enqueue(new HttpCallback<LiveRoomPlayInfo>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(Headers headers, int code, String status, LiveRoomPlayInfo response, String rawResponse) {
|
public void onResponse(Headers headers, int code, String status, LiveRoomPlayInfo response, String rawResponse) {
|
||||||
LiveRoomPlayInfo.Codec codec = response.getPlayurlInfo().getPlayurl().getStream().get(0).getFormat().get(0).getCodec().get(0);
|
Random random = new Random();
|
||||||
String url = codec.getUrlInfo().get(0).getHost() + codec.getBaseUrl() + codec.getUrlInfo().get(0).getExtra();
|
List<LiveRoomPlayInfo.Stream> streams = response.getPlayurlInfo().getPlayurl().getStream();
|
||||||
|
List<LiveRoomPlayInfo.Stream> streamList = streams.stream()
|
||||||
|
.filter(it -> "http_stream".equals(it.getProtocolName()))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
LiveRoomPlayInfo.Stream stream = streamList.get(random.nextInt(streamList.size()));
|
||||||
|
if (stream == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<LiveRoomPlayInfo.Format> formats = stream.getFormat().stream().filter(it -> "flv".equals(it.getFormatName())).toList();
|
||||||
|
LiveRoomPlayInfo.Format format = formats.get(random.nextInt(formats.size()));
|
||||||
|
|
||||||
|
List<LiveRoomPlayInfo.Codec> codecs = format.getCodec().stream().filter(item -> "avc".equals(item.getCodecName())).toList();
|
||||||
|
|
||||||
|
LiveRoomPlayInfo.Codec codec = codecs.get(random.nextInt(codecs.size()));
|
||||||
|
|
||||||
|
int urlIndex = random.nextInt(codec.getUrlInfo().size());
|
||||||
|
LiveRoomPlayInfo.UrlInfo urlInfo = codec.getUrlInfo().get(urlIndex);
|
||||||
|
|
||||||
|
|
||||||
|
String url = urlInfo.getHost() + codec.getBaseUrl() + urlInfo.getExtra();
|
||||||
|
Log.i("下载直播",rawResponse,codec.toString(),urlInfo.toString(),"URL:"+url);
|
||||||
|
|
||||||
if (bean.getRecordLiveModel() == 1) {
|
if (bean.getRecordLiveModel() == 1) {
|
||||||
javaRecord(url, response);
|
javaRecord(url, response);
|
||||||
@ -253,32 +277,46 @@ public class LiveVideoDownloadService {
|
|||||||
|
|
||||||
FFmpegUtils.Builder builder = new FFmpegUtils.Builder()
|
FFmpegUtils.Builder builder = new FFmpegUtils.Builder()
|
||||||
.withParam("-user_agent", ConfigTools.getUserAgent())
|
.withParam("-user_agent", ConfigTools.getUserAgent())
|
||||||
.withParam("-headers", "Referer: https://live.bilibili.com")
|
.withParam("-headers", "Referer: https://live.bilibili.com/" + playInfo.getRoomId())
|
||||||
|
// .withNotSymbolParam("-reconnect", "1")
|
||||||
|
// .withNotSymbolParam("-reconnect_at_eof", "1")
|
||||||
|
// .withNotSymbolParam("-reconnect_streamed", "1")
|
||||||
|
// .withNotSymbolParam("-reconnect_delay_max", "2")
|
||||||
|
// .withNotSymbolParam("-loglevel", "error")
|
||||||
// .withNotSymbolParam("-progress", "-")
|
// .withNotSymbolParam("-progress", "-")
|
||||||
|
// .withNotSymbolParam("-fflags", "+genpts")
|
||||||
.withNotSymbolParam("-threads", "8")
|
.withNotSymbolParam("-threads", "8")
|
||||||
.withNotSymbolParam("-c:v", "copy")
|
.withNotSymbolParam("-bufsize", "10M")
|
||||||
.withNotSymbolParam("-fflags", "+genpts")
|
.withNotSymbolParam("-c", "copy")
|
||||||
|
.withNotSymbolParam("-bsf:a", "aac_adtstoasc")
|
||||||
|
// .withNotSymbolParam("-loglevel", "debug")
|
||||||
.withNotSymbolParam("-y", "")
|
.withNotSymbolParam("-y", "")
|
||||||
//-reconnect 1 -reconnect_at_eof 1 -reconnect_streamed 1 -reconnect_delay_max 2
|
//-reconnect 1 -reconnect_at_eof 1 -reconnect_streamed 1 -reconnect_delay_max 2
|
||||||
.withNotSymbolParam("-reconnect", "1")
|
|
||||||
.withNotSymbolParam("-reconnect_at_eof", "1")
|
|
||||||
.withNotSymbolParam("-reconnect_streamed", "1")
|
|
||||||
.withNotSymbolParam("-reconnect_delay_max", "2")
|
|
||||||
.withNotSymbolParam("-loglevel", "error")
|
|
||||||
// .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);
|
||||||
Log.i(command.getCommand());
|
Log.i(command.getCommandDecode());
|
||||||
try {
|
try {
|
||||||
command.start(new DownloadInterface() {
|
command.start(new DownloadInterface() {
|
||||||
|
TimerTask task = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDownloadStart() {
|
public void onDownloadStart() {
|
||||||
super.onDownloadStart();
|
super.onDownloadStart();
|
||||||
|
task = new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
VideoTask.this.onStart();
|
VideoTask.this.onStart();
|
||||||
Log.i("启动录制:" + playInfo.getRoomId());
|
Log.i("启动录制:" + playInfo.getRoomId());
|
||||||
|
task = null;
|
||||||
|
cancel();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
new Timer().schedule(task, 5 * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -289,6 +327,10 @@ public class LiveVideoDownloadService {
|
|||||||
@Override
|
@Override
|
||||||
public void onDownload(File file) {
|
public void onDownload(File file) {
|
||||||
super.onDownload(file);
|
super.onDownload(file);
|
||||||
|
if (task != null) {
|
||||||
|
task.cancel();
|
||||||
|
task = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -386,7 +428,7 @@ public class LiveVideoDownloadService {
|
|||||||
videoFile = new File(videoInfo.getPath());
|
videoFile = new File(videoInfo.getPath());
|
||||||
}
|
}
|
||||||
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.getCommand());
|
System.out.println(ffmpeg.getCommandDecode());
|
||||||
ffmpeg.start(new DownloadInterface() {
|
ffmpeg.start(new DownloadInterface() {
|
||||||
@Override
|
@Override
|
||||||
public void onDownload(File file) {
|
public void onDownload(File file) {
|
||||||
|
@ -13,7 +13,11 @@ public class Base64Tools {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String decode(String str) {
|
public static String decode(String str) {
|
||||||
|
try {
|
||||||
return new String(Base64.getDecoder().decode(str));
|
return new String(Base64.getDecoder().decode(str));
|
||||||
|
} catch (Exception e) {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String encode(byte[] bytes) {
|
public static String encode(byte[] bytes) {
|
||||||
@ -31,5 +35,6 @@ public class Base64Tools {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
System.out.println(decode("aHR0cHM6Ly9jbi16ampoLWN0LTA0LTA2LmJpbGl2aWRlby5jb20vbGl2ZS1idmMvMzE1MDQ2L2xpdmVfMjY5NDE1MzU3Xzk4Mjc2ODIuZmx2P2V4cGlyZXM9MTczMjYwNDIyOCZwdD13ZWImZGVhZGxpbmU9MTczMjYwNDIyOCZsZW49MCZvaT0yOTM2NjQ2MjYwJnBsYXRmb3JtPXdlYiZxbj0xMDAwMCZ0cmlkPTEwMDAwZTUzYTY2ZjBiNWFjMDgwNGMwMDBhZGI5MTY3NDU2MyZ1aXBrPTEwMCZ1aXB2PTEwMCZuYnM9MSZ1cGFyYW1zPWNkbixkZWFkbGluZSxsZW4sb2kscGxhdGZvcm0scW4sdHJpZCx1aXBrLHVpcHYsbmJzJmNkbj1jbi1nb3RjaGEwMSZ1cHNpZz1iOGZhNjQyNGYxM2E1MDUwZThkNGRkZDc1NDcyOGYwYiZzaXRlPWRhYTczMDFjYmM5YzgwMjA1MTk4MDZmYmM4YzA4MmI2JmZyZWVfdHlwZT0wJm1pZD05NjMwMCZzY2hlPWJhbiZzaWQ9Y24tempqaC1jdC0wNC0wNiZjaGFzaD0xJmJtdD0xJnNnPWxyJnRyYWNlPTE3JmlzcD1jdCZyZz1DZW50cmFsJnB2PUh1bmFuJnNsPTImcHA9cnRtcCZwMnBfdHlwZT0xJmRlcGxveV9lbnY9cHJvZCZzdWZmaXg9b3JpZ2luJm9yaWdpbl9iaXRyYXRlPTc2OTczNiZzb3VyY2U9cHV2M19vbmV0aWVyJnNrPTQ5Yzc3YTNjMDBlY2M0NzI2ZjdlMGU1YTEzZjM5ZjYzJnNjb3JlPTUyJmhvdF9jZG49NTczNTMmdmQ9bmMmem9uZWlkX2w9MTUxMzg4MTYxJnNpZF9sPWxpdmVfMjY5NDE1MzU3Xzk4Mjc2ODImc3JjPXB1djMmb3JkZXI9MQ=="));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,14 +10,18 @@ import org.springframework.util.StringUtils;
|
|||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class FFmpegUtils extends AbsVideoRecord {
|
public class FFmpegUtils extends AbsVideoRecord {
|
||||||
private static final Map<String, Task> pidMap = new HashMap<>();
|
private static final Map<String, Task> pidMap = new HashMap<>();
|
||||||
@Getter
|
|
||||||
private String command;
|
private String command;
|
||||||
@Getter
|
@Getter
|
||||||
private String outputFilePath;
|
private String outputFilePath;
|
||||||
private String uid;
|
private String uid;
|
||||||
|
@Getter
|
||||||
|
private String commandDecode;
|
||||||
|
@Getter
|
||||||
|
private Long pid;
|
||||||
|
|
||||||
public FFmpegUtils() {
|
public FFmpegUtils() {
|
||||||
}
|
}
|
||||||
@ -88,6 +92,7 @@ public class FFmpegUtils extends AbsVideoRecord {
|
|||||||
.withParam("-y", outputPath + File.separator + "course-%04d.ts")
|
.withParam("-y", outputPath + File.separator + "course-%04d.ts")
|
||||||
.getCommand(ffmpegPath, video.getAbsolutePath(), null);
|
.getCommand(ffmpegPath, video.getAbsolutePath(), null);
|
||||||
ffmpeg.outputFilePath = "video.m3u8";
|
ffmpeg.outputFilePath = "video.m3u8";
|
||||||
|
ffmpeg.commandDecode= Arrays.stream(ffmpeg.command.split(" ")).map(Base64Tools::decode).collect(Collectors.joining(" "));
|
||||||
return ffmpeg;
|
return ffmpeg;
|
||||||
}
|
}
|
||||||
// ffmpeg 切片
|
// ffmpeg 切片
|
||||||
@ -111,20 +116,20 @@ public class FFmpegUtils extends AbsVideoRecord {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getCommand(String ffmpegPath, String inputUrl, String outputPath) {
|
private String getCommand(String ffmpegPath, String inputUrl, String outputPath) {
|
||||||
StringBuilder command = new StringBuilder(ffmpegPath);
|
StringBuilder command = new StringBuilder(Base64Tools.encode(ffmpegPath));
|
||||||
|
|
||||||
command.append(" -i ").append("\"").append(inputUrl).append("\"");
|
command.append(" ").append(Base64Tools.encode("-re")).append(" ").append(Base64Tools.encode("-i")).append(" ").append(Base64Tools.encode("\""+inputUrl+"\""));
|
||||||
for (Map.Entry<String, String> entry : params.entrySet()) {
|
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||||
if (StringUtils.hasText(entry.getKey())) {
|
if (StringUtils.hasText(entry.getKey())) {
|
||||||
command.append(" ");
|
command.append(" ");
|
||||||
command.append(entry.getKey());
|
command.append(Base64Tools.encode(entry.getKey()));
|
||||||
}
|
}
|
||||||
if (entry.getValue() != null && !entry.getValue().isEmpty()) {
|
if (entry.getValue() != null && !entry.getValue().isEmpty()) {
|
||||||
command.append(" ").append(entry.getValue());
|
command.append(" ").append(Base64Tools.encode(entry.getValue()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (outputPath != null) {
|
if (outputPath != null) {
|
||||||
command.append(" ").append("\"").append(outputPath).append("\"");
|
command.append(" ").append(Base64Tools.encode("\""+outputPath+"\""));
|
||||||
}
|
}
|
||||||
return command.toString();
|
return command.toString();
|
||||||
|
|
||||||
@ -133,6 +138,7 @@ public class FFmpegUtils extends AbsVideoRecord {
|
|||||||
public FFmpegUtils build(String uid, String ffmpegPath, String inputUrl, String outputPath) {
|
public FFmpegUtils build(String uid, String ffmpegPath, String inputUrl, String outputPath) {
|
||||||
FFmpegUtils ffmpeg = new FFmpegUtils();
|
FFmpegUtils ffmpeg = new FFmpegUtils();
|
||||||
ffmpeg.command = getCommand(ffmpegPath, inputUrl, outputPath);
|
ffmpeg.command = getCommand(ffmpegPath, inputUrl, outputPath);
|
||||||
|
ffmpeg.commandDecode= Arrays.stream(ffmpeg.command.split(" ")).map(Base64Tools::decode).collect(Collectors.joining(" "));
|
||||||
ffmpeg.outputFilePath = outputPath;
|
ffmpeg.outputFilePath = outputPath;
|
||||||
ffmpeg.uid = uid;
|
ffmpeg.uid = uid;
|
||||||
return ffmpeg;
|
return ffmpeg;
|
||||||
@ -141,7 +147,9 @@ public class FFmpegUtils extends AbsVideoRecord {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(DownloadInterface downloadInterface) {
|
public void start(DownloadInterface downloadInterface) {
|
||||||
new Task(downloadInterface).start();
|
Task task = new Task(downloadInterface);
|
||||||
|
task.start();
|
||||||
|
pid= task.pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -194,7 +202,7 @@ public class FFmpegUtils extends AbsVideoRecord {
|
|||||||
super.run();
|
super.run();
|
||||||
try {
|
try {
|
||||||
if (check(uid)) {
|
if (check(uid)) {
|
||||||
kill();
|
return;
|
||||||
}
|
}
|
||||||
Process process = ProcessUtils.exec(command.split(" "));
|
Process process = ProcessUtils.exec(command.split(" "));
|
||||||
pid = process.toHandle().pid();
|
pid = process.toHandle().pid();
|
||||||
@ -207,7 +215,10 @@ public class FFmpegUtils extends AbsVideoRecord {
|
|||||||
}
|
}
|
||||||
pidMap.put(uid, this);
|
pidMap.put(uid, this);
|
||||||
long startTimer = System.currentTimeMillis();
|
long startTimer = System.currentTimeMillis();
|
||||||
while (inputStream.read(bytes) > -1) {
|
ByteArrayOutputStream os=new ByteArrayOutputStream();
|
||||||
|
int len;
|
||||||
|
while ((len=inputStream.read(bytes)) > -1) {
|
||||||
|
os.write(bytes, 0, len);
|
||||||
if (downloadInterface != null) {
|
if (downloadInterface != null) {
|
||||||
downloadInterface.onDownloading(System.currentTimeMillis() - startTimer, 0);
|
downloadInterface.onDownloading(System.currentTimeMillis() - startTimer, 0);
|
||||||
}
|
}
|
||||||
@ -216,11 +227,12 @@ public class FFmpegUtils extends AbsVideoRecord {
|
|||||||
//获取视频时长:ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 input.mp4
|
//获取视频时长:ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 input.mp4
|
||||||
//获取到结果:5372.432000
|
//获取到结果:5372.432000
|
||||||
if (downloadInterface != null) {
|
if (downloadInterface != null) {
|
||||||
Log.i("触发下载完成", command);
|
//Log.i("触发下载完成", command);
|
||||||
|
Log.i("触发下载完成", new String(os.toByteArray()));
|
||||||
downloadInterface.onDownload(null);
|
downloadInterface.onDownload(null);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
Log.e(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user