我试图从大约400个视频中制作一个大视频,但是我面临的问题是"太多的文件打开"

时间:2015-12-18 01:08:32

标签: python batch-processing moviepy

我试图从~400个视频中制作一个大视频,但是我面临的问题是"太多文件打开"。我已阅读文档(并看到了此post)。

但是我仍然遇到同样的错误: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个文件。问题发生在第一批或第二批(处理约100-150个文件)之后,这指向未关闭的文件(否则第一批将无法正确处理)。这意味着如果我以10个批次进行同样的操作,只是文件没有正确关闭

其他帖子,例如this one,您可以看到答案:

  

您的测试脚本会覆盖每次迭代,这意味着每次都会关闭该文件。使用管道记录到文件和子进程都会使用描述符,这可能导致用尽。

并不适用,因为我每50次重复覆盖一次实例,但我仍然遇到问题。

此外,我无法致电"关闭"在VideoFileClip上。

0 个答案:

没有答案