用AutoHotkey解决B站客户端缓存视频m4s合并成mp4提示解析失败

Posted 火冷

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用AutoHotkey解决B站客户端缓存视频m4s合并成mp4提示解析失败相关的知识,希望对你有一定的参考价值。

一直用you-get下载B站视频,这两天发现视频的质量很低,于是又折腾了下

  1. 在线播放有1080P,而you-get -i url返回的最高清晰度就是480P
  2. 听朋友安利用哔哩下载姬(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 ~= "^\\d9$")  ;缓存文件夹是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
    



以上是关于用AutoHotkey解决B站客户端缓存视频m4s合并成mp4提示解析失败的主要内容,如果未能解决你的问题,请参考以下文章

b站缓存json是啥

bilibili缓存文件夹文件目录分析

b站禁用拓展插件怎么解除

Flutter——缓存B站视频,节省你的流量

当用户寻找另一个时间时,计算 HTML5 视频流中的 .m4s 段文件后缀

唧唧Down(B站视频下载) 彻底解决你的B站视频下载问题