Как найти временные метки подмножества видео - PullRequest
0 голосов
/ 27 мая 2020

Я никогда раньше не занимался программированием на основе видео, и хотя этот пост SuperUser предоставляет способ сделать это в командной строке, я предпочитаю программный подход c, желательно с Python .

У меня есть куча дополнительных видео. Предположим, один из них называется 1234_trimmed.mp4 и представляет собой короткий фрагмент, вырезанный из исходного, гораздо более длинного видео 1234.mp4. Как я могу определить временные метки начала и окончания 1234_trimmed.mp4 внутри 1234.mp4?

К вашему сведению, все видео в любом случае изначально находятся на YouTube («1234» соответствует видео YouTube ID), если там есть ярлык.

Ответы [ 3 ]

0 голосов
/ 28 мая 2020

MP4 использует относительные отметки времени. Когда файл был обрезан, старые отметки времени были потеряны, и теперь новый файл начинается с нулевой отметки времени.

Таким образом, единственный способ определить, где этот файл может перекрываться с другим файлом, - это использовать компьютерное зрение или перцепционное хеширование. Оба варианта слишком сложны, чтобы описать их в одном ответе stackoverflow.

0 голосов
/ 29 мая 2020

Сам разобрался с cv2. Моя стратегия заключалась в том, чтобы получить первый и последний кадры субвидео и перебрать каждый кадр исходного видео, где я сравниваю dha sh текущего кадра (минимальное расстояние Хэмминга вместо проверки равенства в случае изменения размера и других преобразований) против первого и последнего кадров. Я уверен, что могут быть некоторые возможности оптимизации, но мне это нужно вчера.

import cv2

original_video_fpath = '5 POPULAR iNSTAGRAM BEAUTY TRENDS (DiY Feather Eyebrows, Colored Mascara, Drippy Lips, Etc)-vsNVU7y6dUE.mp4'
subvideo_fpath = 'vsNVU7y6dUE_trimmed-out.mp4'


def dhash(image, hashSize=8):
    # resize the input image, adding a single column (width) so we
    # can compute the horizontal gradient
    resized = cv2.resize(image, (hashSize + 1, hashSize))
    # compute the (relative) horizontal gradient between adjacent
    # column pixels
    diff = resized[:, 1:] > resized[:, :-1]
    # convert the difference image to a hash
    return sum([2 ** i for (i, v) in enumerate(diff.flatten()) if v])


def hamming(a, b):
    return bin(a^b).count('1')


def get_video_frame_by_index(video_cap, frame_index):
    # get total number of frames
    totalFrames = video_cap.get(cv2.CAP_PROP_FRAME_COUNT)

    if frame_index < 0:
        frame_index = int(totalFrames) + frame_index

    # check for valid frame number
    if frame_index >= 0 & frame_index <= totalFrames:
        # set frame position
        video_cap.set(cv2.CAP_PROP_POS_FRAMES, frame_index)

    _, frame = video_cap.read()
    return frame


def main():
    cap_original_video = cv2.VideoCapture(original_video_fpath)

    cap_subvideo = cv2.VideoCapture(subvideo_fpath)

    first_frame_subvideo = get_video_frame_by_index(cap_subvideo, 0)
    last_frame_subvideo = get_video_frame_by_index(cap_subvideo, -1)

    first_frame_subvideo_gray = cv2.cvtColor(first_frame_subvideo, cv2.COLOR_BGR2GRAY)
    last_frame_subvideo_gray = cv2.cvtColor(last_frame_subvideo, cv2.COLOR_BGR2GRAY)

    hash_first_frame_subvideo = dhash(first_frame_subvideo)
    hash_last_frame_subvideo = dhash(last_frame_subvideo)

    min_hamming_dist_with_first_frame = float('inf')
    closest_frame_index_first = None
    closest_frame_timestamp_first = None

    min_hamming_dist_with_last_frame = float('inf')
    closest_frame_index_last = None
    closest_frame_timestamp_last = None

    frame_index = 0
    while(cap_original_video.isOpened()):
        frame_exists, curr_frame = cap_original_video.read()

        if frame_exists:
            timestamp = cap_original_video.get(cv2.CAP_PROP_POS_MSEC) // 1000

            hash_curr_frame = dhash(curr_frame)

            hamming_dist_with_first_frame = hamming(hash_curr_frame, hash_first_frame_subvideo)
            hamming_dist_with_last_frame = hamming(hash_curr_frame, hash_last_frame_subvideo)

            if hamming_dist_with_first_frame < min_hamming_dist_with_first_frame:
                min_hamming_dist_with_first_frame = hamming_dist_with_first_frame
                closest_frame_index_first = frame_index
                closest_frame_timestamp_first = timestamp

            if hamming_dist_with_last_frame < min_hamming_dist_with_last_frame:
                min_hamming_dist_with_last_frame = hamming_dist_with_last_frame
                closest_frame_index_last = frame_index
                closest_frame_timestamp_last = timestamp

            frame_index += 1
        else:
            print('processed {} frames'.format(frame_index+1))
            break

    cap_original_video.release()
    print('timestamp_start={}, timestamp_end={}'.format(closest_frame_timestamp_first, closest_frame_timestamp_last))


if __name__ == '__main__':
    main()
0 голосов
/ 28 мая 2020

Если бы они были просто -codec copy 'd, отметки времени должны быть такими, как они были в исходном файле. В противном случае ffmpeg не подходит для этой работы. В этом случае вам следует изучить другие утилиты, которые могут найти точно совпадающие видео- и аудиокадры в обоих файлах и получить оттуда временные метки.

...