此文感谢B站up主 @FurryTech无私奉献
解密步骤(二进制文件)
1、删除开头9个‘0’
2、把‘$’(24)换成空格(20)
3、删除‘avc1’(61 76 63 31)
用java代码做解密与生成命令
用 ffmpeg软件做视频、音频合并 FFmpeg官网
ffmpeg合并命令
ffmpeg -i (视频m4s-1-30080).m4s -i (音频m4s-1-30280).m4s -codec copy (输出文件).mp4
路径
private final static String sourcePath = "F:\\temp\\source\\"; //b站缓存文件夹
private final static String dist1Path = "F:\\temp\\dist1\\"; //解码视频文件夹
private final static String dist2Path = "F:\\temp\\dist2\\"; //解码音频文件夹
private final static String dist3Path = "F:\\temp\\dist3\\"; //视频合并文件夹
private final static String ffmpegPath = "D:\\Soft\\ffmpeg\\bin\\ffmpeg.exe "; //ffmpeg文件
解密方法(视频音频方法一样)
//解密 视频
public static void decryt() throws Exception{
File basePathFile = new File(sourcePath);
File[] fileSecends = basePathFile.listFiles();
for (File fileSecend : fileSecends) {
String name = fileSecend.getName();
if ("load_log".equals(name)) { //跳过 load_log 文件
continue;
}
String file = fileSecend.getAbsoluteFile() + "\\" + name + "-1-30080.m4s"; //30080-dist1 30280-dist2
RandomAccessFile rw = new RandomAccessFile(file, "r");
byte[] header = new byte[50]; //读前50个字节
rw.seek(0);
rw.read(header, 0, 50);
byte[] bytes = Arrays.copyOfRange(header, 9, 50); //解密第一步 删除开头9个‘0’
bytes[3] = (byte) 0x20; //解密第二步 把‘$’(24)换成空格(20)
byte[] bytes1 = Arrays.copyOfRange(bytes, 0, 24);
byte[] bytes2 = Arrays.copyOfRange(bytes, 28, 41);
byte[] bytes3 = new byte[bytes1.length + bytes2.length];
System.arraycopy(bytes1, 0, bytes3, 0, bytes1.length);
System.arraycopy(bytes2, 0, bytes3, bytes1.length, bytes2.length); //解密第三步 删除‘avc1’(61 76 63 31)
rw.close();
FileOutputStream output = new FileOutputStream(dist1Path + "\\" + name + ".m4s");
output.write(bytes3);
FileInputStream input = new FileInputStream(file);
input.read(header, 0, 50);
byte[] buffer = new byte[1024];
int read = 0;
while ((read = input.read(buffer)) != -1) {
output.write(buffer, 0, read);
}
input.close();
output.close();
}
}
解密音频代码只需将 -1-30080.m4s 换成 -1-30280.m4s, dist1Path 目录换成 dist2Path 再运行一遍
合并方法
//合并
public static void merger() throws Exception{
TypeReference<Map<String, Object>> tr = new TypeReference<Map<String, Object>>() {};
ObjectMapper om = new ObjectMapper();
File basePathFile = new File(dist1Path);
File[] files = basePathFile.listFiles();
for (File file : files) {
String name = file.getName();
File json = new File(sourcePath + name.replace(".m4s","") + "\\" + "videoInfo.json");
Map<String, Object> map = om.readValue(json, tr);
String title = (String) map.get("title");
title = title.replaceAll("[\\\\/:*?\"<>|]", "").replace(" ", "_");
String cmd = ffmpegPath + "-i " + dist1Path + name + " -i " + dist2Path + name + " -codec copy " + dist3Path + title + ".mp4";
System.out.println(cmd);
}
}
注:在videoInfo.json中取视频名作为MP4文件名称
把上述代码放在main方法中跑一遍即可得到ffmpeg 合成命令(如下)
D:\Soft\ffmpeg\bin\ffmpeg.exe -i F:\bilibili\dist1\27300987951.m4s -i F:\temp\dist2\27300987951.m4s -codec copy F:\temp\dist3\[1.1]--1-1-导学.mp4
将此命令保存在bat文件中,执行即可(注意bat文件的编码)