Last active
November 12, 2019 06:33
-
-
Save brakkum/4aff9c6711d718bd5af50bae6368b6fd to your computer and use it in GitHub Desktop.
A Python script that is supplied a directory, and recursively goes through said directory and compresses all photos/videos it finds of types specified in file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from moviepy.editor import VideoFileClip, vfx | |
from PIL import Image | |
import imageio | |
import shutil | |
import imghdr | |
import numpy | |
import rawpy | |
import time | |
import sys | |
import os | |
# no dir provided | |
if len(sys.argv) <= 1: | |
print("give me a dir") | |
exit() | |
_dir = sys.argv[1] | |
# bad dir | |
if not os.path.isdir(_dir): | |
print("give me a single dir that exists") | |
exit() | |
# current dir | |
elif _dir.startswith("."): | |
print("plz no parent dir shenanigans") | |
exit() | |
if _dir[len(_dir) - 1] == "/": | |
_dir = _dir[:-1] | |
# what makes new dir unique | |
append = "-copy-{}".format(time.time()) | |
# dir where copies are saved | |
new_dir = "{}{}".format(_dir, append) | |
# this shouldn't happen, but if copy dir exists | |
# destroy it | |
if os.path.isdir(new_dir): | |
shutil.rmtree(new_dir, ignore_errors=True) | |
# make dir for copies | |
os.mkdir(new_dir) | |
# max width or height | |
max_image_dimension = 1200, 1200 | |
# replace first instance of dir supplied | |
# to the dir name where copies are kept | |
def get_new_copies_dir_name(path): | |
return path.replace(_dir, new_dir, 1) | |
# log to an error file | |
def log_error(err): | |
with open("dup_errors_{}".format(new_dir), mode="a+") as err_file: | |
err_file.writelines("{}\n".format(err)) | |
# recursive func to traverse dirs and convert | |
# photos into small jpgs | |
def convert_photos_in_dir(_next_dir): | |
print("Next Dir: {}".format(_next_dir)) | |
# get copies dir name for current directory | |
_new_photos_dir = get_new_copies_dir_name(_next_dir) | |
# current dir being converted | |
_this_dir = _next_dir | |
# mkdir in copies dir | |
if not os.path.exists(_new_photos_dir): | |
os.mkdir(_new_photos_dir) | |
# loop through them files | |
for file in os.listdir(_this_dir): | |
# full file path including given dir | |
_this_file = "{}/{}".format(_this_dir, file) | |
# file is dir, recurse | |
if (os.path.isdir(_this_file)): | |
convert_photos_in_dir(_this_file) | |
# not a dir, check if valid file we want | |
else: | |
compressed_file_types = [".jpeg", ".jpg", ".png"] | |
raw_file_types = [ ".nef", ".orf"] | |
tiff_file_types = [".tif", ".tiff"] | |
video_file_types = [".mp4", ".mov"] | |
file_ext = os.path.splitext(file)[1].lower() | |
# raw files | |
if file_ext in raw_file_types: | |
print("Photo {}".format(_this_file)) | |
try: | |
with rawpy.imread(_this_file) as photo: | |
temp_file = "{}/{}.tiff".format(_new_photos_dir, file) | |
imageio.imsave(temp_file, photo.postprocess()) | |
with Image.open(temp_file) as temp_photo: | |
out_file = "{}/{}-raw.jpg".format(_new_photos_dir, file) | |
temp_photo.thumbnail(max_image_dimension, Image.ANTIALIAS) | |
temp_photo.save(out_file, "JPEG") | |
os.remove(temp_file) | |
except: | |
print("Error: {}".format(_this_file)) | |
log_error(_this_file) | |
# already compressed files | |
elif file_ext in compressed_file_types: | |
print("Photo {}".format(_this_file)) | |
try: | |
with Image.open(_this_file) as photo: | |
photo.thumbnail(max_image_dimension, Image.ANTIALIAS) | |
photo.save("{}/{}".format(_new_photos_dir, file), "JPEG") | |
except: | |
print("Error: {}".format(_this_file)) | |
log_error(_this_file) | |
# tiffs | |
elif file_ext in tiff_file_types: | |
print("Photo {}".format(_this_file)) | |
try: | |
with Image.open(_this_file) as tiff_file: | |
tiff_array = numpy.array(tiff_file) | |
im = Image.fromarray(tiff_array) | |
im = im.convert("RGB") | |
im.thumbnail(max_image_dimension, Image.ANTIALIAS) | |
im.save("{}/{}.jpg".format(_new_photos_dir, file), "JPEG") | |
except: | |
print("Error: {}".format(_this_file)) | |
log_error(_this_file) | |
# video files | |
elif file_ext in video_file_types: | |
try: | |
video = VideoFileClip(_this_file).fx(vfx.resize, width=1000) | |
out_file = "{}/{}".format(_new_photos_dir, file) | |
video.write_videofile(out_file, | |
preset="veryslow", | |
codec="libx264", | |
audio_codec="aac", | |
temp_audiofile="temp-audio.m4a", | |
remove_temp=True | |
) | |
except: | |
print("Error: {}".format(_this_file)) | |
log_error(_this_file) | |
# pngs | |
elif file_ext in png_types: | |
print("Photo {}".format(_this_file)) | |
try: | |
with Image.open(_this_file) as photo: | |
photo.thumbnail(max_image_dimension, Image.ANTIALIAS) | |
photo.save("{}/{}".format(_new_photos_dir, file), "PNG") | |
except: | |
print("Error: {}".format(_this_file)) | |
log_error(_this_file) | |
# start at given dir | |
convert_photos_in_dir(_dir) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment