|
|
| import argparse
|
| import glob
|
| import os
|
| import os.path as osp
|
| import sys
|
| from multiprocessing import Pool
|
|
|
|
|
| def resize_videos(vid_item):
|
| """Generate resized video cache.
|
|
|
| Args:
|
| vid_item (list): Video item containing video full path,
|
| video relative path.
|
|
|
| Returns:
|
| bool: Whether generate video cache successfully.
|
| """
|
| full_path, vid_path = vid_item
|
|
|
| if args.to_mp4:
|
| vid_path = vid_path.split('.')
|
| assert len(vid_path) == 2, \
|
| f"Video path '{vid_path}' contain more than one dot"
|
| vid_path = vid_path[0] + '.mp4'
|
| out_full_path = osp.join(args.out_dir, vid_path)
|
| dir_name = osp.dirname(vid_path)
|
| out_dir = osp.join(args.out_dir, dir_name)
|
| if not osp.exists(out_dir):
|
| os.makedirs(out_dir)
|
| result = os.popen(
|
| f'ffprobe -hide_banner -loglevel error -select_streams v:0 -show_entries stream=width,height -of csv=p=0 {full_path}'
|
| )
|
| w, h = [int(d) for d in result.readline().rstrip().split(',')]
|
| if w > h:
|
| cmd = (f'ffmpeg -hide_banner -loglevel error -i {full_path} '
|
| f'-vf {"mpdecimate," if args.remove_dup else ""}'
|
| f'scale=-2:{args.scale} '
|
| f'{"-vsync vfr" if args.remove_dup else ""} '
|
| f'-c:v libx264 {"-g 16" if args.dense else ""} '
|
| f'-an {out_full_path} -y')
|
| else:
|
| cmd = (f'ffmpeg -hide_banner -loglevel error -i {full_path} '
|
| f'-vf {"mpdecimate," if args.remove_dup else ""}'
|
| f'scale={args.scale}:-2 '
|
| f'{"-vsync vfr" if args.remove_dup else ""} '
|
| f'-c:v libx264 {"-g 16" if args.dense else ""} '
|
| f'-an {out_full_path} -y')
|
| os.popen(cmd)
|
| print(f'{vid_path} done')
|
| sys.stdout.flush()
|
| return True
|
|
|
|
|
| def parse_args():
|
| parser = argparse.ArgumentParser(
|
| description='Generate the resized cache of original videos')
|
| parser.add_argument('src_dir', type=str, help='source video directory')
|
| parser.add_argument('out_dir', type=str, help='output video directory')
|
| parser.add_argument(
|
| '--dense',
|
| action='store_true',
|
| help='whether to generate a faster cache')
|
| parser.add_argument(
|
| '--level',
|
| type=int,
|
| choices=[1, 2],
|
| default=2,
|
| help='directory level of data')
|
| parser.add_argument(
|
| '--remove-dup',
|
| action='store_true',
|
| help='whether to remove duplicated frames')
|
| parser.add_argument(
|
| '--ext',
|
| type=str,
|
| default='mp4',
|
| choices=['avi', 'mp4', 'webm', 'mkv'],
|
| help='video file extensions')
|
| parser.add_argument(
|
| '--to-mp4',
|
| action='store_true',
|
| help='whether to output videos in mp4 format')
|
| parser.add_argument(
|
| '--scale',
|
| type=int,
|
| default=256,
|
| help='resize image short side length keeping ratio')
|
| parser.add_argument(
|
| '--num-worker', type=int, default=8, help='number of workers')
|
| args = parser.parse_args()
|
|
|
| return args
|
|
|
|
|
| if __name__ == '__main__':
|
| args = parse_args()
|
|
|
| if not osp.isdir(args.out_dir):
|
| print(f'Creating folder: {args.out_dir}')
|
| os.makedirs(args.out_dir)
|
|
|
| print('Reading videos from folder: ', args.src_dir)
|
| print('Extension of videos: ', args.ext)
|
| fullpath_list = glob.glob(args.src_dir + '/*' * args.level + '.' +
|
| args.ext)
|
| done_fullpath_list = glob.glob(args.out_dir + '/*' * args.level + args.ext)
|
| print('Total number of videos found: ', len(fullpath_list))
|
| print('Total number of videos transfer finished: ',
|
| len(done_fullpath_list))
|
| if args.level == 2:
|
| vid_list = list(
|
| map(
|
| lambda p: osp.join(
|
| osp.basename(osp.dirname(p)), osp.basename(p)),
|
| fullpath_list))
|
| elif args.level == 1:
|
| vid_list = list(map(osp.basename, fullpath_list))
|
| pool = Pool(args.num_worker)
|
| pool.map(resize_videos, zip(fullpath_list, vid_list))
|
|
|