ffmpeg -i %0Xd.png
我知道如何使用或等将图像序列制作成视频。*.png
但我想做的是以某种方式告诉 ffmpeg 跳过每 n 个文件。例如,如果我有编号为 0000、0001、0002、0003、0004、0005、0006 等的文件。我想用文件 0000、0003、0006、0009 等制作视频(即获取每 n==3 个文件)。移动和重命名并不是一个真正的选择,因为我有数十万张图像,我想批量转换具有不同 n 量的许多不同版本。例如
- 0000、0001、0002...-> n1.mp4
- 0000、0002、0004...-> n2.mp4
- 0000、0003、0006...-> n3.mp4
ETC。
这可能吗?
答案1
我最终编写了一个 Python 脚本来执行此操作
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
'''
converts sequence of images to video
uses glob pattern and allows skipping images
---
uses [sk-video](https://github.com/scikit-video/scikit-video)
```> pip install sk-video```
backend uses ffmpeg or libav
TODO:
- add more input & output dict opts
For full list of flags see
- https://ffmpeg.org/ffmpeg.html
- https://trac.ffmpeg.org/wiki/Encode/H.264
Note: Not using opencv2.VideoWriter because it fails silently on Anaconda
'''
from __future__ import print_function
from __future__ import division
import argparse
import glob
import os
from imageio import imread
from skvideo.io import FFmpegWriter
from tqdm import tqdm
from pprint import pprint
parser = argparse.ArgumentParser()
parser.add_argument('-i', '--input_folder', default='.', help='path to folder containing images')
parser.add_argument('-p', '--file_pattern', default='*.png', help='Unix filename pattern. For details see https://docs.python.org/2/library/fnmatch.html')
parser.add_argument('-o', '--output_path', default='output.mp4', help='path to output video file')
parser.add_argument('-n', '--every', default=10, type=int, help='include every nth image. i.e. every==1 uses every image. every==2 takes every other image ')
parser.add_argument('-m', '--max_count', default=None, type=int, help='if > 0, cap at this many frames')
parser.add_argument('-v', '--verbose', default=False, type=int, help='dump a lot of stuff to the console')
# ffmpeg args
parser.add_argument('-r', '--fps', default='30', type=str, help='frames per second')
parser.add_argument('-vcodec', default='libx264', type=str, help='output video codec')
parser.add_argument('-b', '--bitrate', default=None, type=str, help='bitrate')
parser.add_argument('-crf', default=None, type=str, help='Constant Rate Factor. The range of the CRF scale is 0–51, where 0 is lossless, 23 is the default, and 51 is worst quality possible. A lower value generally leads to higher quality, and a subjectively sane range is 17–28. Consider 17 or 18 to be visually lossless or nearly so; it should look the same or nearly the same as the input but it isnt technically lossless')
args = parser.parse_args()
#%% Get input file list
glob_path = os.path.join(os.path.expanduser(os.path.expandvars(args.input_folder)), args.file_pattern)
# read all files in folder matching pattern
print('Reading folder "{}"'.format(glob_path))
paths = sorted(glob.glob(glob_path))
args.stats = {'file_count_total' : len(paths) }
print(args.stats['file_count_total'], 'files found')
# skip
if args.every > 1:
paths = [x for i,x in enumerate(paths) if i % args.every == 0]
args.stats['file_count_with_skip'] = len(paths)
print(args.stats['file_count_with_skip'], 'files with skip')
# cap to max_count
if args.max_count:
paths = paths[:args.max_count]
args.stats['file_count_capped'] = len(paths)
print(args.stats['file_count_capped'], 'files after cap')
#%% init video writer with parameters
inputdict = {}
outputdict = {}
if args.fps:
inputdict['-r'] = args.fps
outputdict['-r'] = args.fps
if args.vcodec: outputdict['-vcodec'] = args.vcodec
if args.bitrate: outputdict['-b'] = args.bitrate
if args.crf: outputdict['-crf'] = args.crf
video_writer = FFmpegWriter(args.output_path, inputdict=inputdict, outputdict=outputdict)
#%%
print('Starting with args:')
pprint(vars(args))
for path in tqdm(paths):
img = imread(path)
if args.verbose: print('processing file', i, path)
video_writer.writeFrame(img)
print('\n-')
print('Finished. Video saved at', args.output_path)
video_writer.close()