2016-01-28 47 views
7

Szukałem kilku dni w związku z tym problemem, ale nie znalazłem rozwiązania. Mam duży skrypt (próbuję połączyć dużą liczbę filmów, ~ 100-500), dlatego pojawił się błąd "Zbyt wiele otwartych plików". Czytając odpowiedzi Zulko do innych zagadnień, widziałem, że to było konieczne, aby usunąć każdą instancję VideoFileClip ręcznie tak:Instancja MoviePy VideoFileClip nie ma atrybutu "czytnik"

del clip.reader 
del clip 

Problem mam w obliczu jest, że mam prosty hello_world starając się to zrobić, ale dostać błąd VideoFileClip instance has no attribute 'reader' Oto kod:

from moviepy.editor import * 
rel_path = "main.py" 
file_path="hello_world.mp4" 
newVideo = VideoFileClip(file_path) 
del newVideo.reader 
del newVideo 

Używam El Capitan (OS X), zostały zaktualizowane MoviePy, Numpy, ImageMagick, a wszystkie pakiety widziałem jak jest to wymagane, ale nadal jestem coraz to błąd. Problemem jest to, że mój komputer czasami zamarza, ponieważ zużywa tyle pamięci. Aktualnie łączę 25 kawałków i próbuję usunąć wszystkie 25 "otwartych plików", połączyć kolejne 25 i tak dalej. Potem połączyłem dłuższe filmy.

Należy pamiętać, że bez linii del newVideo.reader nadal pojawia się błąd Zbyt wiele plików otworzyć

gdy próbuję działa prawdziwy scenariusz, pojawia się następujący błąd, jeśli ja nie dodawać newVideo.reader

Traceback (most recent call last): 
    File "/Users/johnpeebles/mispistachos/vines/video/reader.py", line 135, in compile_videos 
    newVideo = VideoFileClip(videoPath).resize(height=finalHeight,width=finalWidth).set_position('center').set_start(currentDuration) 
    File "/Library/Python/2.7/site-packages/moviepy/video/io/VideoFileClip.py", line 55, in __init__ 
    reader = FFMPEG_VideoReader(filename, pix_fmt=pix_fmt) 
    File "/Library/Python/2.7/site-packages/moviepy/video/io/ffmpeg_reader.py", line 32, in __init__ 
    infos = ffmpeg_parse_infos(filename, print_infos, check_duration) 
    File "/Library/Python/2.7/site-packages/moviepy/video/io/ffmpeg_reader.py", line 237, in ffmpeg_parse_infos 
    proc = sp.Popen(cmd, **popen_params) 
    File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 710, in __init__ 
    errread, errwrite) 
    File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 1223, in _execute_child 
    errpipe_read, errpipe_write = self.pipe_cloexec() 
    File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 1175, in pipe_cloexec 
    r, w = os.pipe() 
OSError: [Errno 24] Too many open files 
Error compiling videos 
Exception AttributeError: "VideoFileClip instance has no attribute 'reader'" in <bound method VideoFileClip.__del__ of <moviepy.video.io.VideoFileClip.VideoFileClip instance at 0x136e46908>> ignore 

Zgodnie z życzeniem Tynn, publikuję "prawdziwy kod". To, co tu robię, to, jak wyjaśniłem powyżej, kompilacja filmów w porcjach 25 filmów, a następnie skompilowanie wszystkich tych wstępnie skompilowanych filmów w jeden duży film. Dostaję błąd Too Many Files Open teraz (jeśli nie dodawać del clip.reader) sam

for videoObject in data["videos"]: 
     counter+=1 
     #Download video and thumbnail 
     downloader=urllib.URLopener() 
     videoId = videoObject[API_VIDEO_ID] 
     videoUrl = str(videoObject[API_VIDEO_URL]) 
     videoPath =os.path.join(file_dir, "tmp",str(videoObject[API_VIDEO_ID].replace("/",""))+'_video.mp4') 
     thumbPath =os.path.join(file_dir, "tmp",str(videoObject[API_VIDEO_ID].replace("/",""))+'_thumb.jpg') 
     currentVideoDimension = videoObject[API_VIDEO_DIMENSIONS] 
     currentVideoWidth = currentVideoDimension[0] 
     currentVideoHeight = currentVideoDimension[1] 

     thumbUrl = str(videoObject[API_THUMB_URL]) 
     finalWidth = w*1.0 
     finalHeight = h*1.0 
     videoProportion = (float(currentVideoWidth)/float(currentVideoHeight)) 
     if currentVideoWidth >= currentVideoHeight: 
      finalHeight = finalWidth/videoProportion 
     else: 
      finalWidth = finalHeight*videoProportion 


     try: 
      download(videoUrl, videoPath) 
      download(thumbUrl, thumbPath) 
     except Exception as e: 
      print("Exception: "+str(e)) 
      print("Video ID: "+str(videoId)) 
      traceback.print_exc() 
      continue 
     #Create new video and update video duration's offset 
     newVideo = VideoFileClip(videoPath).resize(height=finalHeight,width=finalWidth).set_position('center').set_start(currentDuration) 
     #If it's not squared we append a video first 
     if videoProportion != float(1): 
      backgroundClip = ColorClip(size=((w,h)), col=colors.hex_to_rgb("#000")).set_position("center").set_start(currentDuration).set_duration(newVideo.duration) 
      videos_and_subtitles.append(backgroundClip) 
     #Append new video to videos 

     videos_and_subtitles.append(newVideo) 
     #Append subtitle to Subtitles 
