一直用
you-get
下载B站视频,这两天发现视频的质量很低,于是又折腾了下
- 在线播放有
1080P
,而you-get -i {url}
返回的最高清晰度就是480P
- 听朋友安利用
哔哩下载姬(DownKyi)
,试了也是只有480P
的清晰度
看来B站作了限制了,于是下载了官方客户端,可以缓存视频,
发现是两个m4s
格式的文件,经网上查看,一个是视频,一个是音频,
用ffmpeg -i {f1} -i {f2} -c copy out.mp4
想合并文件并转为mp4
,提示xxx.m4s: Invalid data found when processing input
,看来是B站对这个文件也做了处理。
继续找视频,在B站客户端缓存视频解码与打开方法_哔哩哔哩知道了要修改的地方(主要是这个)。
于是又用AutoHotkey
折腾了文件二进制的处理。
附上 AutoHotkey v2-beta 代码
m4sDir("c:\Users\Administrator\Desktop\811376303")
;传入文件夹即可
m4sDir(dir) {
SplitPath(dir, &dn)
if (dn ~= "^\d{9}$") { ;缓存文件夹是9个数字
fnn := A_Now
arrFp := []
loop files, dir . "\*.m4s", "F" { ;B站缓存
arrFp.push((fnn . string(A_Index)).fnn2fp("m4s"))
um_m4s_modify(A_LoopFileFullPath, arrFp[-1])
}
;解析 .videoInfo 文件,获取文件名
title := json.parse(fileread(".videoInfo".fn2fp(dir), "utf-8"))["title"]
;用ffmpeg合并文件
RunWait(format('ffmpeg.exe -i {1} -i "{2}" -c copy "{3}"',arrFp[1],arrFp[2],title.fnn2fp("mp4",dir)))
;删除两个临时文件
arrFp.map((fp)=>FileDelete(fp))
return 1
}
}
;核心:对m4s文件进行二进制处理
um_m4s_modify(fp, fp1:="") {
o := fileread(fp, "raw")
o.mid(1,9) ;删除前面9个字符
o.deleteByStr("avc1", 10, 30) ;删除指定字符串
numput("char", 32, o, 3) ;修改第4个字符为空格
if (FileExist(fp1))
FileDelete(fp1)
FileAppend(o, fp1)
}
defprop := {}.DefineProp.bind(buffer.prototype)
proto := _Buffer.prototype
for k in proto.OwnProps() {
if (k != "__Class")
defprop(k, proto.GetOwnPropDesc(k))
}
class _Buffer {
static fromFile(fp) => fileread(fp, "raw")
;删除 i开始l个字符
;o := ClipboardAll(o.ptr + 9, o.size-9)
mid(i, l){
dllcall("RtlMoveMemory", "ptr",this.ptr+i-1, "ptr",this.ptr+i+l-1, "uptr",this.size-l)
this.size -= l
}
;从 start 处开始匹配字符串 limit为限制查找长度
index(str, start:=0, limit:=0) {
;字符串转成 asc 码
arr := []
loop parse, str
arr.push(ord(A_LoopField))
i := start
while (i < this.size) {
if (limit && i-start > limit)
return 0
if (numget(this, i, "char") == arr[1]) { ;匹配第一个字符
OutputDebug(format("i#{1} {2}:{3} match first={4}", A_LineFile,A_LineNumber,A_ThisFunc,i))
res := i
;确认后续内容是否完整匹配
i++
loop(arr.length-1) {
if (numget(this, i, "char") != arr[A_Index+1]) { ;有一个不匹配,则退出
res := 0
break
}
i++
}
if (res) {
OutputDebug(format("i#{1} {2}:{3} res={4}", A_LineFile,A_LineNumber,A_ThisFunc,res))
return res
}
} else {
i++
}
}
}
;删除第一个找到的字符串
deleteByStr(str, start:=0, limit:=0) {
i := this.index(str, start, limit)
if (i) {
this.mid(i+1, strlen(str))
}
return i
}
}
标签:fp,AutoHotkey,m4s,start,mp4,limit,res,arrFp
From: https://www.cnblogs.com/hyaray/p/17063380.html