2022/8/4 更新
支持加入水印
水印必須包含透明圖像,并且水印圖像大小要等于原圖像的大小
python convert_image_to_video.py -f 30 -m watermark.png im_dir out.mkv
2022/6/21 更新
讓命令行參數(shù)更加易用
新的命令行使用方法
python convert_image_to_video.py -f 30 im_dir out.mkv
FFMPEG 命令行轉(zhuǎn)換 一組JPG圖像 到視頻時,是將這組圖像視為 MJPG 流。
我需要轉(zhuǎn)換一組 PNG 圖像到視頻,F(xiàn)FMPEG 就不認了。
pyav內(nèi)置了ffmpeg庫,不需要系統(tǒng)帶有ffmpeg工具
因此我使用 ffmpeg 的python包裝 pyav寫一個命令行工具,可以轉(zhuǎn)換一組任意格式圖像到視頻,來解決這個問題。
視頻尺寸為第一張圖像的大小
編碼方式為 crf 18
編碼時間參考:i7-8750H 5分鐘1080P 30FPS 視頻,編碼時間約為 30 分鐘
requirement.txt
opencv-python
tqdm
av
click
使用方法
將以下代碼,復制粘貼到一個文件內(nèi),命名為 convert_image_to_video.py
使用命令python convert_image_to_video.py im_dir --out_file out.mkv文章來源:http://www.zghlxwxcb.cn/news/detail-433579.html
python convert_image_to_video.py -f 30 im_dir out.mkv
可以看到進度條,可以看到輸出文件默認名字為 out.mkv
即使沒有完成,也可以立刻使用播放器播放 out.mkv 文件觀看成品質(zhì)量。文章來源地址http://www.zghlxwxcb.cn/news/detail-433579.html
import av
import numpy as np
import cv2
from glob import glob
from tqdm import tqdm
import click
support_im_exts = ('.png', '.bmp', '.webp', '.jpg', '.jp2', '.jpeg')
def blend(im, wm_color, wm_alpha):
im = im * (1-wm_alpha) + wm_color * wm_alpha
im = np.uint8(np.clip(np.round(im), 0, 255))
return im
@click.command()
@click.argument('in-dir', type=str)
@click.argument('out-file', type=str)
@click.option('-f', '--fps', type=click.IntRange(1), default=30, show_default=True, help='Video FPS.')
@click.option('-m', '--watermark', type=str, default=None, show_default=True, help='watermark file.')
def main(in_dir, out_file, fps=30, watermark=None):
vcodec = 'libx264'
if '*' not in in_dir:
in_dir = f'{in_dir}/*.*'
in_files = glob(in_dir, recursive=True)
in_files = [f for f in in_files if f.endswith(support_im_exts)]
in_files = sorted(in_files)
if watermark is not None:
buf = open(watermark, 'rb').read()
buf = np.frombuffer(buf, dtype=np.uint8)
wm = cv2.imdecode(buf, -1)
assert wm is not None
assert wm.ndim == 3 and wm.shape[-1] == 4
wm = cv2.cvtColor(wm, cv2.COLOR_BGRA2RGBA)
else:
wm = None
container = av.open(out_file, mode="w")
stream = container.add_stream(vcodec, rate=fps)
stream.pix_fmt = "yuv420p"
# stream.bit_rate = 10000*1000
stream.options["crf"] = "18"
stream.options["profile"] = "high"
stream.options["tune"] = "ssim"
stream.options["preset"] = "7"
stream.options["high-tier"] = "1"
stream.options["level"] = "5"
stream.options["tier"] = "high"
wm_color = None
wm_alpha = None
for f_i, file in enumerate(tqdm(in_files)):
im = cv2.imread(file, 1)
assert im is not None
im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
if f_i == 0:
stream.width = im.shape[1]
stream.height = im.shape[0]
if wm is not None:
wm = cv2.resize(wm, tuple(im.shape[:2][::-1]), interpolation=cv2.INTER_LINEAR)
wm_color = wm[..., :3]
wm_alpha = np.float32(wm[..., 3:4]) / 255.
if wm is not None:
im = blend(im, wm_color, wm_alpha)
frame = av.VideoFrame.from_ndarray(im, format="rgb24")
for packet in stream.encode(frame):
container.mux(packet)
# Flush stream
for packet in stream.encode():
container.mux(packet)
# Close the file
container.close()
if __name__ == '__main__':
main()
到了這里,關(guān)于python ffmpeg 使用 pyav 轉(zhuǎn)換 一組圖像 到 視頻的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!