File size: 5,742 Bytes
7daf628 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | import os
from glob import glob
import time
import argparse
import numpy as np
import librosa
from decord import VideoReader
import shared.utils.log as log
from os.path import exists, basename
from natsort import natsorted
def resize_video_simple(input_path, output_path, width=480):
import subprocess
command = f"""ffmpeg -loglevel quiet -i {input_path} -vf \"scale={width}:-1\" -c:a copy {output_path}"""
subprocess.call(command, shell=True)
def load_pending_videos(tracker_file):
"""Load list of pending videos from tracker file."""
if not exists(tracker_file):
return []
with open(tracker_file, 'r') as f:
return [line.strip() for line in f.readlines() if line.strip()]
def save_pending_videos(tracker_file, video_paths):
"""Save list of pending videos to tracker file."""
with open(tracker_file, 'w') as f:
for path in video_paths:
f.write(f"{path}\n")
def remove_completed_video(tracker_file, completed_video):
"""Remove a completed video from the tracker file."""
pending_videos = load_pending_videos(tracker_file)
if completed_video in pending_videos:
pending_videos.remove(completed_video)
save_pending_videos(tracker_file, pending_videos)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument(
"--video_dir", type=str, required=True,
help="Directory containing videos to downsize."
)
parser.add_argument(
"--ext", type=str, default="mp4",
help="File extension to search for (default: mp4)."
)
parser.add_argument(
"--remove_old", action="store_true",
help="Remove original video after downsizing."
)
parser.add_argument(
"--width", type=int, default=480,
help="Width to resize videos to (default: 480)."
)
parser.add_argument(
"--debug", action="store_true",
help="Run debug checks after downsizing."
)
parser.add_argument("--si", type=int, default=None)
parser.add_argument("--ei", type=int, default=None)
parser.add_argument(
"--tracker_file", type=str, default="video_resize_tracker.txt",
help="Tracker file to keep track of pending videos (default: video_resize_tracker.txt)."
)
parser.add_argument(
"--reset_tracker", action="store_true",
help="Reset the tracker file and start fresh."
)
args = parser.parse_args()
assert os.path.isdir(args.video_dir), f"Directory {args.video_dir} does not exist."
# Handle tracker file
if args.reset_tracker and exists(args.tracker_file):
os.remove(args.tracker_file)
print(f"> Reset tracker file: {args.tracker_file}")
# Check if we have pending videos from previous run
pending_videos = load_pending_videos(args.tracker_file)
if pending_videos:
print(f"> Found {len(pending_videos)} pending videos from previous run")
ifiles = pending_videos
ofiles = pending_videos # In-place replacement
else:
# Start fresh - find all videos
pattern = os.path.join(args.video_dir, f"**/*.{args.ext}")
ifiles = glob(pattern, recursive=True)
ifiles = natsorted(ifiles)
ofiles = ifiles # In-place replacement
print("> Number of videos in the directory:", len(ifiles))
# Apply start/end index filtering
si = args.si if args.si is not None else 0
ei = args.ei if args.ei is not None else len(ifiles)
print("> Start index:", si)
print("> End index:", ei)
ifiles = ifiles[si:ei]
ofiles = ofiles[si:ei]
# Save to tracker file for future runs
save_pending_videos(args.tracker_file, ifiles)
print(f"> Saved {len(ifiles)} videos to tracker file: {args.tracker_file}")
print("> Number of videos to downsize:", len(ifiles))
iterator = log.tqdm_iterator(
range(len(ifiles)), total=len(ifiles), desc="Downsizing videos",
)
for i in iterator:
ifile = ifiles[i]
ofile = ifile
assert exists(ifile), f"Video {ifile} does not exist."
tmp_ofile = ifile + ".tmp.mp4"
start_time = time.time()
resize_video_simple(ifile, tmp_ofile, width=args.width)
end_time = time.time()
time_taken = end_time - start_time
desc = f"Time taken {time_taken:.2f}s for {basename(ifile)}"
iterator.set_description(desc)
if args.debug:
yold, srold = librosa.load(ifile, offset=1.0, duration=1.0)
ynew, srnew = librosa.load(tmp_ofile, offset=1.0, duration=1.0)
assert srold == srnew, "Sampling rate mismatch."
assert len(yold) == len(ynew), "Length mismatch."
assert np.allclose(yold, ynew), "Audio mismatch."
vr = VideoReader(tmp_ofile)
frames = vr.get_batch(range(0, 10)).asnumpy()
assert frames.shape[0] == 10, "Length mismatch."
assert frames.shape[2] == args.width, "Width mismatch."
# Replace original file
os.replace(tmp_ofile, ofile)
# Remove completed video from tracker
remove_completed_video(args.tracker_file, ifile)
if args.remove_old:
# Already replaced, so nothing to remove
pass
# Clean up tracker file if all videos are done
if not load_pending_videos(args.tracker_file):
os.remove(args.tracker_file)
print(f"> All videos completed. Removed tracker file: {args.tracker_file}")
else:
remaining = len(load_pending_videos(args.tracker_file))
print(f"> {remaining} videos remaining. Tracker file preserved: {args.tracker_file}") |