Skip to content

Instantly share code, notes, and snippets.

@wrybread
Created March 25, 2023 22:23
Show Gist options
  • Save wrybread/777ba824b54e2f2553782f0fd687476c to your computer and use it in GitHub Desktop.
Save wrybread/777ba824b54e2f2553782f0fd687476c to your computer and use it in GitHub Desktop.
Video compressor for DJI drone videos (or anything else)
#!/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