主要参考360个人博物馆的一个文章1,在评论区看到好像这个头条2的才是原出处?
首先说一下注意事项:
-
手机直接连在电脑上,可以复制文件,但是不能够通过命令行访问。其原因大概是没有挂载盘符,导致其路径一直在
/此电脑下面。 -
FFmpeg的安装等不再赘述,我这里已经安装好了。而且这里的FFmpeg已经加入环境变量,即全局可调用。如果没有加入环境变量,则需要通过安装路径/ffmpeg.exe或者进入安装文件夹,通过.\ffmpeg.exe来调用
E:\Android\data\tv.danmaku.bili\download\10590361\c_17482191
| entry.json
| danmaku.xml
|
\---64
index.json
audio.m4s
video.m4s
在上图当中,10590361是缓存视频的文件夹,c_17482191是该分P的文件夹。其中64这个文件夹是该分P的视频video.m4s,音频audio.m4s等信息,而entry.json则是该分P的信息及整个系列的信息。
不同的缓存当中,存储视频和音频的文件夹名不一定相同,这个是64,我也见过16的,一般都是数字
代码如下:
import json
# 用于解析json
import os
# 用于新建文件夹等
import re
# 用于替换字符
import time
# 用于计时
At = time.time()
# 记录总耗时
def validateTitle(title):
rstr = r"[\/\\\:\*\?\"\<\>\|]"
# '/ \ : * ? " < > |'
new_title = re.sub(rstr, "", title)
# 替换为下划线
return new_title
pathI = "E:/Android/data/tv.danmaku.bili/download/929386644/"
# 缓存所在的目录
listF = os.listdir(pathI)
# 该缓存下有几个视频文件夹
pathF = pathI + listF[0] + '/entry.json'
# 该缓存下P1的信息文件路径
with open(pathF, encoding='utf-8') as fileI:
infoJ = json.load(fileI)
# 读入文件
dirT = validateTitle(infoJ['title'])
dirN = 'D:/NetVideo/'+dirT + '/'
# 新的文件夹路径,包含中文
dirO = 'D:/NetVideo/Tmp/'
# 旧的临时文件夹路径,用于FFmpeg的命令
if not(os.path.exists(dirO)):
os.mkdir(dirO)
# 按照临时文件夹的名字创立文件
listFL = len(listF)
handleP = []
# 循环该缓存下的每一个分P
for index,itemF in enumerate(listF):
print(index+1,'/',listFL,' ','*'*20)
trnT = time.time()
pathF = pathI + itemF + '/'
# 该分P的路径
os.chdir(pathF)
# 将工作目录改为当前路径
with open('entry.json',encoding='utf-8') as fileI:
infoJ = json.load(fileI)
# 读入该分P的信息
fileO = dirO+'O.mp4'
# 该分P视频的临时文件名,不含中文
fileNC = validateTitle(infoJ['page_data']['part'])
# 去除文件名当中不能存在的字符
fileN = dirO + fileNC + '.mp4'
# 该分P的实际文件名,包含中文
print(fileNC)
commandS = 'ffmpeg -loglevel quiet -i video.m4s -i audio.m4s -codec copy '+fileO
# 拼接命令
# print(commandS)
# # 查看命令
# print(fileN)
# # 查看文件名
sunDir = [i for i in os.listdir(pathF) if os.path.isdir(i) ]
# 找到该文件夹下面的子文件夹
os.chdir(pathF+sunDir[0]+'/')
# 将工作目录调整到分P文件夹下,包含视频的文件夹
# 一般每一份缓存,各分P文件夹的名字不不相同
# 但是各分P文件夹下保存视频的文件夹名字一般相同,为数字
print(pathF+sunDir[0]+'/')
# os.system('echo %cd%')
# # 打印当前目录
# ffmpeg -f concat -i N.txt -c copy D:/NetVideo/output.mp4
# # 判断文件是否存在
if not(os.path.exists(fileN)):
if (os.path.exists(pathF+sunDir[0]+'/'+'video.m4s')):
print("Get video.m4s !!!")
os.system(commandS)
else:
print("No video.m4s !!!")
handleP.append(pathF+sunDir[0]+'/')
# continue
commandS = 'ffmpeg -loglevel quiet -f concat -i N.txt -c copy'+fileO
listN = os.listdir(pathF+sunDir[0]+'/')
listN.remove('index.json')
with open("N.txt",'w') as F:
for i in listN:
F.write('file '+i+'\n')
os.system(commandS)
os.remove('N.txt')
os.rename(fileO, fileN)
# 将视频文件重命名回实际文件名,包含中文
os.rename(fileO, fileN)
# 将视频文件重命名回实际文件名,包含中文
print('Iter Cost: {}'.format(time.time() - trnT))
os.rename(dirO,dirN)
# 将视频文件夹重命名为实际文件名,包含中文
print(handleP)
print('\nTotal Cost: {}\n\n\n\n'.format(time.time() - At))
# import os
# os.chdir('E:/Android/data/tv.danmaku.bili/download/10590361/c_17482207/lua.flv720.bili2api.64/')
# listN = os.listdir()
# listN.remove('index.json')
# with open('tmp.txt','w') as F:
# for i in listN:
# F.write('file '+i+'\n');
# fileO = "D:/NetVideo/O.mp4"
# # -loglevel quiet
# # 13 Unsupervised Learning - Linear Methods
# commandS = "ffmpeg -loglevel quiet -f concat -i tmp.txt -c copy "+fileO
# os.system(commandS)
# os.remove('tmp.txt')
给两个参考文献: