未末 发布的文章

官方wiki有下面三个例子:

ffmpeg -ss 00:01:00 -i video.mp4 -to 00:02:00 -c copy cut.mp4
ffmpeg -i video.mp4 -ss 00:01:00 -to 00:02:00 -c copy cut.mp4
ffmpeg -ss 00:01:00 -i video.mp4 -to 00:02:00 -c copy -copyts cut.mp4

-t-to两者不可同时出现,如果同时使用,则以-t为准

  • -t是在-ss指定的时间后持续的时间
  • -to是结束时间

测试后,第二种方式最为稳妥,但速度较慢,一三两种方式很快但是会出现时间误差。

对于bt2020等,使用这样的方法提取均会保留。

批量提取视频vid,样本如下

vlist = ['x0030wh28ov', 'p0024ht72c2', ..., 'x002483emfm', 'o0024m4oidi', 'n0024mvc1b8']

通过简单观察,可以发现第2、3、4、5位存在明显的递增关系,通过其他手段,可以验证vid和时间存在关系。
现在计划分析vid的一些规律。

字符频率

首先将2、3、4、5位剔除,因为他们有明显的规律,但其他位的字符都是0-9和a-z范围。现在用下面的脚本统计这些字符的信息。

def cc(s):
    ac = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
    cres = [s.count(c) for c in ac]#统计字符出现次数
    cresd = [x-y for x, y in zip(cres, cres[1:])]#相邻字符的差值
    print(cres)
    print(cresd)
    print(sum(cresd))
string = ""
for vid in vlist:
    string = string + vid[:1] + vid[5:]
    cc(string)

随加入统计的vid增加,对各个字符出现的频率进行统计,绘制曲线,情况如下(共333个vid):
各字符频率变化

可以发现随着vid的数量越来越多,单个字符的频率稳定在一个值附近,但并不是同一个频率。
这样看起来依然不够直观,在此对每个字符的统计进行拟合,鉴于前面部分的数据属于小样本情况,对拟合可能造成较大误差,所以用于拟合的数据从100个vid之后开始,采用指数函数拟合(a * exp(-b * x) + c)。结果如下:
将x轴起始坐标偏移至1(这个图可能有点问题,但我不想改了)
1
将x轴起始坐标保持
101

在原位置拟合结果比较明显,各个字符概率分布情况也比较清晰了。
不过我觉得再增加一定数量vid,现在总vid数量是407,效果如下
将x轴起始坐标偏移至1
1
将x轴起始坐标保持
101

可以看到各个字符的频率已经可以认为是稳定了,得到拟合函数的具体系数,得到极限值,就可以认为极限值是字符对应的频率。
完整视角的拟合情况:
全视角

将vid看做一个向量,按一定映射关系,计算其长度,下面是样本中vid的分布情况:
vid分布

横轴也这样计算,分布如下:
x轴的分布

即使样本不够多,但可以明显看到的是,vid的长度分布比较均匀,分布在某一个数的前后,横轴亦是如此。
考虑连续的一串数字,比如1-10000,将其每一个数字转为字符串,计算总的距离,下面是距离分布:
连续数字

如果是y = x^3 + 11 * x^2 + 1.5这样的函数,结果如下:
三次多项式

可以看到这样的规律性都很强。就这样的结果来看,可以排除数字和vid的映射关系应该不是高次多项式,更不是线性关系。下面再试试其他函数。
比如y = a * cos(b * x) + c * sin(d * x) + e其中e能使整个函数始终大于0,这个规律性更明显了。
三角函数

对10进制到16进制的变化,可见整体走势依然和10进制一样。
hex(x)

到这里,我认为原vid的向量长度的样本过少,不足以更全面直观体现它的分布,所以现在先去提取更多的vid。

---分割线---
在多次尝试后,发现随机提取某三个索引,在三维空间中显示出来,发现也是随机分布的,并没有明显特征(如下)。
三维的向量分布

至此,除了单个字符的出现存在稳定的概率外,没有其他发现。
另外尝试将有着明显时间差的vid进行简单的36进制转换在!7这么多种情况下,依然不能满足递增的关系。如果说有什么规律,至少不是按某一种进制转换的。
还尝试了将vid按36进制换算后,计算向量长度,结果如下图,样本有限,不过似乎能看出整体分布可能接近三角函数的样子。
向量长度

