我试图从~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上。