FFMPEG 命令行转换 一组JPG图像 到视频时,是将这组图像视为 MJPG 流。 我需要转换一组 PNG 图像到视频,FFMPEG 就不认了。
pyav内置了ffmpeg库,不需要系统带有ffmpeg工具
因此我使用 ffmpeg 的python包装 pyav写一个命令行工具,可以转换一组任意格式图像到视频,来解决这个问题。 视频尺寸为第一张图像的大小 编码方式为 crf 18 编码时间参考:i7-8750H 5分钟1080P 30FPS 视频,编码时间约为 30 分钟
requirement.txt
opencv-python
tqdm
av
click
使用方法 将以下代码,复制粘贴到一个文件内,命名为 convert_image_to_video.py 使用命令
python convert_image_to_video.py im_dir --out_file out.mkv
可以看到进度条,可以看到输出文件默认名字为 out.mkv 即使没有完成,也可以立刻使用播放器播放 out.mkv 文件观看成品质量。
import av
import cv2
from glob import glob
from tqdm import tqdm
import click
support_im_exts = ('.png', '.bmp', '.webp', '.jpg', '.jp2', '.jpeg')
@click.command()
@click.argument('in_dir', type=str)
@click.option('--out_file', type=str, default='out.mkv', show_default=True, help='The out file name.')
@click.option('--fps', type=click.IntRange(1), default=30, show_default=True, help='Video FPS.')
def main(in_dir, out_file, fps=30):
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)
container = av.open(out_file, mode="w")
stream = container.add_stream(vcodec, rate=fps)
stream.pix_fmt = "yuv420p"
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"
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]
frame = av.VideoFrame.from_ndarray(im, format="rgb24")
for packet in stream.encode(frame):
container.mux(packet)
for packet in stream.encode():
container.mux(packet)
container.close()
if __name__ == '__main__':
main()
|