input = [1,2,3,4]
# output = [24,12,8,6]
input = [5,3,2,4,1]
# output = [24,40,60,30,120]
length = len(input)
a = b = []
for index in range(length):
    r=1
    for i in input[:index]:
        r *= i
    a.append(r)
    r=1
    for i in input[length-index-1:]:
        r *= i
    b.append(r)
b.reverse()
b = b + [1]
_ = b.pop(0)
# print(a)
# print(b)
print(list(map(lambda x, y: x * y, a, b)))

这种算是知道就会,不知道也很难想出来的吧?

前提是网盘有这个文件,好处在于不用开浏览器...

# -*- coding: utf-8 -*-

import os
import sys
import zlib
import json
import hashlib
import requests
from argparse import ArgumentParser
# 此处的BDUSS是网页源代码中的XDUSS
cookies = {"BDUSS":"pansec_***"}
ua_1 = {
    "X-Requested-With":"XMLHttpRequest",
    "User-Agent":"netdisk;2.0.0.4;PC;PC-Windows;10.0.17763;uploadplugin",
    "Content-Type":"application/x-www-form-urlencoded",
    "Accept":"*/*",
    "Accept-Language":"zh-CN,zh;q=0.8",
    "Accept-Charset":"GBK,utf-8;q=0.7,*;q=0.3",
    }

def crc(path):
    prev = 0
    for line in open(path,"rb"):
        prev = zlib.crc32(line, prev)
    return prev & 0xFFFFFFFF
    
def slice_md5(path):
    with open(path, "rb") as f:
        bin_obj = f.read(256 * 1024)
        part_md5 = hashlib.new('md5', bin_obj).hexdigest()
    return part_md5
    
def info(path):
    crc32 = crc(path)
    part_md5 = slice_md5(path)
    size = fs = os.path.getsize(path)
    f = open(path, "rb")
    hash_obj = hashlib.md5()
    md5_list = []
    while (fs > 0):
        if fs < 4194304:
            bin_obj = f.read(fs)
        else:
            bin_obj = f.read(4194304)
        hash_obj.update(bin_obj)
        md5_list.append(hashlib.new('md5', bin_obj).hexdigest())
        fs -= 4194304
    f.close()
    md5 = hash_obj.hexdigest()
    print("crc32", crc32)
    print("前256K的md5", part_md5)
    print("分片md5", md5_list)
    print("文件md5", md5)
    return crc32, part_md5, md5_list, md5, size
    
def rapidupload(remote_fullpath, md5, part_md5, crc32, size):
    url = "http://pan.baidu.com/api/rapidupload"
    query = {
        "clienttype":"6",
        "version":"2.0.0.4",
        }
    data = {
        "path":remote_fullpath,
        "content-md5":md5,
        "slice-md5":part_md5,#前256K的md5值
        "content-crc32":crc32,#10进制
        "content-length":size,
    }
    # 返回中errno为404说明自己网盘没有这个文件
    rapid_res = requests.post(url, data=data, headers=ua_1, cookies=cookies, params=query)
    rapid_resd = json.loads(rapid_res.content.decode("utf-8"))
    print(rapid_resd)
    if rapid_resd.get("errno") in [-8, 0]:
        if rapid_resd.get("errno") == -8:
            print("已存在同名文件")
        if rapid_resd.get("errno") == 0:
            print(rapid_resd["info"])
        return True
    else:
        print(rapid_resd.get("errno"))
        return False
        
def main():
    # 需要安装argparse
    parser = ArgumentParser(description="尝试秒传文件至百度网盘")
    parser.add_argument("-fp", "--fpath",help="本地文件路径")
    parser.add_argument("-bp", "--bpath",help="网盘路径")
    args = parser.parse_args()
    _, name = os.path.split(args.fpath)
    remote_fullpath = args.bpath + "/" + name
    crc32, part_md5, md5_list, md5, size = info(args.fpath)
    flag = rapidupload(remote_fullpath, md5, part_md5, crc32, size)
    if flag:
        sys.exit("{} 已秒传 位于 {}".format(name, remote_fullpath))
    else:
        sys.exit("{} 秒传失败".format(name))
    
