1

400 までの動画から大きな動画を作成しようとしていますが、「開いているファイルが多すぎます」という問題に直面しています。私はドキュメントを読みました (そしてこの投稿を見ました)。

しかし、私はまだ同じエラーが発生しています:OSError: [Errno 24] Too many open files

メソッドで開いている各ムービーを既に削除している場合、調査しましたが、他に何をすべきかわかりませんclose_files

コード:

from moviepy.editor import *
import json
import os
import urllib
import shutil
import re
import api.constants
import traceback
from api.constants import *
import datetime
import string


def close_files(files):
    for file in files:
        try:
            if not (isinstance(file,ImageClip) or isinstance(file,TextClip)):
                del file.reader
            del file
        except Exception,e:
            print "Exception: "+str(e)

def max_text(title,author):
    return title
    #if len(title) > 120:
    #    return title[0:(120- len(author))]+"..."
    #else:
    #    return title

def clean(text):
    return ''.join(filter(lambda x: x in string.printable, text))

def compile_videos(fileName,serverjson,post_to):
    try:
        now = datetime.datetime.now()
        print "Starting at: "+str(now)

        #Video's dimensions
        w = 1440
        h = 1440
        videoDimension = w,h

        #Video offset
        videoOffset = 580
        titleOffset = 0

        #Movie dimensions
        w2 = 2560
        h2 = 1440
        movieDimensions = w2,h2

        #Title dimensions
        w3 = 540
        h3 = 1440
        titleDimensions = w3,h3

        #Left Holder Dimension
        holderDimensions = 500,500
        holderPosition = 50,450


        #Holder
        left_holder = ImageClip("assets/everyday_icon.png").set_position(holderPosition)
        if post_to=="7min":
            left_holder = ImageClip("assets/7min_icon.png").set_position(holderPosition)
        elif post_to=="7x7":
            left_holder = ImageClip("assets/7x7_icon.png").set_position(holderPosition)

        #Temporal directory
        directory = 'tmp'
        if os.path.exists(directory):
          shutil.rmtree(directory)
        if not os.path.exists(directory):
          os.makedirs(directory)

        #Read Videos/Files

        data = serverjson

        videos_and_subtitles = []
        #We add the holder so that there's always a background
        videos_and_subtitles.append(left_holder)

        currentDuration = 0
        videoId = ""
        preprocessedVideos = []
        counter = 0
        videoNumber = 0
        print "Total videos: "+str(len(data["videos"]))
        for videoObject in data["videos"]:
            counter+=1
            #Download video and thumbnail
            downloader=urllib.URLopener()
            videoId = videoObject[API_VIDEO_ID]
            videoPath = directory+"/"+str(videoObject[API_VIDEO_ID])+'_video.mp4'
            thumbPath = directory+"/"+str(videoObject[API_VIDEO_ID])+'_thumb.jpg'
            try:
                downloader.retrieve(str(videoObject[API_VIDEO_URL]),videoPath)
                downloader.retrieve(str(videoObject[API_THUMB_URL]),thumbPath)
            except Exception,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=w,width=h).set_position((videoOffset,titleOffset)).set_start(currentDuration)
            #Append new video to videos

            videos_and_subtitles.append(newVideo)
            #Append subtitle to Subtitles
            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):
                currentFilename=directory+"/"+str(videoNumber)+fileName
                result = CompositeVideoClip(videos_and_subtitles,size=movieDimensions,bg_color=(0,164,119)).set_duration(currentDuration).write_videofile(filename=currentFilename,preset='ultrafast',fps=24)
                preprocessedVideos.append(VideoFileClip(currentFilename))
                close_files(videos_and_subtitles)
                videos_and_subtitles = []
                currentDuration = 0
                videoNumber+=1
                if (videoObject==data["videos"][-1]):
                    break
            print "Next video"

        print "Compiling video"
        result = concatenate_videoclips(preprocessedVideos).write_videofile(filename=directory+"/"+fileName,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 fileName
    except Exception,e:
        print "Exception: "+str(e)
        print "Video ID: "+str(videoId)
        traceback.print_exc()
        return None

小さいバッチで処理すると時間がかかるため、ファイルを 50 個のバッチで処理しています。問題は、一度に 50 個のファイルを開くことではありません。この問題は、最初または 2 番目のバッチ (処理された 100 ~ 150 個のファイル) の後に発生します。これは、ファイルが閉じられていないことを示しています (そうでなければ、最初のバッチは正しく処理されませんでした)。これは、10 個のバッチで実行すると同じことが起こることを意味します。ファイルが正しく閉じられていないだけです。

あなたが答えを見ることができるように、このような他の投稿:

テスト スクリプトは反復ごとに f を上書きします。つまり、ファイルは毎回閉じられます。ファイルへのロギングとパイプを使用したサブプロセスの両方で記述子が使い果たされ、枯渇する可能性があります。

50回の反復ごとにインスタンスを上書きしているため、まったく当てはまりませんが、まだ問題があります。

また、VideoFileClip で「閉じる」を呼び出すことはできません。

4

0 に答える 0