新增FFmpeg转码功能
This commit is contained in:
parent
ef87b719fd
commit
51a0a3d111
@ -28,6 +28,7 @@
|
||||
<script type="text/html" id="listTools">
|
||||
<a class="layui-btn layui-btn-xs" lay-event="play">播放</a>
|
||||
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="download">下载</a>
|
||||
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="ffmpeg">转码</a>
|
||||
</script>
|
||||
<script src="/layui/layui.js"></script>
|
||||
<script src="/js/jquery-3.2.1.js"></script>
|
||||
@ -47,9 +48,9 @@
|
||||
{field: 'name', title: 'UP主/房间号', width: 150, sort: true, fixed: 'left'}
|
||||
, {field: 'date', title: '日期', width: 120, sort: true}
|
||||
, {field: 'time', title: '时间', width: 80, sort: true}
|
||||
, {field: 'fileName', title: '文件名', width: 300}
|
||||
, {field: 'fileName', title: '文件名', width: 250}
|
||||
, {field: 'fileSize', title: '大小', width: 80}
|
||||
, {field: "right", width: 120, toolbar: '#listTools'}
|
||||
, {field: "right", width: 170, toolbar: '#listTools'}
|
||||
]]
|
||||
});
|
||||
table.on('tool(listTools)', function (obj) {
|
||||
@ -61,6 +62,15 @@
|
||||
case 'play':
|
||||
play("/download/" + obj.data.date + "/" + encodeURI(obj.data.fileName), obj.data.fileName);
|
||||
break;
|
||||
case 'ffmpeg':
|
||||
$.post('/bili/video/set/ffmpeg.do',{fileName:encodeURI(obj.data.fileName)},function (json) {
|
||||
if (json.code === undefined || json.code !== 0) {
|
||||
layer.msg("您无权操作")
|
||||
return;
|
||||
}
|
||||
layer.msg(json.msg)
|
||||
})
|
||||
break;
|
||||
}
|
||||
})
|
||||
|
||||
@ -79,20 +89,18 @@
|
||||
, area: ['640px', '480px']
|
||||
, maxmin: false
|
||||
, resize: false
|
||||
, content: '<div><video id="' + id + '" style="height: 100%;width: 100%">' +
|
||||
'</video><a href="javascript:;" class="layui-btn layui-btn-xs" id="pause">暂停/播放</a>' +
|
||||
, content: '<div><video id="' + id + '" style="height: 100%;width: 100%" controls>' +
|
||||
'</video><a href="javascript:;" class="layui-btn layui-btn-xs" id="reset">重播</a>' +
|
||||
'</video><a href="javascript:;" class="layui-btn layui-btn-xs" id="danmu">弹幕</a>' +
|
||||
'</video><a href="javascript:;" class="layui-btn layui-btn-xs" id="volume">静音</a>' +
|
||||
'</video><a href="javascript:;" class="layui-btn layui-btn-xs" id="seekDown">-10s</a>' +
|
||||
'</video><a href="javascript:;" class="layui-btn layui-btn-xs" id="seekUp">+10s</a>' +
|
||||
'<a href="javascript:;" class="layui-btn layui-btn-xs" id="danmu">弹幕</a>' +
|
||||
'<a href="javascript:;" class="layui-btn layui-btn-xs" id="seekDown">-10s</a>' +
|
||||
'<a href="javascript:;" class="layui-btn layui-btn-xs" id="seekUp">+10s</a>' +
|
||||
'</div>'
|
||||
, success: function (layero, index) {
|
||||
|
||||
layer.setTop(layero);
|
||||
let videoElement = document.getElementById(id);
|
||||
videoElement.onended=function (){
|
||||
layer.close(index)
|
||||
videoElement.onended = function () {
|
||||
layer.close(index)
|
||||
};
|
||||
let playerConfig = {
|
||||
enableWorker: false,
|
||||
@ -100,10 +108,14 @@
|
||||
stashInitialSize: 512 * 1024,
|
||||
enableStashBuffer: true
|
||||
}
|
||||
let playType = 'flv'
|
||||
if (url.indexOf('_ffmpeg') !== -1) {
|
||||
playType = 'mp4'
|
||||
}
|
||||
flvPlayer = flvjs.createPlayer({
|
||||
type: 'flv',
|
||||
type: playType,
|
||||
url: url
|
||||
},playerConfig)
|
||||
}, playerConfig)
|
||||
|
||||
flvPlayer.attachMediaElement(videoElement);
|
||||
flvPlayer.load();
|
||||
@ -114,7 +126,7 @@
|
||||
} else {
|
||||
flvPlayer.play();
|
||||
}
|
||||
isPlay=!isPlay;
|
||||
isPlay = !isPlay;
|
||||
})
|
||||
$('#reset').click(function () {
|
||||
flvPlayer.unload();
|
||||
|
@ -57,13 +57,23 @@
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">开放注册</label>
|
||||
<div class="layui-input-block">
|
||||
<input id="userReg" type="checkbox" lay-filter="userReg" lay-skin="switch" lay-text="开启|关闭">
|
||||
<input id="userReg" type="checkbox" lay-filter="userReg" lay-skin="switch"
|
||||
lay-text="开启|关闭">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">保存阿B数据</label>
|
||||
<div class="layui-input-block">
|
||||
<input id="saveBiliLive" type="checkbox" lay-filter="saveBiliLive" lay-skin="switch" lay-text="开启|关闭">
|
||||
<input id="saveBiliLive" type="checkbox" lay-filter="saveBiliLive" lay-skin="switch"
|
||||
lay-text="开启|关闭">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">FFmpeg</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" id="ffmpeg" required lay-verify="required"
|
||||
placeholder="ffmpeg绝对路径,回车保存"
|
||||
autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@ -135,6 +145,13 @@
|
||||
$('#bili_login_text').text(json.data.uname);
|
||||
$('#bili_icon_img').attr("src", json.data.icon);
|
||||
|
||||
})
|
||||
$.post('/system/get/ffmpeg.do', function (json) {
|
||||
if (json.code === undefined || json.code !== 0) {
|
||||
return;
|
||||
}
|
||||
$('#ffmpeg').val(json.data.ffmpeg_path);
|
||||
|
||||
})
|
||||
$('#login').click(function () {
|
||||
$.post('/bili/login/set/login.do', function (json) {
|
||||
@ -157,6 +174,14 @@
|
||||
})
|
||||
})
|
||||
})
|
||||
$('#ffmpeg').bind('keypress', function (event) {
|
||||
if (event.keyCode === 13) {
|
||||
$.post('/system/set/ffmpeg.do', {ffmpeg: encodeURI($('#ffmpeg').val())}, function (json) {
|
||||
layer.msg(json.msg)
|
||||
})
|
||||
event.preventDefault();
|
||||
}
|
||||
})
|
||||
$('#header').load("/html/header.html");
|
||||
$('#footer').load("/html/footer.html");
|
||||
|
||||
|
@ -5,8 +5,11 @@ import com.alibaba.fastjson.JSONObject;
|
||||
import com.yutou.bilibili.BiliBili.LiveUtils;
|
||||
import com.yutou.bilibili.BiliBili.Services.IBiliBiliLiveService;
|
||||
import com.yutou.bilibili.BiliBili.Tools.BiliTools;
|
||||
import com.yutou.bilibili.Services.ISystemConfigService;
|
||||
import com.yutou.bilibili.Services.IUserService;
|
||||
import com.yutou.bilibili.Tools.AppTools;
|
||||
import com.yutou.bilibili.Tools.Config;
|
||||
import com.yutou.bilibili.Tools.FFmpegUtils;
|
||||
import com.yutou.bilibili.Tools.ServiceTools;
|
||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliUpInfo;
|
||||
import com.yutou.bilibili.mybatis.model.UUser;
|
||||
@ -19,6 +22,8 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.File;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
@ -29,6 +34,8 @@ public class BiliVideoController {
|
||||
IUserService service;
|
||||
@Resource
|
||||
IBiliBiliLiveService liveService;
|
||||
@Resource
|
||||
ISystemConfigService configService;
|
||||
|
||||
@ResponseBody
|
||||
@RequestMapping("/bili/video/get/list.do")
|
||||
@ -52,9 +59,19 @@ public class BiliVideoController {
|
||||
List<File> list = AppTools.scanFilePath("live");
|
||||
JSONArray array = new JSONArray();
|
||||
for (File f : list) {
|
||||
JSONObject item = new JSONObject();
|
||||
String _time = f.getName().split(" ")[0].substring(1);
|
||||
File mpeg = new File("ffmpeg_out" + File.separator + _time + File.separator + f.getName());
|
||||
if (mpeg.exists()) {
|
||||
f = mpeg;
|
||||
item.put("ffmpeg", true);
|
||||
} else {
|
||||
item.put("ffmpeg", false);
|
||||
}
|
||||
String date = f.getName().split(" ")[0].substring(1);
|
||||
String time = f.getName().split(" ")[1].split("\\]")[0];
|
||||
String roomid = f.getName().split("\\]")[1].replace(".mp4", "").trim();
|
||||
String roomid = f.getName().split("\\]")[1].replace(".mp4", "").replace("_ffmpeg", "").trim();
|
||||
|
||||
BilibiliUpInfo info = liveService.queryUpToRoomId(Integer.parseInt(roomid));
|
||||
long size = f.length();
|
||||
String _size;
|
||||
@ -67,7 +84,7 @@ public class BiliVideoController {
|
||||
} else {
|
||||
_size = (size / 1073741824) + "GB";
|
||||
}
|
||||
JSONObject item = new JSONObject();
|
||||
|
||||
item.put("fileName", f.getName());
|
||||
item.put("fileSize", _size);
|
||||
item.put("date", date);
|
||||
@ -89,11 +106,34 @@ public class BiliVideoController {
|
||||
|
||||
@RequestMapping("/bili/video/download/get.do")
|
||||
public ResponseEntity<FileSystemResource> download(String fileName) {
|
||||
System.out.println(fileName);
|
||||
String time = fileName.split(" ")[0].substring(1);
|
||||
System.out.println(time);
|
||||
File file = new File("live" + File.separator + time + File.separator + fileName);
|
||||
File file = new File("ffmpeg_out" + File.separator + time + File.separator + fileName);
|
||||
if (!file.exists())
|
||||
file = new File("live" + File.separator + time + File.separator + fileName);
|
||||
System.out.println(file.getAbsolutePath());
|
||||
return AppTools.getFile(file);
|
||||
}
|
||||
@ResponseBody
|
||||
@RequestMapping("/bili/video/set/ffmpeg.do")
|
||||
public JSONObject ffmpegOut(String fileName) throws UnsupportedEncodingException {
|
||||
fileName= URLDecoder.decode(fileName,"UTF-8");
|
||||
JSONObject json=new JSONObject();
|
||||
json.put("code",0);
|
||||
json.put("msg","ok");
|
||||
String time = fileName.split(" ")[0].substring(1);
|
||||
File file = new File("live" + File.separator + time + File.separator + fileName);
|
||||
int i= FFmpegUtils.add(configService.getConfig(Config.SYSTEM_VIDEO_FFMPEG),file,new File("ffmpeg_out"+File.separator+time));
|
||||
json.put("model",i);
|
||||
switch (i){
|
||||
case 0:
|
||||
json.put("msg","已添加到后台转码");
|
||||
case 1:
|
||||
json.put("msg","已经转码,无须二次转码");
|
||||
break;
|
||||
case 2:
|
||||
json.put("msg","正在转码");
|
||||
break;
|
||||
}
|
||||
return json;
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
|
||||
@Controller
|
||||
public class SystemConfigController {
|
||||
@ -61,5 +63,25 @@ public class SystemConfigController {
|
||||
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");
|
||||
return json;
|
||||
}
|
||||
@ResponseBody
|
||||
@RequestMapping("/system/get/ffmpeg.do")
|
||||
public JSONObject getFFmpeg(){
|
||||
JSONObject json = 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);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
|
@ -248,4 +248,60 @@ public class AppTools {
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static boolean copyFileToName(String srcFileName,String destFileName,String fileName,boolean overlay) {
|
||||
File srcFile = new File(srcFileName);
|
||||
// 判断源文件是否存在
|
||||
if (!srcFile.exists()) {
|
||||
System.err.println("源文件不存在:"+srcFile.getAbsolutePath()+" > "+destFileName);
|
||||
return false;
|
||||
} else if (!srcFile.isFile()) {
|
||||
System.err.println("源文件是目录:"+srcFile.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 判断目标文件是否存在
|
||||
File destFile = new File(destFileName);
|
||||
// 如果目标文件所在目录不存在,则创建目录
|
||||
if (!destFile.exists()) {
|
||||
// 目标文件所在目录不存在
|
||||
if (!destFile.mkdirs()) {
|
||||
// 复制文件失败:创建目标文件所在目录失败
|
||||
System.err.println("创建文件夹失败:"+destFile.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
|
||||
}else{
|
||||
if(srcFileName.equals("Activity.smali")){
|
||||
System.out.println("文件夹已存在:"+destFileName);
|
||||
}
|
||||
}
|
||||
|
||||
// 复制文件
|
||||
int byteread = 0; // 读取的字节数
|
||||
InputStream in = null;
|
||||
OutputStream out = null;
|
||||
|
||||
try {
|
||||
if(fileName==null) {
|
||||
fileName=srcFile.getName();
|
||||
}
|
||||
in = new FileInputStream(srcFile);
|
||||
out = new FileOutputStream(destFile + File.separator +fileName );
|
||||
byte[] buffer = new byte[1024];
|
||||
|
||||
while ((byteread = in.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, byteread);
|
||||
}
|
||||
out.close();
|
||||
in.close();
|
||||
return true;
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,4 +3,5 @@ package com.yutou.bilibili.Tools;
|
||||
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";
|
||||
}
|
||||
|
79
src/main/java/com/yutou/bilibili/Tools/FFmpegUtils.java
Normal file
79
src/main/java/com/yutou/bilibili/Tools/FFmpegUtils.java
Normal file
@ -0,0 +1,79 @@
|
||||
package com.yutou.bilibili.Tools;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class FFmpegUtils {
|
||||
private static final List<File> nowFFmpegList = new ArrayList<>();
|
||||
|
||||
public static int add(String ffmpeg, File file, File out) {
|
||||
if (nowFFmpegList.contains(file)) {
|
||||
return 2;
|
||||
}
|
||||
File tmp = new File(file.getAbsolutePath().replace(".mp4", "_ffmpeg.mp4"));
|
||||
if (tmp.exists()) {
|
||||
return 1;
|
||||
} else {
|
||||
startFFmpeg(ffmpeg, file, out);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private synchronized static void startFFmpeg(String ffmpeg, File file, File out) {
|
||||
if (nowFFmpegList.contains(file)) {
|
||||
return;
|
||||
}
|
||||
nowFFmpegList.add(file);
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (!out.exists()) {
|
||||
out.mkdirs();
|
||||
}
|
||||
String exec = String.format(
|
||||
"%s -i \"%s\" -c:v copy -y \"%s\" ",
|
||||
ffmpeg,
|
||||
file.getAbsolutePath(),
|
||||
out.getAbsolutePath() + File.separator + file.getName());
|
||||
System.out.println(exec);
|
||||
Process process = Runtime.getRuntime().exec(new String[]{
|
||||
"cmd",
|
||||
"/c",
|
||||
exec
|
||||
}
|
||||
);
|
||||
InputStream inputStream = process.getErrorStream();
|
||||
byte[] bytes = new byte[1024];
|
||||
while (inputStream.read(bytes) > -1) {
|
||||
}
|
||||
inputStream.close();
|
||||
AppTools.copyFileToName(out.getAbsolutePath()+File.separator+file.getName(), file.getParent() + File.separator, file.getName().replace(".mp4", "_ffmpeg.mp4"), true);
|
||||
// file.delete();
|
||||
out.delete();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
nowFFmpegList.remove(file);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
File file = new File("D:\\ieda\\bilibili\\live\\2021-03-20\\[2021-03-20 003537]1064046.mp4");
|
||||
int i = -1;
|
||||
while (i != 1) {
|
||||
i = add("D:\\ffmpeg-4.3.1-2020-11-19-full_build\\bin\\ffmpeg.exe", file.getAbsoluteFile(), new File("ffmpeg_out"));
|
||||
System.out.println(i);
|
||||
try {
|
||||
Thread.sleep(300);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
System.out.println("转码完成");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user