web-dev-qa-db-ja.com

n個のファイルごとにスキップして、画像シーケンスからビデオを作成するにはどうすればよいですか?

ffmpeg -i %0Xd.pngまたは*.pngなどを使用して、イメージシーケンスからビデオを作成する方法を知っています。しかし、nmpファイルごとにスキップするようにffmpegに伝えたいのです。例えば。 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

等.

これは可能ですか?

1
memo

私はこれを行う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()
1
memo