if __name__ == "__main__":
    main()

在控件安装情况下,文件以分片形式上传
请求如下:

POST /rest/2.0/pcs/file?method=upload&app_id=250528&type=tmpfile&dir=%2F/&filename=**X** HTTP/1.1
Cookie: BDUSS=**pansec_X**
Accept: text/*
Content-Type: multipart/form-data; boundary=----------KM7ei4Ef1gL6ae0ei4gL6GI3GI3gL6
User-Agent: netdisk;2.0.0.4;PC;PC-Windows;10.0.17763;uploadplugin
Connection: Keep-Alive
Pragma: no-cache
Host: c.pcs.baidu.com
Cache-Control: no-cache
Content-Length: **X**

------------KM7ei4Ef1gL6ae0ei4gL6GI3GI3gL6
Content-Disposition: form-data; name="Filename"

------------KM7ei4Ef1gL6ae0ei4gL6GI3GI3gL6
Content-Disposition: form-data; name="Filedata"; filename=""
Content-Type: application/octet-stream
**...binary...**

其中**包含起来的地方为个人信息和提交信息,其中:

  • filename为32位大写的字母与数字组合 暂不知产生方法,也许是随机的
  • BDUSS实际上这里和通常使用的值不一样,这个值通过查看网页源代码可以看到,为XDUSS值
  • Content-Length会自动决定
  • 通过multipart/form-data提交的二进制数据分片大小为4M
    返回如下:
HTTP/1.1 200 OK
Content-Type: text/html;charset=utf8
Connection: keep-alive
x-bs-client-ip: **X**
x-bs-request-id: **X**
x-bs-file-size: 4194304
Content-MD5: **X**
x-bs-meta-crc32: **X**
x-poms-part-key: **X**
x-bs-version: **X**
Vary: Accept-Encoding
Server: POMS/CloudUI 1.0
Content-Length: **X**

{"md5":"**X**","request_id":**X**}

其中x-bs-client-ip和x-bs-request-id为base64编码,解码后内容形式如下:
*.*.*.* 为你的出口/公网ip
*.*.*.*:*:*:201*-0*-* *:*:* 为内网ip+port+request_id+时间
x-bs-file-size为分片大小,一般是4M
Content-MD5和即为分片的md5,和返回的值一致
x-bs-meta-crc32似乎与我在电脑上计算的CRC32值不一致
x-poms-part-key和x-bs-version一致 32位数字字母小写组合

分片上传返回的md5在全部分片上传结束之后,通过下面这个接口组合成完整的文件

POST /api/create?a=commit&norename&clienttype=6&version=2.0.0.4 HTTP/1.1
Cookie: BDUSS=*
Connection: keep-alive
X-Requested-With: XMLHttpRequest
User-Agent: netdisk;2.0.0.4;PC;PC-Windows;10.0.17763;uploadplugin
Content-Type: application/x-www-form-urlencoded
Accept: */*
Accept-Language: zh-CN,zh;q=0.8
Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3
Host: pan.baidu.com
Cache-Control: no-cache
Content-Length: 266

path=//*&isdir=0&size=13729324&block_list=["","","",""]&method=POST

其中path为网盘路径,根目录则是//+文件名 size是文件总大小,block_list包含一个list,依次是md5值。
最后是浏览器请求了这个,似乎是刷新作用

GET /statistics?clienttype=0&version=v5&op=webupload&type=uploadSuccess&uk=*&product=pan&from=NativeUploader&detailKey=success&filesize=文件大小&is_member=0&success=1&uploadStyle=0&averageSpeed=0&filePath=本地路径&diskPath=/&file={"name":"文件名","type":"文件后缀包括点","server_path":"网盘路径根目录为/","progress":0,"size":"文件大小","path":"本地路径","dir":0,"status":3,"index":2,"resume":true} 
HTTP/1.1
Host: update.pan.baidu.com
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
Accept: image/webp,image/*,*/*;q=0.8
Referer: https://pan.baidu.com/disk/home?
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: zh-CN,zh;q=0.8
Cookie: *