#   newSubtitleText = max_text(videoObject[API_NAME],videoObject[API_AUTHOR])+" \n\n"+videoObject[API_AUTHOR] 
     videoName = clean(videoObject[API_NAME]) 
     videoAuthor = clean(videoObject[API_AUTHOR]) 
     newSubtitleText = clean(max_text(videoName,videoAuthor)+" \n\n"+videoObject[API_AUTHOR]) 
     newSubtitle = (TextClip(newSubtitleText,fontsize=70,color='white',font='Helvetica-Narrow',align='center',method='caption',size=titleDimensions).set_start(currentDuration).set_position((videoOffset+w,0)).set_duration(newVideo.duration)) 
     videos_and_subtitles.append(newSubtitle) 




     currentDuration+=newVideo.duration 

     #Preprocess videos 
     if counter%50==0 or len(data["videos"])==(counter): 
      if closure_video_path != None and closure_video_path != "" and len(data["videos"])==(counter): 
       newVideo = VideoFileClip(closure_video_path).resize(height=finalHeight,width=finalWidth).set_position((videoOffset,titleOffset)).set_start(currentDuration) 
       videos_and_subtitles.append(newVideo) 
       currentDuration+=closure_video_duration 

      currentFilename=os.path.join(file_dir, "tmp",str(videoNumber)+fileName) 
      result = CompositeVideoClip(videos_and_subtitles,size=movieDimensions,bg_color=colors.hex_to_rgb(background_color)).set_duration(currentDuration).write_videofile(filename=currentFilename,preset='ultrafast',fps=24) 

      del result 

      preprocessedVideos.append(VideoFileClip(currentFilename)) 

      #Close files 
      #close_files(videos_and_subtitles) 
      for clip in videos_and_subtitles: 
       try: 
        if not (isinstance(clip,ImageClip) or isinstance(clip,TextClip)): 
         del clip 
        else: 
         del clip 
       except Exception,e: 
        print "Exception: "+str(e) 
      #End Close files       


      videos_and_subtitles = [] 
      videos_and_subtitles.append(left_holder) 
      currentDuration = 0 
      videoNumber+=1 
      if (videoObject==data["videos"][-1]): 
       break 
     print("Next video") 


    print("Compiling video") 

    filepath = os.path.join(file_dir, "tmp",fileName) 
    result = concatenate_videoclips(preprocessedVideos).write_videofile(filename=filepath, preset='ultrafast') 
    #result = CompositeVideoClip(videos_and_subtitles,size=movieDimensions,bg_color=(0,164,119)).set_duration(currentDuration).write_videofile(filename=directory+"/"+fileName,preset='ultrafast') 
    print("Video Compiled") 
    now = datetime.datetime.now() 
    print("Finished at: "+str(now)) 
    return filepath 
except Exception as e: 
    print("Exception: "+str(e)) 
    print("Video ID: "+str(videoId)) 
    traceback.print_exc() 
    rollbar.report_exc_info() 
    return None 
+0

W pętli for usuniesz odwołanie, które właśnie utworzyłeś wcześniej. Nic tam nie zamykasz. 'videos_and_subtitles = []' usuwa odniesienia na liście. Może nawet ~ 50 referencji na twojej liście i zawartość 'preprocessedVideos' są za dużo. – tynn

+0

Co masz na myśli, że niczego nie zamykam? Każdego elementu usuwam w videos_and_subtitles co 50 filmów (lub kiedy docieram do ostatniego filmu). W preprocessedVideos nie zawiera więcej niż 1-3 elementów (jest to wideo, które zostało wygenerowane po skompilowaniu 50 filmów, więc jeśli mam 150 filmów, będę miał 3 teledyski złożone) – Waclock

+0

Po użyciu polecenia CompositeVideoClip, usunę go i utworzę nowe odniesienie do nowego wideo (wykonane z 50 filmów). – Waclock

Odpowiedz

2

Zulko writes:

W kolejnych wersjach MoviePy tylko del clip wystarczy.

To było przed wydaniem wersji 0.2.2. Wygląda więc na to, że nie musisz wykonywać del clip.reader.

Aby być bardziej precyzyjnym, nie wolno tego robić! VideoFileClip definiuje destruktora robi to za ciebie:

def __del__(self): 
    """ Close/delete the internal reader. """ 
    del self.reader 

Ale skoro już usunięte go już Ci w AttributeError:

instancja VideoFileClip nie ma atrybutu 'czytnik'

w <bound method VideoFileClip.__del__ of <...VideoFileClip instance at 0x13..>>

+0

Witaj Tynn, dzięki za twoją odpowiedź. Masz rację, zapomniałem wspomnieć, że jeśli wstawiam tylko "del clip", pojawia się błąd "Zbyt wiele otwartych plików", więc to też nie jest dobre: ​​/ – Waclock

+0

@Kodowanie należy usunąć wszystkie odniesienia do 'klipu' samo. Czy próbowałeś zrobić 'clip.reader = None'? Powinno to mieć taki sam efekt jak usunięcie bez efektu ubocznego. – tynn

+0

Spróbuję. Sądzę, że mam, tworzę tablicę i pcham każdy obiekt klipu, następnie iteruję obiekt i usuwam każdą instancję klipu, który mam. – Waclock

0

Mam rozwiązać moje pytanie, które jest opisane szczegółowo na https://github.com/Zulko/moviepy.

Po zainstalowaniu ImageMagick, zostanie automatycznie wykryty przez MoviePy, z wyjątkiem systemu Windows! Przed instalacją MoviePy ręcznie, użytkownicy Windowsa muszą edytować moviepy/config_defaults.py, aby podać ścieżkę do pliku binarnego ImageMagick, który nazywa się convert. Powinno to wyglądać tak: IMAGEMAGICK_BINARY = "C:\\Program Files\\ImageMagick_VERSION\\convert.exe".