orestonce/m3u8d

使用从服务器取得的文件的时间戳

Mishasama opened this issue · 26 comments

最终合成的mp4里的文件元数据因为是外部的库估计你是改不了吧?(如果能写TAG那就更好了)
image

那能否使用从服务器上取得的第一个ts文件中的创建时间作为mp4文件的创建时间,使用m3u8文件的更改时间作为mp4的更改时间?
image

有点类似 IDM 的这个功能。
image
现在一般从服务器上下载到的文件都是按原样提供的,极少数会遇到重新构造或者时间戳缺失的情况。

这样就能在大量下载后,根据文件的时间戳来整理文件了。也能依据这个信息来推测出一些信息,比如视频录制的开始时间和结束时间。如果起止时间与视频时长对不上的话就能得知这个视频被后期修改过了。
这些信息对溯源、归档等还是很有帮助的。

我看大佬的动作还是挺快的……想着要不要试着把项目做成世界第一啥的😅
嗯……现在的功能已经很好很强大了就是了,似乎已经Google不到竞品了。即便不做这个也无敌了吧

这个由于合并库的原因无法更改,后续看看有没办法修改吧。

由于合并库的原因

其实只需要在目前的最后步骤合并好mp4文件后修改mp4文件的时间即可。
网上有很多修改文件时间标签的工具,可以参考一下。甚至可以用BAT直接调用它们来改……

你说的这个功能应该是你误会IDM了,IDM的功能应该是服务端提供的“服务器当前时间”,而不是服务端提供的“文件修改时间”。
根据我取得的curl返回信息,服务端只返回了“服务器自己的当前时间”(http头部的Date属性),并没有返回m3u8文件的创建时间、
修改时间等属性。

例子1:

< HTTP/1.1 200 OK
< Server: JSP3/2.0.14
< Date: Mon, 02 Sep 2024 11:44:48 GMT
< Content-Type: application/vnd.apple.mpegURL
< Transfer-Encoding: chunked
< Connection: keep-alive
< Age: 155599
< Accept-Ranges: bytes
< X-Powered-By: Express
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Headers: X-Requested-With
< Access-Control-Allow-Methods: GET,POST,METHOD,OPTIONS
< Ohc-Global-Saved-Time: Sat, 31 Aug 2024 16:15:52 GMT
< Ohc-Cache-HIT: cd11ct64 [2], suzix64 [2]
< Ohc-File-Size: 1635
< X-Cache-Status: HIT
< Access-Control-Max-Age: 86400
<

例子2:

< HTTP/1.1 200 OK
< Server: openresty
< Date: Mon, 02 Sep 2024 11:52:20 GMT
< Content-Type: application/x-mpegURL
< Connection: keep-alive
< X-NG-Host: LECDN-TC-COS-IN-60-15
< X-LeCloud-Ver: LeCloud/31.3.17
< Expires: Tue, 03 Sep 2024 02:14:39 GMT
< Cache-Control: max-age=86400
< Le-Status: TCP_HIT
< Age: 34662
< Access-Control-Allow-Origin: *
< x-cos-hash-crc64ecma: x
< x-cos-request-id: xxx=
< Content-Length: 90990
< Request-Id: xxxx
< Ctl-Cache-Status: HIT from he-tangshan3-ca26, MISS from sc-nanchong2-ca65
< x-cos-storage-class: INTELLIGENT_TIERING
<

IDM的功能应该是服务端提供的“服务器当前时间”

实际下载一个文件就知道了……

  • 如果没有勾选,那么下载到本地后的文件的创建时间是下载完成时间。(分块合并完成时间)
  • 如果勾选了,那么下载到本地后的文件的创建时间就是服务器原文件的创建时间。(使用下载文件时第一分块获取到的原文件头的元数据信息)

这个功能相当于模仿单线程下载文件,原封不动的还原下载目标的所有数据的情况。
(因为现代下载都倾向分块多线程,最后合并的方式。但这样做文件的时间戳就会改变,因为合并出来的理论上是一个刚新建的文件,而不是复制粘贴出来的老文件。)

跟HTTP头没有关系,这是文件自身的元数据。这不是网络的事,这是文件的事。

文件的元数据的信息里也没有:

ffprobe -v quiet -print_format json -show_format -show_streams 00001.ts

