Я пробовал ниже, но он показывает только фоновое видео.
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)
@Rotem Спасибо. Я отредактировал вопрос на основе ваших предложений. Пожалуйста, проверьте.
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).
Вот ответы на два ваших вопроса:
Для рисования белой линии на изображении 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()
Спасибо Ротем за вашу помощь. Линия рисования с альфа-значением работает отлично.
Трудно сказать, почему это не работает... 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') и проверьте файл журнала.