Как наложить последовательность кадров на видео с помощью ffmpeg-python?

Я пробовал ниже, но он показывает только фоновое видео.

background_video = ffmpeg.input( "input.mp4")
overlay_video = ffmpeg.input(f'{frames_folder}*.png', pattern_type='glob', framerate=25)
subprocess = ffmpeg.overlay(
                          background_video,
                          overlay_video,
                        ).filter("setsar", sar=1)

Я также пытался собрать последовательность кадров в видео .webm/.mov, но теряется прозрачность. видео принимает черный в качестве фона.

P.s. Размер кадра такой же, как размер фонового видео. Так что масштабирование не требуется.

Редактировать

Я попробовал предложения @Rotem

Попробуйте сначала использовать одно изображение PNG
overlay_video =  ffmpeg.input('test-frame.png')

Он не работает для кадров, созданных OpenCV, но работает для любого другого изображения png. Это странно, когда я вручную просматриваю папку с этими кадрами, отображаются пустые изображения (Ссылка на папку с моими кадрами). Но если я конвертирую эти кадры в видео (см. ниже), оно правильно показывает, что я рисую на каждом кадре.

output_options = {
                    'crf': 20,
                    'preset': 'slower',
                    'movflags': 'faststart',
                    'pix_fmt': 'yuv420p'
                }
ffmpeg.input(f'{frames_folder}*.png', pattern_type='glob', framerate=25 , reinit_filter=0).output(
                    'movie.avi',
                    **output_options
                ).global_args('-report').run()
попробуйте создать видео из всех изображений PNG без наложения

Он работает, как и ожидалось, единственная проблема - прозрачность. Есть ли способ создать видео с прозрачным фоном? Я пробовал .webm/.mov/.avi, но не повезло.

Добавьте .global_args('-report') и проверьте файл журнала
Report written to "ffmpeg-20221119-110731.log"
Log level: 48
ffmpeg version 5.1 Copyright (c) 2000-2022 the FFmpeg developers
  built with Apple clang version 13.1.6 (clang-1316.0.21.2.5)
  configuration: --prefix=/opt/homebrew/Cellar/ffmpeg/5.1 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libbluray --enable-libdav1d --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librist --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-videotoolbox --enable-neon
  libavutil      57. 28.100 / 57. 28.100
  libavcodec     59. 37.100 / 59. 37.100
  libavformat    59. 27.100 / 59. 27.100
  libavdevice    59.  7.100 / 59.  7.100
  libavfilter     8. 44.100 /  8. 44.100
  libswscale      6.  7.100 /  6.  7.100
  libswresample   4.  7.100 /  4.  7.100
  libpostproc    56.  6.100 / 56.  6.100
Input #0, image2, from './frames/*.png':
  Duration: 00:00:05.00, start: 0.000000, bitrate: N/A
  Stream #0:0: Video: png, rgba(pc), 1920x1080, 25 fps, 25 tbr, 25 tbn
Codec AVOption crf (Select the quality for constant quality mode) specified for output file #0 (movie.avi) has not been used for any stream. The most likely reason is either wrong type (e.g. a video option with no video streams) or that it is a private option of some encoder which was not actually used for any stream.
Codec AVOption preset (Configuration preset) specified for output file #0 (movie.avi) has not been used for any stream. The most likely reason is either wrong type (e.g. a video option with no video streams) or that it is a private option of some encoder which was not actually used for any stream.
Stream mapping:
  Stream #0:0 -> #0:0 (png (native) -> mpeg4 (native))
Press [q] to stop, [?] for help
Output #0, avi, to 'movie.avi':
  Metadata:
    ISFT            : Lavf59.27.100
  Stream #0:0: Video: mpeg4 (FMP4 / 0x34504D46), yuv420p(tv, progressive), 1920x1080, q=2-31, 200 kb/s, 25 fps, 25 tbn
    Metadata:
      encoder         : Lavc59.37.100 mpeg4
    Side data:
      cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: N/A
frame=  125 fps= 85 q=31.0 Lsize=     491kB time=00:00:05.00 bitrate= 804.3kbits/s speed=3.39x    
video:482kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 1.772174%

Для рисования рамки я использовал ниже.

for i in range(num_frames):
            transparent_img = np.zeros((height, width, 4),  dtype=np.uint8)
            cv2.line(transparent_img, (x1,y1), (x2,y2) ,(255, 255, 255), thickness=1, lineType=cv2.LINE_AA)
            self.frames.append(transparent_img)


## To Save each frame of the video in the given folder
for i, f in enumerate(frames):
    cv2.imwrite("{}/{:0{n}d}.png".format(path_to_frames, i, n=num_digits), f)



Трудно сказать, почему это не работает... 1. Попробуйте сначала использовать одно изображение PNG (замените f'{frames_folder}*.png', pattern_type='glob' на image_name.png). 2. Для проверки попробуйте создать видео из всех изображений PNG без наложения. 3. Попробуйте добавить флаг -reinit_filter 0: overlay_video = ffmpeg.input(f'{frames_folder}*.png', pattern_type='glob', framerate=25, reinit_filter=0). 4. Добавьте .global_args('-report') лайк .filter("setsar", sar=1).output('output.mp4').global_args('-report') и проверьте файл журнала.