{
    "streams": [
        {
            "index": 0,
            "codec_name": "aac",
            "codec_long_name": "AAC (Advanced Audio Coding)",
            "profile": "LC",
            "codec_type": "audio",
            "codec_tag_string": "[15][0][0][0]",
            "codec_tag": "0x000f",
            "sample_fmt": "fltp",
            "sample_rate": "48000",
            "channels": 2,
            "channel_layout": "stereo",
            "bits_per_sample": 0,
            "initial_padding": 0,
            "ts_packetsize": "188",
            "id": "0x100",
            "r_frame_rate": "0/0",
            "avg_frame_rate": "0/0",
            "time_base": "1/90000",
            "start_pts": 5581530,
            "start_time": "62.017000",
            "duration_ts": 898560,
            "duration": "9.984000",
            "bit_rate": "162741",
            "disposition": {
                "default": 0,
                "dub": 0,
                "original": 0,
                "comment": 0,
                "lyrics": 0,
                "karaoke": 0,
                "forced": 0,
                "hearing_impaired": 0,
                "visual_impaired": 0,
                "clean_effects": 0,
                "attached_pic": 0,
                "timed_thumbnails": 0,
                "non_diegetic": 0,
                "captions": 0,
                "descriptions": 0,
                "metadata": 0,
                "dependent": 0,
                "still_image": 0
            }
        },
        {
            "index": 1,
            "codec_name": "h264",
            "codec_long_name": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10",
            "profile": "High",
            "codec_type": "video",
            "codec_tag_string": "[27][0][0][0]",
            "codec_tag": "0x001b",
            "width": 1280,
            "height": 720,
            "coded_width": 1280,
            "coded_height": 720,
            "closed_captions": 0,
            "film_grain": 0,
            "has_b_frames": 1,
            "sample_aspect_ratio": "1:1",
            "display_aspect_ratio": "16:9",
            "pix_fmt": "yuv420p",
            "level": 32,
            "color_range": "tv",
            "color_space": "bt709",
            "color_transfer": "bt709",
            "color_primaries": "bt709",
            "chroma_location": "left",
            "field_order": "progressive",
            "refs": 1,
            "is_avc": "false",
            "nal_length_size": "0",
            "ts_packetsize": "188",
            "id": "0x101",
            "r_frame_rate": "60/1",
            "avg_frame_rate": "60/1",
            "time_base": "1/90000",
            "start_pts": 5582880,
            "start_time": "62.032000",
            "duration_ts": 900060,
            "duration": "10.000667",
            "bits_per_raw_sample": "8",
            "extradata_size": 50,
            "disposition": {
                "default": 0,
                "dub": 0,
                "original": 0,
                "comment": 0,
                "lyrics": 0,
                "karaoke": 0,
                "forced": 0,
                "hearing_impaired": 0,
                "visual_impaired": 0,
                "clean_effects": 0,
                "attached_pic": 0,
                "timed_thumbnails": 0,
                "non_diegetic": 0,
                "captions": 0,
                "descriptions": 0,
                "metadata": 0,
                "dependent": 0,
                "still_image": 0
            }
        },
        {
            "index": 2,
            "codec_name": "timed_id3",
            "codec_long_name": "timed ID3 metadata",
            "codec_type": "data",
            "codec_tag_string": "ID3 ",
            "codec_tag": "0x20334449",
            "ts_packetsize": "188",
            "id": "0x102",
            "r_frame_rate": "0/0",
            "avg_frame_rate": "0/0",
            "time_base": "1/90000",
            "start_pts": 5582880,
            "start_time": "62.032000",
            "disposition": {
                "default": 0,
                "dub": 0,
                "original": 0,
                "comment": 0,
                "lyrics": 0,
                "karaoke": 0,
                "forced": 0,
                "hearing_impaired": 0,
                "visual_impaired": 0,
                "clean_effects": 0,
                "attached_pic": 0,
                "timed_thumbnails": 0,
                "non_diegetic": 0,
                "captions": 0,
                "descriptions": 0,
                "metadata": 0,
                "dependent": 0,
                "still_image": 0
            }
        }
    ],
    "format": {
        "filename": "00001.ts",
        "nb_streams": 3,
        "nb_programs": 1,
        "format_name": "mpegts",
        "format_long_name": "MPEG-TS (MPEG-2 Transport Stream)",
        "start_time": "62.017000",
        "duration": "10.015667",
        "size": "8017824",
        "bit_rate": "6404225",
        "probe_score": 50
    }
}

不是……我是指文件系统……啊……我不知道那个叫什么名字啦!

反正就是在属性那看到的时间是存在文件二进制数据的最前端的数据,比文件自身的主要内容更要靠前的。记录着文件名、时间、读写等属性的内容,是针对某个文件自身的metadata,就像分区表那样的存在。并不是以任何可读的文本形式储存的,更不是针对某个文件格式的tag(metadata)。

