Help with space by converting MP4 into time elapse
Origin
The idea came from a very weird situation. My friend was at the issue of getting in a small crash and he wanted to see if it was possible to get his dash camera feed. Personally, I didn't actually end up using the program for that but that is beside the point. I used test data of phone footage as it was the only thing that I could find that would be worth the time elapsed at the time.
Setting up
First of all, I created this to be command-line based with everything in the same folder to limit the amount of confusion that will be going on. I would love to make GUI but for a small project like this is it not worth it.
So to start out you will need to grab the FFmpeg file as that is needed to read most video formats. Just go to this website and download it putting it in the same folder as the project.
The final part of the setup is having python installed. I used python because of my familiarity with the image processing class and written programs with it in the past.
This project was a beast and took a day and a half to write because of processing time and the number of issues I ran into. I will try and keep it brief but I had 8 versions if that tells you how many issues I had.
Step 1: The Overview
So I know the process overview of what the code was going to look like. At first, it was going to be efficient and take a lot of writing but I wanted to guarantee the highest possibility of testing without wasting a lot of resources. Another huge factor was I couldn't find how to do input and output at the same time for video files.
I would take apart the video by specific frame times and then put them together into a gif. From there I could turn it back into an mp4 if wanted. Sounds so simple but in so many places it went wrong.
Step 2: The Starting Code
The process of writing the first version of the code. It has a lot of mistakes and the thought process was a little long because after my research not much was out there for a project like this. I might not have done good enough research but I guess it was ok with me so far.
Turning mp4 into photos
This is the easiest version. The issue is the GIF was massive
Also, I used Tinify to make smaller images because the size was an issue, well that backfired a lot. It created horrible images and made me even doubt a gif would work at that point because looking up more it was limited in colors. It was based on the fact it would be better but had to rethink that when this came up.
Overall
Overall view of the first attempt, the code would need a lot of tweaking but I was onto something. It was coming together just inefficiently.
Step 3: Modifications
So at this point, I had a lot of parts of code, but nothing was really solid. I cleaned up the code and got a great main class.
Initial Main Method
The main method I strung together after my first attempt
defmain(): ovfn =input("Enter in the file path: ")# Original Video Filename vidcap = cv2.VideoCapture(ovfn);if (not vidcap.read()):# Is it able to read the fileexit()# Inputting speedprint("I need to collect some data about our new file")print("If you need any help just enter define and I will print some help") initd =input("Do you want more than one frame per second ('Yes' or 'No'): ") duration =0if ("y"in initd):# If you want long videosprint("Ok so that means its going to be long.") duration =input("You want a frame every how many seconds? ")else:# If you want Speed up videosprint("This is going to be a compression, Fun. I love these") duration =input("How many frames do you want in a second? ") duration =1/ duration duration =float(duration)print("Now we must consider the power of the software and Each Videos Properties")''' Printing the properties of the video file ''' framerate = vidcap.get(5) framecount = vidcap.get(7)print("Frame Rate: ", framerate)print("Frame Count: ", framecount)print("Frame Height: ", vidcap.get(CAP_PROP_FRAME_HEIGHT))print("Frame Width: ", vidcap.get(CAP_PROP_FRAME_WIDTH))print("Number of Frames: ", vidcap.get(CAP_PROP_FRAME_COUNT))print("Total Number of Frames: ", framecount * framerate)''' Creating the output folder if it doesn't exist ''' outFold ='data6'# Outputting foldertry:ifnot os.path.exists(outFold): os.makedirs(outFold)exceptOSError:print ('Error: Creating directory of data') speedRate =input("Input the number of frames you want")""" Need to add here the speed rate checking to see if it is a number"""print(type(speedRate)) speedRate =float(speedRate)''' The Actual process of breaking up the MP4 ''' con =0# Counter of the file fileNumb =0# The file Numberwhile fileNumb < (con * secTime):if con >200:# For the longer files cut offprint("You trying to break this. I'm cutting you off")break success, image = vidcap.read()if success: cv2.imwrite(outFold+"/frame"+str(fileNumb) +".jpg", image)# save frame as JPEG fileelse:# At the end of the filebreak con+=1/ speedRate # Adding time to next frame fileNumb +=1# Next frame""" Creating the GIF with the obtained Files """ images = []for i inrange(fileNumb): filename ="data6/frame"+str(i)+".jpg" images.append(imageio.imread(filename)); output_file ='Gif-%s.gif'% datetime.datetime.now().strftime('%Y-%M-%d-%H-%M-%S') imageio.mimsave(output_file, images, duration=duration)print("Time to clean up")print("Releasing all the lose ends") vidcap.release()print("Destroying all the evidence. MWahhhahha") cv2.destroyAllWindows()print("Welp, there we go. We are all done.")print("Continue with the rest of your day")main()
Step 4: Cleaning Up
So I had a solid main class and all it took was modifications to this to get it how I wanted. I was going to do a better interface but after telling people about the program it was more of personal use than wide use. I modified it to work really well and the code was turning to be better
Second take of code
The code after my first day of starting the project
import osimport shutilfrom cv2 import imwrite, CAP_PROP_FRAME_COUNT, CAP_PROP_POS_AVI_RATIO,\ CAP_PROP_POS_MSEC, CAP_PROP_FRAME_HEIGHT, CAP_PROP_FRAME_WIDTHimport cv2import ffmpyimport imageioimport sysimport moviepy.editor as mpimport numpy as npdefcheck(a): # Checks to see if it is Yes or Noreturn"y"in a or"Y"in adefinput_speed():print("I need to collect some data about our new file")print("If you need any help just enter define and I will print some help") initd =input("Do you want to compress The File ('Yes' or 'No') ")# initd = "Yes" duration =0ifnotcheck(initd):# If you want long videosprint("Ok so that means its going to be long.") su =input("Are you sure about that??? ")ifnotcheck(su):print("Thank the lord. That is really not what this is used for") duration =input("How many frames do you want in a second? ")else:print("Fine be that way") duration =input("You want a frame every how many seconds? ")else:# If you want Speed up videosprint("This is going to be a compression, Fun. I love these") duration =input("How many frames do you want in a second? ")# duration = 4returnint(duration)# Return int for no problems''' Add a preference input for this one '''defoutput_exist(outFold): # Make sure output folder existstry:ifnot os.path.exists(outFold): os.makedirs(outFold)print("It has been created. Your welcome")else:print("The output folder already existed. Your good to go")exceptOSError:print ('Error: Creating directory of data')return outFolddefmain(): secTime =1000# Number of MiliSeconds in Second videoFiles = [] # Files need to go through outFold =output_exist("data")# The output folderprint("WELCOME TO MY MP4 TO GIF TO MP4 PROGRAM") numbFold =input("Are you doing a folder ('Yes' or 'No'): ")# numbFold = "No"ifcheck(numbFold):print("Yeah we get to have some fun") vidfol =input("Input the folder name: ")# Folder of Videosprint("PLOT TWIST. I Can't actually do that yet. Come back at another time and check again.") videoFiles.append(input("Enter in the file path of one file: "))else:print("What a shame not using to full potential. Ok so be it") videoFiles.append(input("Enter in the file path: "))for ovfn in videoFiles: ovfn = ovfn.strip("\"")# Takes care of parentheses filename, file_extension = os.path.splitext(ovfn)print("The file name is: "+str(filename))print("With an extension of "+str(file_extension))if(os.path.isdir(ovfn)):# Is a directoryprint("Well "+ ovfn +" is a directory so I'll skip it")breakelifnot("mp4"in file_extension or"MP"in file_extension):print("That isn't a MP4 file silly. I'll let that slide though.")breakelse:# is a file vidcap = cv2.VideoCapture(ovfn)if (not vidcap.read()[0]):# Is it able to read the fileprint("Your a failure at life. That is not a readable file")print("Onward we go") vidcap.release()else: duration =1/input_speed()print("Now it is time for some properties") framerate = vidcap.get(5) framecount = vidcap.get(7) totFrame = framerate * framecount secLength = framecount / framerateprint("Video Length (Seconds): ", secLength)print("Frame Rate: ", framerate)print("Frame Count: ", framecount)print("Frame Height: ", vidcap.get(CAP_PROP_FRAME_HEIGHT))print("Frame Width: ", vidcap.get(CAP_PROP_FRAME_WIDTH))print("Number of Frames: ", vidcap.get(CAP_PROP_FRAME_COUNT))print("Total Number of Frames: ", totFrame)print("Now I know videos can be long and only want 2 min of a 10 min video") capSec = secLengthprint("Here is your chance. The video is "+str(capSec) +" seconds Long") clipped =input("Do you want to make it shorter?\nEnter 'Yes' or 'No': ")ifcheck(clipped):print("Ok so shortening it. Good to hear") newCapSec =float(input("How many Seconds long do you want it (up to "+str(capSec) +" seconds): "))if(newCapSec > capSec):print("That doesn't work. Your trying to break my program. I'll Let you have one more try") newCapSec =input("How many Seconds long do you want it (up to "+str(capSec) +" seconds")if(newCapSec > capSec):print("Well that didn't work so I guess it will not be shortened")else:print("Good you came around and noticed your mistakes") capSec = newCapSecelse:print("Now just let me enter your new shortened length") capSec = newCapSec con =1# Seconds Counter of the fileprint("There are some benifits of this specific program.\nI can create it to be smoother") smo =input("Would you like it smoother ('Yes' or 'No'): ") smoothRate =1# Smoothness of the fileifcheck(smo):print("That is great. Number must be greater than one (I'm not checking)") smoothRate =int(input("How much smoother? "))else:print("You have a lot of faith in a second but have it your way.") fileNumb =0# The File Numberwhile(con < capSec): vidcap.set(cv2.CAP_PROP_POS_MSEC, (secTime * con)) success, image = vidcap.read()if success: cv2.imwrite(outFold +"/frame"+str(fileNumb) +".jpg", image)# Save frame as JPGelse:# At the end of the filebreak con +=1/int(smoothRate) fileNumb +=1""" Creating the GIF with the obtained Files """ images = [] # Files in the folderprint("Putting together "+str(fileNumb) +" files")for i inrange(fileNumb): filenames = outFold +"/frame"+str(i)+".jpg" images.append(imageio.imread(filenames)); output_file = filename +".gif"''' Checking to see that it is a valid File Number ''' fileWorks =False fileCount =0whilenot fileWorks:try:if(os.path.exists(output_file)): output_file = filename +str(fileCount)+".gif" fileCount +=1else: fileWorks =TrueexceptOSError:print('Error when Creating the file name or something') imageio.mimsave(output_file, images, duration=duration)print("Now we have an option since the GIF is probably big") conback =input("Would you like to convert back to a MP4 File? ")ifcheck(conback):# Convert to MP4print("Ok I can convert the GIF to MP4\nJust give me a second") clip = mp.VideoFileClip(output_file) clip.write_videofile(filename +"_Lapse.MP4")else:print("OK. Was just trying to help out")print("Time to clean up")print("Releasing all the lose ends") vidcap.release()print("Destroying all the evidence. MWahhhahha") cv2.destroyAllWindows()print("WARNING: THIS IS GOING TO TAKE UP A LOT OF SPACE") cleanRemove =input("Do you want to delete the folder of all the images.")ifcheck(cleanRemove):print("Cleaning out the files") shutil.rmtree(outFold)print("They have been removed as requested")else:print("It helps on space. Please reconsider") cleanRemove =input("Do you want to delete the folder of all the images.")ifcheck(cleanRemove):print("The hard drive thanks you\nCleaning out the files") shutil.rmtree(outFold)print("They have been removed as requested")else:print("That is a shame. I was trying to save you space.")print("Welp, there we go. We are all done.")print("Continue with the rest of your day")print("Finally we are done")main()"""''' Other Ideas to add '''Creating an input for output folderBeing able to do folders.Simplifying for more modules even though that isn't that bad.Make the software a little smaller"""
Other ideas
I came up with a few ideas at this point
Create an input for the output folder
Being able to do multiple folders in 1 project
Start program with already taken images
Simplify the modules even though it isn't that bad
Making the software smaller
Final Conclusion
The program seemed better in my head but when putting it all together it didn't really live up to my expectations. It did get it done and could add the compression algorithm I already had made a while ago. The really big issue with this project is putting it into gif I thought would make a bigger deal than it did on the size.
Final Code
Final code that is released
import osimport shutilimport cv2import ffmpyimport imageioimport sysimport moviepy.editor as mp#import numpy as npdefcheck(a): # Checks to see if it is Yes or Noreturn"y"in a or"Y"in adefinput_speed():print("I need to collect some data about our new file")print("If you need any help just enter define and I will print some help") initd =input("Do you want to compress The File ('Yes' or 'No') ")# initd = "Yes" duration =0ifnotcheck(initd):# If you want long videosprint("Ok so that means its going to be long.") su =input("Are you sure about that??? ")ifnotcheck(su):print("Thank the lord. That is really not what this is used for") duration =input("How many frames do you want in a second? ")else:print("Fine be that way") duration =input("You want a frame every how many seconds? ")else:# If you want Speed up videosprint("This is going to be a compression, Fun. I love these") duration =input("How many frames do you want in a second? ")# duration = 4returnint(duration)# Return int for no problems''' Add a preference input for this one '''defoutput_exist(outFold): # Make sure output folder existstry:ifnot os.path.exists(outFold): os.makedirs(outFold)print("It has been created. Your welcome")else:print("The output folder already existed. Your good to go")exceptOSError:print ('Error: Creating directory of data')return outFolddefmain(): secTime =1000# Number of MiliSeconds in Second videoFiles = [] # Files need to go through outFold =output_exist("data")# The output folderprint("WELCOME TO MY MP4 TO GIF TO MP4 PROGRAM") numbFold =input("Are you doing a folder ('Yes' or 'No'): ")# numbFold = "No"ifcheck(numbFold):print("Yeah we get to have some fun") vidfol =input("Input the folder name: ")# Folder of Videosprint("PLOT TWIST. I Can't actually do that yet. Come back at another time and check again.")# videoFiles = os.listdir(vidfol) videoFiles.append(input("Enter in the file path of one file: "))else:print("What a shame not using to full potential. Ok so be it") videoFiles.append(input("Enter in the file path: "))for ovfn in videoFiles: ovfn = ovfn.strip("\"")# Takes care of parentheses filename, file_extension = os.path.splitext(ovfn)print("The file name is: "+str(filename))print("With an extension of "+str(file_extension))if(os.path.isdir(ovfn)):# Is a directoryprint("Well "+ ovfn +" is a directory so I'll skip it")breakelifnot("mp4"in file_extension or"MP"in file_extension):print("That isn't a MP4 file silly. I'll let that slide though.")breakelse:# is a file vidcap = cv2.VideoCapture(ovfn)if (not vidcap.read()[0]):# Is it able to read the fileprint("Your a failure at life. That is not a readable file")print("Onward we go") vidcap.release()else: duration =1/input_speed()print("Now it is time for some properties") framerate = vidcap.get(5) framecount = vidcap.get(7) totFrame = framerate * framecount secLength = framecount / framerateprint("Video Length (Seconds): ", secLength)print("Frame Rate: ", framerate)print("Frame Count: ", framecount)print("Frame Height: ", vidcap.get(cv2.CAP_PROP_FRAME_HEIGHT))print("Frame Width: ", vidcap.get(cv2.CAP_PROP_FRAME_WIDTH))print("Number of Frames: ", vidcap.get(cv2.CAP_PROP_FRAME_COUNT))print("Total Number of Frames: ", totFrame)print("Now I know videos can be long and only want 2 min of a 10 min video") capSec = secLengthprint("Here is your chance. The video is "+str(capSec) +" seconds Long") clipped =input("Do you want to make it shorter?\nEnter 'Yes' or 'No': ")ifcheck(clipped):print("Ok so shortening it. Good to hear") newCapSec =float(input("How many Seconds long do you want it (up to "+str(capSec) +" seconds): "))if(newCapSec > capSec):print("That doesn't work. Your trying to break my program. I'll Let you have one more try") newCapSec =input("How many Seconds long do you want it (up to "+str(capSec) +" seconds")if(newCapSec > capSec):print("Well that didn't work so I guess it will not be shortened")else:print("Good you came around and noticed your mistakes") capSec = newCapSecelse:print("Now just let me enter your new shortened length") capSec = newCapSec con =1# Seconds Counter of the fileprint("There are some benifits of this specific program.\nI can create it to be smoother") smo =input("Would you like it smoother ('Yes' or 'No'): ") smoothRate =1# Smoothness of the fileifcheck(smo):print("That is great. Number must be greater than one (I'm not checking)") smoothRate =int(input("How much smoother? "))else:print("You have a lot of faith in a second but have it your way.") fileNumb =0# The File Numberwhile(con < capSec): vidcap.set(cv2.CAP_PROP_POS_MSEC, (secTime * con)) success, image = vidcap.read()if success: cv2.cv2.imwrite(outFold +"/frame"+str(fileNumb) +".jpg", image)# Save frame as JPGelse:# At the end of the filebreak con +=1/int(smoothRate) fileNumb +=1""" Creating the GIF with the obtained Files """ images = [] # Files in the folderprint("Putting together "+str(fileNumb) +" files")for i inrange(fileNumb): filenames = outFold +"/frame"+str(i)+".jpg" images.append(imageio.imread(filenames)); output_file = filename +".gif"''' Checking to see that it is a valid File Number ''' fileWorks =False fileCount =0whilenot fileWorks:try:if(os.path.exists(output_file)): output_file = filename +str(fileCount)+".gif" fileCount +=1else: fileWorks =TrueexceptOSError:print('Error when Creating the file name or something') imageio.mimsave(output_file, images, duration=duration)print("Now we have an option since the GIF is probably big") conback =input("Would you like to convert back to a MP4 File? ")ifcheck(conback):# Convert to MP4print("Ok I can convert the GIF to MP4\nJust give me a second") clip = mp.VideoFileClip(output_file) clip.write_videofile(filename +"_Lapse.MP4")else:print("OK. Was just trying to help out")print("Time to clean up")print("Releasing all the lose ends") vidcap.release()print("Destroying all the evidence. MWahhhahha") cv2.destroyAllWindows()# clip.end()print("WARNING: THIS IS GOING TO TAKE UP A LOT OF SPACE") cleanRemove =input("Do you want to delete the folder of all the images.")ifcheck(cleanRemove):print("Cleaning out the files") shutil.rmtree(outFold)print("They have been removed as requested")else:print("It helps on space. Please reconsider") cleanRemove =input("Do you want to delete the folder of all the images.")ifcheck(cleanRemove):print("The hard drive thanks you\nCleaning out the files") shutil.rmtree(outFold)print("They have been removed as requested")else:print("That is a shame. I was trying to save you space.")print("Welp, there we go. We are all done.")print("Continue with the rest of your day")print("Finally we are done")main()
Code exe
The exe file of the final code. It is in the git repository because I was unable to include all the classes and the size could not be less than 75 MB. It started out being 120 MB.