Rotem 18.11.2022 23:00

@Rotem Спасибо. Я отредактировал вопрос на основе ваших предложений. Пожалуйста, проверьте.

Yogesh Yadav 19.11.2022 07:19

1. Нарисуйте линию со значением альфа-канала 255. Пример: cv2.line(transparent_img, (10,10), (100,100), (255, 255, 255, 255), thickness=10, lineType=cv2.LINE_AA). 2. Для создания видео с прозрачным фоном попробуйте: .webm файл, используйте libvpx-vp9 видеокодек и используйте -pix_fmt yuva420p - "a" канала yuva applis alpha (transparency).

Rotem 19.11.2022 10:08
Как настроить Tailwind CSS с React.js и Next.js?
Как настроить Tailwind CSS с React.js и Next.js?
Tailwind CSS - единственный фреймворк, который, как я убедился, масштабируется в больших командах. Он легко настраивается, адаптируется к любому...
LeetCode запись решения 2536. Увеличение подматриц на единицу
LeetCode запись решения 2536. Увеличение подматриц на единицу
Увеличение подматриц на единицу - LeetCode
Переключение светлых/темных тем
Переключение светлых/темных тем
В Microsoft Training - Guided Project - Build a simple website with web pages, CSS files and JavaScript files, мы объясняем, как CSS можно...
Отношения "многие ко многим" в Laravel с методами присоединения и отсоединения
Отношения "многие ко многим" в Laravel с методами присоединения и отсоединения
Отношения "многие ко многим" в Laravel могут быть немного сложными, но с помощью Eloquent ORM и его моделей мы можем сделать это с легкостью. В этой...
В PHP
В PHP
В большой кодовой базе с множеством различных компонентов классы, функции и константы могут иметь одинаковые имена. Это может привести к путанице и...
Карта дорог Беладжар PHP Laravel
Карта дорог Беладжар PHP Laravel
Laravel - это PHP-фреймворк, разработанный для облегчения разработки веб-приложений. Laravel предоставляет различные функции, упрощающие разработку...
3
3
281
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вот ответы на два ваших вопроса:

  • Для рисования белой линии на изображении BGRA используйте цвет (255, 255, 255, 255) вместо (255, 255, 255). Последний 255 применяет значение альфа-канала (прозрачности), а 255 делает линию полностью непрозрачной.

  • Для создания видео с прозрачным фоном попробуйте: .webm тип файла, используйте libvpx-vp9 видеокодек и используйте -pix_fmt yuva420p - a из yuva применяет альфа-канал (прозрачность).


Вот пример "автономного" кода (пожалуйста, прочтите комментарии):

import cv2
import numpy as np
import ffmpeg

# Create synthetic MP4 video file from testing
ffmpeg.input('testsrc=size=192x108:rate=1:duration=10', f='lavfi').output('tmp.mp4').overwrite_output().run()

transparent_img = np.zeros((108, 192, 4), np.uint8)

width, height, fps = 192, 108, 1

def make_sample_image(i):
    p = width//60
    img = np.zeros((height, width, 4), np.uint8)  # Fully transparent
    cv2.putText(img, str(i), (width//2-p*10*len(str(i)), height//2+p*10), cv2.FONT_HERSHEY_DUPLEX, p, (255, 255, 255, 255), p*2)  # White number
    return img

# Create 10 PNG files with transparent background an white number (counter).
for i in range(1, 11):
    transparent_img = make_sample_image(i)
    cv2.imwrite(f'{i:03d}.png', transparent_img)


output_options = {  'vcodec' : 'libvpx-vp9',  # libvpx-vp9 supports transparency.
                    'crf': 20,
                    #'preset': 'slower',  # Not supported by libvpx-vp9
                    #'movflags': 'faststart',  # Not supported by WebM
                    'pix_fmt': 'yuva420p'  # yuva420p includes transparency.
                }

frames_folder = './'

# Create video with transparency:
# reinit_filter=0 is required, only if the PNG images have different characteristics (example: some are RGB and some RGBA).
# Use %03d.png instead of glob pattern, becuase my Windows version of FFmpeg doesn't support glob pattern.
ffmpeg.input(f'{frames_folder}%03d.png', framerate=fps, reinit_filter=0).output(
                    'movie.webm',  # WebM container supports transparency
                    **output_options
                ).global_args('-report').overwrite_output().run()


# Overlay the PNG on top of tmp.mp4
background_video = ffmpeg.input( "tmp.mp4")
overlay_video = ffmpeg.input(f'{frames_folder}%03d.png', framerate=fps)
subprocess = ffmpeg.overlay(
                          background_video,
                          overlay_video,
                        ).filter("setsar", sar=1)

subprocess.output('overlay_video.webm', **output_options).global_args('-report').overwrite_output().run()

Спасибо Ротем за вашу помощь. Линия рисования с альфа-значением работает отлично.

Yogesh Yadav 20.11.2022 12:25

Другие вопросы по теме