你不知道这个东西吗?😮

你的意思是操作系统的文件管理-选中文件-右键点击“属性”里面的 创建时间、修改时间?那个是文件在你的电脑上创建的时间,不是在服务器上创建的时间。
捕获

你的意思是操作系统的文件管理-选中文件-右键点击“属性”里面的 创建时间、修改时间?

是的。

那个是文件在你的电脑上创建的时间,不是在服务器上创建的时间。

实际上服务器上存着的文件也有这个时间信息。你在下载的时候是会一并获得这个信息的,除非提供文件的服务器刻意隐藏(洗掉)了。
(不支持续传或者无法获知下载文件大小的那种一般就是不给文件头信息的了,反之一般都带文件头信息)
至于我们平时下载回来后为什么只会得到与下载开始或完成时相符的时间,我在这里已经解释了。

你如果有IDM就用IDM测试,如果没有,可以把浏览器的分段下载关掉,或者把下载工具的默认线程数设置为1。这样你再去看看下载回来的文件你就会发现并不是你的下载日时了。(服务器不可能时间不同步,因为SSL/TLS需要时间戳来进行加密握手的,双方误差超过1分钟就会握手失败,导致无法通讯)

v1.24.36 已支持“使用服务器提供的时间”

v1.24.36 已支持“使用服务器提供的时间”

不行,合并后的文件依旧是合并文件的完成时间。与使用IDM实测的时间戳不一样。

你要是没有测试资源的话我这里给你一份
https://d2vjef5jvl6bfs.cloudfront.net/0fcd00ad0bf0a1dc88bd_rainbow6_51974574413_1725869399/chunked/index-dvr.m3u8

这个是具体时间数据,采用本地时间码显示,应该没墙。
https://twitchtracker.com/rainbow6/streams/51974574413
image

image
你倒是在METATAG里放时间戳啊……?
也不是不行……要是连文件也一起改掉就更好了😅

image
不过好像还是有点问题……年份不对。

image
年份正确的是这个软件用ffmpeg导出的,估计还是合并库有问题?
这个开源软件包含了对文件时间戳的修改(不是详细属性里的媒体标签METATAG),也许你可以参考一下。

捕获

  • mp4文件内部的标签里的时间是更改正确了的。
  • 文件自己的属性包括三个: 创建时间、修改时间、访问时间。创建时间需要使用每个平台不同的syscall系统调用才能修改,由于每个平台不一样,这个就不改了;上个版本设置后两者时候出了bug,试一下 v1.24.37
  • mp4文件内部的标签里的时间是更改正确了的。

image
已测.38,但Windows属性识别出来还是不对的,这个你得换其它日期显示格式你才能发现问题。(比如我用的和历)
这个好像是跟你的保存格式有关的,得用UTC还是啥的通用格式(几千万秒的那个?),让系统自动转换来显示才行。

  • 上个版本设置后两者时候出了bug,试一下 v1.24.37

访问时间修改基本没有意义,看个属性就会自动刷新。
而修改时间只要更改了标签,甚至给视频评个星也会被刷新。
只有创建时间是相对稳固的,也是最为有价值(应用面最广)。所有的FTP、私有云等文件系统都索引它。

如果实在太麻烦就算了……给IDM一条活路得了。

那就算了,不修改文件的创建时间。修改创建时间需要windows/linux/macos每个平台都单独写修改时间代码,相当麻烦。

那就算了,相当麻烦。

中秋快乐🏮

@orestonce 可以用这个库修改文件创建时间:https://github.com/xiaoqidun/setft

@orestonce 可以用这个库修改文件创建时间:https://github.com/xiaoqidun/setft

糟了,来大佬加工作量了🤣

@monkeyWie @Mishasama 这个库只实现了windows下的文件创建时间更改,其他平台并未实现。不过也可以先抄过来,有个平台了总比没有强,下个版本增加此功能。

v1.24.40 已支持windows下更新文件的创建时间

据setft作者所说,linux、macos的文件创建时间需要root权限操作。所以更改文件创建时间的功能就这样了。

有windows够了🤣

v1.24.40 已支持windows下更新文件的创建时间

能不能扩展支持一下合并ts?直接复制第一个TS(00001.ts)文件的时间属性。

可以

最新版本 已支持合并ts时使用第一个ts的修改时间作为输出mp4的创建时间

最新版本 已支持合并ts时使用第一个ts的修改时间作为输出mp4的创建时间

完美,大哥牛逼!