2

我有一个系统,其中视频文件被摄取,然后启动多个 CPU 密集型任务。由于这些任务的计算成本很高,如果文件已经被处理,我想跳过处理它。

视频来自各种来源,因此文件名等不是可行的选择。

如果我使用图片,我会比较 MD5 哈希,但在 5GB - 40GB 视频上,这可能需要很长时间来计算。

为了比较两个视频,我正在测试这种方法:

  • 检查相关元数据匹配
  • 使用 ffmpeg / ffprobe 检查文件长度
  • 使用 ffmpeg 以 100 个预定义的时间戳提取帧 [1-100]
  • 创建每个帧的 MD5 哈希
  • 比较 MD5 哈希以检查是否匹配

有谁知道这样做更有效的方法?还是解决问题的更好方法?

4

4 回答 4

2

首先,您需要正确定义在哪些条件下两个视频文件被视为相同。您的意思是与逐字节完全相同吗?或者你的意思是内容相同,那么你需要为内容定义一个合适的比较方法。

我假设第一个(完全相同的文件)。这与文件实际包含的内容无关。当您收到文件时,请始终为该文件构建哈希,并将哈希与文件一起存储。

检查重复是一个多步骤的过程:

1.) 比较哈希,如果你没有找到匹配的哈希,文件是新的。在新文件的大多数情况下,您可以期望这一步是唯一的步骤,一个好的哈希(SHA1 或更大的东西)对于任何实际数量的文件几乎不会发生冲突。

2.) 如果您发现其他具有相同哈希的文件,请检查文件长度。如果它们不匹配,则文件是新的。

3.)如果哈希和文件长度都匹配,则必须比较整个文件内容,找到第一个差异时停止。如果整个文件比较结果相同,则文件相同。

在最坏的情况下(文件相同),这应该不会超过读取两个文件的原始 IO 速度。在最好的情况下(散列不同),测试只需要与散列查找一样多的时间(在 DB 或 HashMap 或您使用的任何东西中)。

编辑:您担心构建哈希的 IO。如果您先比较文件长度并跳过文件长度的所有内容,您可能会部分避免这种情况。另一方面,您还需要跟踪您已经为哪些文件构建了散列。这将允许您推迟构建哈希,直到您真正需要它。如果缺少散列,您可以直接跳到比较两个文件,同时在同一个 pass 中构建散列。它需要跟踪的状态要多得多,但根据您的情况,这可能是值得的(您需要一个可靠的数据基础,说明重复文件的发生频率及其平均大小分布才能做出决定)。

于 2013-06-13T16:07:58.720 回答
2

我将从文件长度(快速和肮脏)开始,继续使用 MD5 并以检查帧结束。快捷方便。

当然,如果你得到一个编辑过的文件,它会给你假阴性,但它可能会给你 MD5 的假阴性,甚至可能检查偶数帧;防止由于版本导致的误报在计算上非常昂贵,以至于最好忽略它们。

于 2013-06-13T15:10:47.777 回答
1

散列您的文件,并跟踪散列。下面是一个例子:Getting a File's MD5 Checksum in Java

请记住,尽管极不可能,但在数学上可能有两个不同的文件给出相同的哈希值。如果您正在处理大量文件(大约 2^128 个文件),那么您需要一个更好的哈希算法……比如 SHA2-256。但这可能不是这里的情况。

于 2013-06-13T15:13:33.210 回答
0

MD5 哈希非常慢。考虑使用更快的哈希函数,例如MurmurHash

它具有非常好的抗碰撞性,而且速度非常快。

此外,您应该首先检查文件大小,这不会花费时间并避免不必要的哈希计算。

于 2013-06-13T15:13:13.043 回答