0

所以,我试图通过 python 解决一些随机问题并陷入逻辑。问题是:我有多个视频以及它们的运行时间或运行长度。现在,我想维护 2 个列表。如果“已同步”,则列出 1 个列表,而另一个列表“未同步”。如果流的运行时间差异小于或等于 2 秒,我们决定“同步”。否则,它们不会同步。如果我们有多个匹配的流,那么我们采用匹配计数/数量最高的流。

我能够想出一个非常简单/缓慢的方法来分割和配对这些文件。但是,当我得到不同的数据集时,我的逻辑失败了。

这就是我写的:

from datetime import datetime


# same_streams_old = {
  "Stream_1": "0:24:08.925167",
  "Stream_2": "0:24:08.990644",
  "Stream_3": "0:24:08.990644",
  "Stream_4": "0:24:12.118778",
  "Stream_5": "0:24:12.118778",
  "stream_6": "0:24:10.075066"
}
same_streams = {
  "Stream_1": "0:24:08.925167",
  "Stream_2": "0:24:12.118778",
  "Stream_3": "0:23:11.057711",
  "Stream_4": "0:24:12.118778",
  "Stream_5": "0:24:10.075066",
  "Stream_6": "0:24:08.990644"
}

keys = []
values = []
final_synced_video_files = []
final_non_synced_video_files = []

def get_time_diff(episode_run_time, episode_time):
    prev_episode_time = datetime.strptime(episode_run_time, '%H:%M:%S.%f')
    current_episode_time = datetime.strptime(episode_time, '%H:%M:%S.%f')

    time_diff = prev_episode_time - current_episode_time
    if current_episode_time > prev_episode_time:
        time_diff = current_episode_time - prev_episode_time

    return float(time_diff.seconds)

for key, value in same_streams.items():
    keys.append(key)
    values.append(value)
for key in keys:
    for _key in keys:
        if key != _key:
            diff = get_time_diff(same_streams[key], same_streams[_key])
            if diff <= 1.5:
                final_synced_video_files.append(key)
            else:
                pass

final_synced_video_files = list(set(final_synced_video_files))
final_non_synced_video_files = list(set(keys) - set(final_synced_video_files))

print("Synced Files : {0}".format(final_synced_video_files))
print("Non Synced Files : {0}".format(final_non_synced_video_files))

REPL 链接

如您所见,匹配最多的流是stream_1、和。stream_2stream_3stream_6

我写的还没有比较最大计数。然而,当我在做这件事时,我觉得这并不是真正有效的,也是解决这个问题的好方法。任何输入任何人?

我尝试了一些重叠间隔的方法,然后得到了这个:REPL LINK

但是,如果您运行查看这两个same_streams字典,您会看到结果不是我想要实现的。对此的任何帮助都会很棒。

编辑:我需要获取彼此相差 2 秒的流。例如:在same_streams_old中,期望的结果是流 1,2,3 和 6。但是,在字典same_streams中,期望的结果是流 2,4 和 5。

基本上,我需要看看哪些流可以“混合”在一起,哪些不能混合。

4

1 回答 1

1

好的,所以下面的打印例程可能有点乱,但请耐心等待,它们仅用于调试,完成后您可能不需要它们。我知道这是一个很长的答案,但请仔细阅读..

简短的回答:

您的问题可能来自这样一个事实,即当您从 string 转换为 时会丢失小数精度datetime,它将秒视为整数。但是,该timedelta对象有一个名为的方法total_seconds(),它确实提供亚秒级分辨率。有关详细信息,请参阅文档或一般文档。只需将return语句更改get_time_diff()为,

 return float(time_diff.total_seconds())

长答案的动机:

我不确定您要使用(非和)同步列表实现什么目标:您可能会遇到流a与流b同步的情况,而流cd同步,但cdab同步。他们都应该在你的synced_list吗?根据您要对列表执行的操作,我会考虑使用下面描述的同步矩阵,而不是您的列表,因为它们会丢失很多信息。

长答案:

让我介绍一下同步矩阵的概念。它将完整描述您的哪些流相互同步:

THE SYNC MATRIX:对称矩阵;当且仅当流“i”和“j”同步时,矩阵中的单元格 (i,j) 为 TRUE。否则,单元格值为 FALSE。因此,对角线 (.) 完全为 TRUE,因为流始终与自身同步。

     1 2 3 4
    ________
 1 | . T T F
 2 |   . T F
 3 |     . F
 4 |       .

“T”为真,“F”为假:显然从上面的示例图中,流 1 与流 2 同步,但与流 4 不同步。

对于您的示例,创建这样的同步矩阵非常简单:

def is_synced(key_1, key_2):    
    max_allowed_desync = 1.5
    return max_allowed_desync > get_time_diff(same_streams[key_1], same_streams[key_2])

keys = same_streams.keys()
keys.sort() # VERY IMPORTANT, for the synced matrix to be constructed correctly; also make 's' uppercase for "stream_6" in OP.

# The complete matrix ..
full_sync_matrix = [[is_synced(k1,k2) for k2 in keys] for k1 in keys]

# We can optimize (memory usage) to only get the half matrix, since it's symmetric anyway; also excluding the diagonal.
half_sync_matrix = [[is_synced(k1,k2) for k2 in keys[curr+1:]] for curr,k1 in enumerate(keys)]

现在,让我们实现两个用于打印/显示同步矩阵的函数:

# Print a HALFED sync matrix
def print_sync_half_matrix(sm):
    string = ""
    for i,row in enumerate(sm):
        string += "\n" + " "*i*2
        for col in row:
            string += " " + ("T" if col else "F")
    print(string)

# Print a COMPLETE sync_matrix
def print_sync_full_matrix(sm):
    string = ""
    for row in sm:
        string += "\n"
        for col in row:
            string += " " + ("T" if col else "F")
    print(string)

然后,对于您提供的数据集,我得到:

same_streams = {
  "Stream_1": "0:24:08.925167",
  "Stream_2": "0:24:08.990644",
  "Stream_3": "0:24:08.990644",
  "Stream_4": "0:24:12.118778",
  "Stream_5": "0:24:12.118778",
  "Stream_6": "0:24:10.075066"
} # note that "Stream_6" previously had a lower case 's'!

print_sync_half_matrix(half_sync_matrix)
#   1 2 3 4 5 6
# 1   T T F F T
# 2     T F F T
# 3       F F T
# 4         T F
# 5           F

请记住,矩阵/打印中不包含对角线!这里的结果是正确的,并且符合输入的预期。让我们打印出一些时差来获得更多的情报,

for stream_key in same_stream:
    print("Stream_1 ~ "+stream_key+": "+str(get_time_diff(same_streams["Stream_1"], same_streams[stream_key])))

..这很快表明您的时间戳已经失去了小数精度:

Stream_1 ~ Stream_5: 3.0
Stream_1 ~ Stream_4: 3.0
# ...

如果我们查看文档,datetime我们会看到它将时间视为秒的整数。seconds因此,当您从函数datetime中的对象请求时,会丢失微秒精度get_time_diff。只需从 deltatime 方法请求秒数即可解决.total_seconds()

于 2019-12-18T10:25:21.947 回答