Created
March 25, 2023 22:23
-
-
Save wrybread/777ba824b54e2f2553782f0fd687476c to your computer and use it in GitHub Desktop.
Video compressor for DJI drone videos (or anything else)
This file contains 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
#!/usr/bin/python | |
''' | |
This takes a directory of video files and compresses them. | |
Made because my DJI Mini 3 Pro drone makes such gigantic raw files (about 1.5 gigs per 5 minutes), which wouldn't play on my Chromecast | |
To do: | |
- exclude target folder more intelligently | |
- change subprocess command soit doesn't spawn a window? | |
''' | |
import sys, os, subprocess, time | |
from datetime import datetime | |
# figure out the current directory | |
if getattr(sys, 'frozen', False): current_directory = os.path.dirname(sys.executable) | |
else: current_directory = os.path.dirname( os.path.abspath(sys.argv[0]) ) | |
# where are the uncompressed videos? | |
input_directory = "e:/Drone Footage" | |
# directory to put the compressed videos | |
output_directory = "e:/Drone Footage/compressed" | |
# path to FFMPEG | |
ffmpeg = os.path.abspath(current_directory + "/ffmpeg.exe") | |
print ( "Making a listing of all the videos in %s" % input_directory ) | |
videos = [] | |
for path, dirs, files in os.walk(input_directory): | |
for filename in files: | |
extension = os.path.splitext(filename)[1].lower() | |
if extension == ".mp4" and "zzz" not in filename and "zzz" not in path and "compressed" not in path and filename[0] != ".": | |
filename_complete = os.path.abspath( os.path.join(path, filename) ) | |
videos.append( filename_complete ) | |
print ( "Found %s videos in %s..." % (len(videos), input_directory) ) | |
time.sleep(2) | |
done_counter = 0 | |
skipped_counter = 0 | |
overral_start_time=time.time() | |
try: os.makedirs(output_directory) | |
except: pass | |
for input_fname in videos: | |
print ("\nStarting %s of %s %s" % (videos.index(input_fname)+1, len(videos), input_fname)) | |
# check if target already exists and if so confirm that it's not a 1kb file | |
output_fname = os.path.abspath(output_directory + "/" + os.path.basename(input_fname)) | |
if os.path.exists(output_fname): | |
fsize = os.stat(output_fname).st_size | |
if fsize > 1500: | |
skipped_counter+=1 | |
print ( "The file %s exists and has size (%s), so skipping it (skip #%s)" % (output_fname, fsize, skipped_counter) ) | |
continue | |
######################## | |
# compose FFmpeg command | |
######################## | |
# ffmpeg -i input.mp4 -vcodec libx265 -crf 28 output.mp4 | |
cmd = '"%s" ' % ffmpeg | |
cmd += "-y " # say "yes" to overwrite the target file if present | |
cmd += '-i "%s" ' % input_fname | |
# which codec? | |
cmd += "-vcodec libx264 " | |
# scale the 4k down to 1080p. Otherwise this command couldn't process 4k video. Probably fixable in some other way. | |
cmd += "-vf scale=1920:1080 " | |
# The range of the CRF scale is 0-51, where 0 is lossless, 23 is the default | |
cmd += "-crf 28 " | |
cmd += '"%s"' % output_fname | |
print (cmd) | |
# save the command just for goofs | |
handle = open(current_directory + "/last_cmd.txt", "w") | |
handle.write(cmd) | |
handle.close() | |
start_time = time.time() | |
# spawn a window and process the output | |
p = subprocess.Popen(cmd) | |
p.communicate() | |
''' | |
# Another way of running the command that can process the frame number | |
p = subprocess.Popen(cmd, | |
stdout=subprocess.PIPE, | |
stderr=subprocess.PIPE, | |
universal_newlines=True) # This flag converts carriage return chars to new lines | |
while p.poll() is None: # While the process p is still running | |
line = p.stderr.readline() | |
#line = p.stdout.readline() | |
print(line) | |
''' | |
done_counter+=1 | |
total_time = int(time.time() - start_time) # | |
total_time_hms = time.strftime('%H:%M:%S', time.gmtime(total_time)) # format the time as hh:mm:ss | |
print ( "Done in %s" % (total_time_hms) ) | |
total_time = int(time.time() - overral_start_time) # | |
total_time_hms = time.strftime('%H:%M:%S', time.gmtime(total_time)) # format the time as hh:mm:ss | |
print ( "\nDone compressing %s videos in %s" % (done_counter, total_time_hms) ) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment