前言

使用哔哩哔哩手机客户端下载的视频在电脑上播放,无奈视频是分段的,每次都只好手动的合并再播放。而且客户端下载的视频不会按网页文件名命名,而是以av号--全数字命名。最可怕的是,每次打开一集的时候,进入的目录层级得吓死人。

视频层级

最最可怕的是,新版客户端默认文件后缀是.blv难道我们要一个一个重命名然后再合并吗?

NO!这种重复的事情交给计算机就好了。自己动手丰衣足食,我们就动手写个JAVA版的哔哩哔哩视频合并小程序。

实现功能

1.自动识别文件夹下视频文件并进行合并

2.合并后以视频播放页视频名称+视频分P名称命名

F:\(日剧)夺爱之冬\第一话.flv

3.合并完成删除源文件

前期准备

1.得到哔哩哔哩客户端下载的视频目录

将哔哩哔哩手机客户端下载的视频移出手机的Android目录,如移动到根目录

因android MTP限制,电脑无法访问Android目录。此目录是Android应用缓存目录。

视频位于 Android--data--tv.danmaku.bili(最下面)--download下。如图显示的数字目录即为需求目录。请将数字目录移出Android目录外。

手机连上电脑后,将上述数字目录复制或移动到电脑。

2.分析视频目录结构

8896746\1\entry.json 这个json包含了整个播放目录的名称和每一P的名称

8896746\1\lua.flv.bili2api.3\0.blv 这个文件夹就是各分段视频文件了。

注意:视频文件命名逻辑是:0.blv,1.blv...9.blv,10.blv...

也就是说,一旦视频文件超过10个,如 0-10,合并的时候会出现这样的合并顺序:0.blv--1.blv--10.blv--2.blv...

所以说,我们需要先把 0.blv-9.blv 重命名为 00.blv-09.blv

3.FLV科普

FLV是一个二进制文件,由文件头(FLV header)和很多tag组成。tag又可以分成三类:audio,video,script,分别代表音频流,视频流,脚本流(关键字或者文件信息之类)。

FLV文件=FLV头文件+ tag1+tag内容1 + tag2+tag内容2 + ...+... + tagN+tag内容N。

也就是说合并FLV分段视频的时候不能简单粗暴的将多个flv视频片段按字节流的方式写到一个文件中。

这时候来看FLV合并的原理:

(1) flv 文件由1个header和若干个tag组成;

(2) header记录了视频的元数据;

(3) tag 是有时间戳的数据;

(4) flv合并的原理就是把多个文件里的tag组装起来,调整各tag的时间戳。

(5)判断是否为第一个文件,是则安装头部。

了解了这些就可以动手撰写我们的合并程序了。Let's go.

流程逻辑

提示输入哔哩哔哩下载的视频文件夹(输入文件夹),输入输出的文件夹。

因最后合并完成后要删除源文件,故要求输出文件夹不能和输入文件夹相同。

一次输入多个输入文件夹以英文逗号隔开。

然后进入输入文件夹下-- entry.json 得到视频名称,和输入文件夹拼接创建目录。

如:输出到 F:\\视频名称 文件夹

执行合并

listFiles()执行两次进入到这个文件夹

entry.json得到视频每一P的名称,拼接输出如F:\\视频名称\第一话.flv

判断进入lua.flv.bili2api.3文件夹即可得到所有视频文件

判断对 0.flv-9.flv 进行重命名---> 00.flv-09.flv

进行合并操作

删除源文件

程序

1.首先eclipse建项目

包结构很简单

包结构

2.输入输出文件夹

包含main方法的Bilibili.java

输入输出文件夹

File out;

File[] in = null;

while(true){

boolean isBreak = true;

Scanner scanner = new Scanner(System.in);

String line = scanner.nextLine();

if(line == null || line.length() == 0){

System.out.println("输入不为空,请重试:");

isBreak = false;

}else{

String[] lines = line.split(",");

in = new File[lines.length];

for(int i = 0;i < lines.length;i++){

in[i] = new File(lines[i]);

if(!in[i].exists()){

System.out.println(in[i].getAbsolutePath() + "文件夹不存在,请重试:");

isBreak = false;

break;

}

}

}

if(isBreak){

break;

}

}

System.out.println("请输入输出路径:");

while(true){

Scanner scanner = new Scanner(System.in);

String line = scanner.nextLine();

out = new File(line);

if(!out.exists()){

System.out.println("文件夹不存在,请重试:");

}else{

boolean isEquals = true;

for(int i = 0;i < in.length;i++){

if(out.getAbsolutePath().equals(in[i].getAbsolutePath())){

isEquals = false;

System.out.println("输出路径和某个输入路径相同,请重试:");

break;

}

}

if(isEquals){

break;

}

}

}

3.循环读取多个输入目录的视频名称

//循环

for(int i = 0;i < in.length;i++){

//得到播放文件名,如"(日剧)夺爱之冬"

String path = in[i].getAbsolutePath() +separator+ "1"+separator+"entry.json";

String line = null;

try {

BufferedReader reader =

new BufferedReader(new InputStreamReader(new FileInputStream(path), Charset.forName("utf-8")));

line = reader.readLine();

reader.close();

System.out.println("json="+line);

} catch (Exception e) {

e.printStackTrace();

}

//输出路径

String[] names = tool.json_getName(line);

String episode_path = out.getAbsolutePath() + separator + names[0];

File episode = new File(episode_path);

if(!episode.exists()){

episode.mkdirs();

}

System.out.println("输出:"+episode_path);

//合并

tool.doMerge(in[i], episode_path);

}

4.判断对 0.flv-9.flv 进行重命名---> 00.flv-09.flv 后合并

public void doMerge(File in,String episode_path){

//1、2、3、4...

File[] files = in.listFiles();

//循环

for(File f : files){

//文件名,如第一话

String name = null;

//获得所有名为.blv的文件

File[] ffs = null;

File[] fs = f.listFiles();

for(final File ff : fs){

if(ff.getName().equals("entry.json")){

String json_name = null;

try {

BufferedReader reader =

new BufferedReader(new InputStreamReader(new FileInputStream(ff), Charset.forName("utf-8")));

json_name = reader.readLine();

reader.close();

} catch (Exception e) {

e.printStackTrace();

}

name = json_getName(json_name)[1];

}

if(ff.isDirectory() && ff.getName().startsWith("lua.")){

//重命名

for(int i = 0; i < ff.list().length;i++){

File pathname = ff.listFiles()[i];

//0.blv -- 00.blv

if(pathname.getName().endsWith(".blv") && pathname.getName().length() == 5){

pathname.renameTo(new File(pathname.getParentFile().getAbsolutePath() + File.separator + "0" + i + ".blv"));

}

if(pathname.getName().endsWith(".flv") && pathname.getName().length() == 5){

pathname.renameTo(new File(pathname.getParentFile().getAbsolutePath() + File.separator + "0" + i + ".flv"));

}

//0.blv.bdl -- 00.blv.bdl

if(pathname.getName().endsWith(".blv.bdl") && pathname.getName().length() == 9){

pathname.renameTo(new File(pathname.getParentFile().getAbsolutePath() + File.separator + "0" + i + ".blv.bdl"));

}

}

ffs = ff.listFiles(new FileFilter() {

public boolean accept(File pathname) {

for(int i = 0;i < ff.list().length;i++){

if(pathname.getName().endsWith(".blv") || pathname.getName().endsWith(".flv") || pathname.getName().endsWith(".blv.bdl")){

return true;

}

}

return false;

}

});

//合并

System.out.println("开始合并...");

FlvMerge mFlvMerge = new FlvMerge();

try {

mFlvMerge.merge(ffs, new File(episode_path + File.separator + name + ".flv"));

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

}

5.递归删除操作

public boolean deleteFolder(File file){

if(!file.exists()){

return false;

}

if(file.isFile() || file.listFiles().length == 0){

file.delete();

return true;

}else{

File[] files = file.listFiles();

for(int i=0;i

deleteFolder(files[i]);

}

file.delete();

return true;

}

}

6.具体怎么对FLV视频进行合并的,请点击这里 ,注释比较清晰。

java手机视频下载_使用JAVA合并哔哩哔哩手机客户端下载的视频相关推荐

  1. java项目----教务管理系统_基于Java的教务管理系统

    java项目----教务管理系统_基于Java的教务管理系统 2022-04-22 18:18·java基础 最近为客户开发了一套学校用教务管理系统,主要实现学生.课程.老师.选课等相关的信息化管理功 ...

  2. java学习视频网站_学习Java的视频网站

    原标题:学习Java的视频网站 很多自学Java的人都发现网上的Java视频教程都会分章节讲解,但是总感觉很乱?那是因为你没有比较系统.全面的了解Java语言,没有将Java应用到实际项目中,那么有哪 ...

  3. java设计是什么软件下载_用Java设计下载软件

    用Java设计下载软件 HTTP 协议的简介 HTTP协议是一种超文本传输协议(Hypertext Transfer Protocol),工作于网络应用层,自1990年起广泛应用于WWW 的全球信息服 ...

  4. 微软java虚拟机下载_微软Java虚拟机下载-Microsoft VM(Java虚拟机)5.0.3805最新版 - 维维软件园...

    你在找最新版本的Java虚拟机吗,快来维维下载Microsoft VM(Microsoft Java Virtual Machine)官方版进行安装吧,它是一款专业便捷的微软Java虚拟机软件,它的功 ...

  5. java流式上传下载_精讲RestTemplate第6篇-文件上传下载与大文件流式下载

    C++Templates(第2版英文版) 123.24元 (需用券) 去购买 > 本文是精讲RestTemplate第6篇,前篇的blog访问地址如下: 精讲RestTemplate第1篇-在S ...

  6. java pdf插件下载_免费java pdf控件

    云原生的概念和理论体系非常的完备,but talk is cheap , show me the code ! 但是作为一名程序员,能动手的咱绝对不多BB,虽然talk并不cheap , 能跟不同层次 ...

  7. java备忘录源码下载_备忘录/java - WEB源码|JSP源码/Java|源代码 - 源码中国

    压缩包 : 备忘录.rar 列表 备忘录\copyright.jsp 备忘录\CSS\style.css 备忘录\error.jsp 备忘录\images\add_bottom.gif 备忘录\ima ...

  8. Java西西软件_随身java学习软件-随身Java清爽版app下载v1.1.2安卓无广告版-西西软件下载...

    随身Java清爽版app是一款非常适合初学者和有一定的开发经验的开发者使用Java技术学习应用,随身Java精选了在Java基础.JavaEE.数据库.面试等过程中经常遇到的知识点,覆盖面广.适用于初 ...

  9. java课程 数独 文库_数独java

    数独游戏的算法研究与实现_IT/计算机_专业资料.数独游戏的算法研究与实现 java lSSN1009-3044 ComputerKnowledgeAnd MnoJ;01∥电奠知识与技术 E-mail ...

  10. java是什么格式_是java格式

    错误:编码GBK的不可映射字符的解决办法 最近在重新补javaSE的基础,编辑器编写完代码以后,在控制台运行代码段的时候,出现了以下的错误提示:错误:编码GBK的不可映射字符 在通过查询谷哥和度娘以后 ...

最新文章

  1. 用MS SQL 语句修改表中字段类型
  2. 多分类神经网络与原子核
  3. spyder 崩溃解决方案
  4. 机甲才是男人的浪漫 这款Python版免费战争机甲类游戏,“白拿党”还在等什么?(超帅气)
  5. 计算机系统组成图表,Excel2013中的图表作用组成类型与认识(上)——想象力电脑应用...
  6. 打造高效前端工作环境-tmuxinator
  7. 从零学React Native之05混合开发
  8. 记一次 windows server 2012R2 上安装 MSSQL2005 及网站发布
  9. vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5
  10. j90度度复数运算_虚数i的运算公式及实际意义
  11. Spark综合项目:企业电商分析平台
  12. 数位板使用技巧_保护您的眼睛技巧,以帮助防止数位眼疲劳
  13. 计算机教育学研究方法,广西师大 教育学 孙杰远《教育研究方法》知识点笔记1.pdf...
  14. 运维工程师是桥的护栏_海沧大桥护栏救过不少车 揭秘护栏是如何养护的
  15. 相机成像原理之物像之间的大小关系换算
  16. 合理清除AlibabaProtect进程
  17. Win10左下角搜索栏以及资源管理器搜索栏无法使用(点击没有反应)
  18. 【ARMv8基础篇】DMC-400控制器简介
  19. json数据的两种格式及两种json方法
  20. 夏敏捷2008科研成果

热门文章

  1. 杭州旅游全攻略,详细!
  2. 关于node.js,dataStr的undefined的问题
  3. 按搜索量排名前100位访问量最高的网站(截至2020年)
  4. Nature子刊:高通量蛋白质组学方法学综述
  5. 常用DNS列表(电信、网通)
  6. 国内外优秀的计算机视觉团队汇总|最新版
  7. 如何用unity做一个合成图片的程序
  8. Springboot微信公众号开发入门流程(校验签名、access_token获取、生成带参二维码、发送文字、图文消息、被动回复消息、图文消息静默跳转)
  9. 计算机资源管理菜单包括哪些,资源管理器文件菜单有哪些命令,资源管理器命令...
  10. 计算机网络1MB等于多少b,1mb等于多少kb流量?1mb等于多少GB?1mb等于多少TB?1mb等于多少b...