1

I understand this has been issued many times but I thought this has been solved altogether. Following is my code ..

from moviepy.editor import *
from random import randint
import os
import subprocess

files = os.listdir('.')
for sourceVideo in files:
    if (sourceVideo[-4:] == ".mp4") or (sourceVideo[-4:] == ".wmv"):
        framerate=10
        filename=sourceVideo
        print(filename)
        clip = VideoFileClip(filename)
        print( clip.duration )
        if  clip.duration < 600:
            for x in range(1,int(clip.duration/60)):
                #print( int(clip.duration/60) ) 
                fi = randint(1,int(clip.duration/60))
                if x == 1:
                    suclip=VideoFileClip(filename).subclip(fi,fi+3).resize(height=182, width=325)
                else:
                    suclip =concatenate_videoclips([suclip,VideoFileClip(filename).subclip(fi+(60*x),fi+3+(60*x))]).resize(height=182, width=325)
        if  clip.duration > 600:
            for x in range(1,int(int(clip.duration/60)/2)):
                #print( int(int(clip.duration/60)/2) )
                fi = randint(1,118)
                if x == 1:
                    suclip=VideoFileClip(filename).subclip(fi,fi+2).resize(height=182, width=325)
                else:
                    suclip =concatenate_videoclips([suclip,VideoFileClip(filename).subclip(fi+(120*x),fi+2+(120*x))]).resize(height=182, width=325)
        suclip.write_gif(filename+".gif",fps=framerate)

Above code looks for all mp4 or wmv format files and then for each file gets 2 or 3 sec duration subclips and merges them and then convert it to gifs.

Code works fine for first mp4 file in folder. But when it reaches to second one it throws error as below.

Error

Now, I have seen following links for solutions. Getting "OSError: [WinError 6] The handle is invalid" in VideoFileClip function

https://github.com/Zulko/moviepy/issues/73

and many more similars.

All of them suggesting to add one or another of below solutions like adding following..

    clip.reader.close()
    clip.audio.reader.close_proc()
    clip.__del__()
    del suclip
    del clip
    subprocess._cleanup()

I have tried putting all of them at the end of my code , after it writes gif file. But error still persists.

It works and creates gif of first video of folder without any problem or error at all. File size of each mp4 is around 100MB.

I also tried on using this

adition=VideoFileClip(filename).subclip(fi+(120*x),fi+2+(120*x))
suclip = concatenate_videoclips([suclip,adition]).resize(height=182, width=325)
del adition

instead of this

suclip =concatenate_videoclips([suclip,VideoFileClip(filename).subclip(fi+(120*x),fi+2+(120*x))]).resize(height=182, width=325)

but it didn't help.

Any solutions will be appreciated. Thank you. :)

Kesh
  • 263
  • 1
  • 3
  • 14
  • To test it just put bunch of mp4 of any size along with it in a folder and run it. It produces error on second gif production. – Kesh Feb 23 '18 at 13:10

1 Answers1

0

So It seems that there is ongoing bug related to it (Something about handling memory? which I read on some of the dozens sites I went through.), I would be glad to find my assumption wrong but it seems that way. As a temporary work around, following method helped me.

I separated my above script into two python scripts. It's not ideal but if it works it ain't stupid right!? At least it works.

first python script calls with argument to second python script.

Following is first script.

from random import randint
import os
import sys
files = os.listdir('.')
for sourceVideo in files:
    if (sourceVideo[-4:] == ".mp4") or (sourceVideo[-4:] == ".wmv"):
        filedir= sys.argv[0]
        filedir=filedir.replace(os.path.basename(sys.argv[0]),'')
        os.system('extra.py "'+sourceVideo+'"') #or os.system('python extra.py "'+sourceVideo+'"') or os.system('python3 extra.py "'+sourceVideo+'"')

second script is placed along side of the first script and named 'extra.py' which accepts filename (here name of mp4 or wmv file to convert to gif) as an sys argument. I know this isn't pretty but went through dozens of places to find answer and no luck, so here is the second script.

from moviepy.editor import *
from random import randint
import os
import sys
framerate=10

for x in sys.argv:
     if (x[-4:] == ".mp4") or (x[-4:] == ".wmv"):
        filename=x
print(filename)
clip = VideoFileClip(filename)
if  clip.duration < 600:
    for x in range(1,int(clip.duration/60)):
        fi = randint(1,int(clip.duration/60))
        if x == 1:
            suclip= VideoFileClip(filename).subclip(fi,fi+3).resize(height=182, width=325)
        else:
            adition=VideoFileClip(filename).subclip(fi+(60*x),fi+3+(60*x))
            suclip = concatenate_videoclips([suclip,adition]).resize(height=182, width=325)
if  clip.duration > 600:
    for x in range(1,int(int(clip.duration/60)/2)):
        fi = randint(1,118)
        if x == 1:
            suclip= VideoFileClip(filename).subclip(fi,fi+2).resize(height=182, width=325)
        else:
            adition=VideoFileClip(filename).subclip(fi+(120*x),fi+2+(120*x))
            suclip = concatenate_videoclips([suclip,adition]).resize(height=182, width=325)
suclip.write_gif(filename+".gif",fps=framerate)

So as you can see from my question, that first file conversion(mp4 to gif) is always without bug, I used that to my advantage by making another script so that second script is ran by it, and for that second file, it is always first file conversion. May be that sentence didn't make any sense lol but hopefully you get the point why I did what I did.. So till the bug is solved in future, this was my solution.

Bug also exist during compiling this files to exe using PyInstaller, which is related to imageio module which is used by moviepy. So, can't convert to exe for now.

Kesh
  • 263
  • 1
  • 3
  • 14