This is a RenderChan module for Olive Video Editor.
Made for use with my patched Olive... make sure you download and build beforehand.
Save the file below to (Renderchan directory)/renderchan/contrib/olive.py.
This is a RenderChan module for Olive Video Editor.
Made for use with my patched Olive... make sure you download and build beforehand.
Save the file below to (Renderchan directory)/renderchan/contrib/olive.py.
__author__ = 'ZoomTen' | |
from renderchan.module import RenderChanModule | |
import subprocess | |
import os, sys | |
from xml.etree import ElementTree | |
import pathlib | |
def get_project_root(path): | |
if os.path.exists(os.path.join(path, "project.conf")) or os.path.exists(os.path.join(path, "remake.conf")): | |
return path | |
else: | |
if os.path.dirname(path) == path: | |
return "" | |
else: | |
return get_project_root(os.path.dirname(path)) | |
class RenderChanOliveModule(RenderChanModule): | |
def __init__(self): | |
RenderChanModule.__init__(self) | |
if os.name == 'nt': | |
self.conf['binary']=os.path.join(os.path.dirname(__file__),"..\\..\\..\\packages\\olive\\olive-editor.exe") # Should change this | |
else: | |
self.conf['binary']="olive-editor-multiexport" | |
self.conf["packetSize"]=0 | |
# I can't make it render in packets unless I can somehow | |
# get Olive to export with a start_number other than 1 | |
# And ffmpeg's API is pretty alien to me, some pointers? | |
self.conf["gpu_device"]="" | |
self.extraParams['use_own_dimensions']='1' | |
self.extraParams['proxy_scale']='1.0' | |
def checkRequirements(self): | |
RenderChanModule.checkRequirements(self) | |
if self.active == False: | |
print("Warning: This module requires a patched version of Olive 0.1.0!") | |
print("You can get the patched version at: https://github.com/ZoomTen/olive/tree/0.1.x-multiexport") | |
return self.active | |
def getInputFormats(self): | |
return ["ove"] | |
def getOutputFormats(self): | |
return ["avi", "mp4", "png", "tif", "mp3"] | |
def analyze(self, filename): | |
info={ "dependencies":[], "width":0, "height":0 } | |
f=open(filename, 'rb') | |
tree = ElementTree.parse(f) | |
root = tree.getroot() | |
media = root.find("media") | |
sequences = root.find("sequences") | |
# get the sequence currently opened | |
active_sequence = sequences.find("sequence[@open='1']") | |
info["width"] = active_sequence.get("width") | |
info["height"] = active_sequence.get("height") | |
for footage in media.iter("footage"): | |
footage_path = os.path.abspath(footage.get("url")) | |
if os.path.exists(footage_path): | |
# direct/static dependency | |
info["dependencies"].append(footage_path) | |
else: | |
# check for render dependency | |
project_root = os.path.abspath( | |
get_project_root(os.path.dirname(filename)) | |
) | |
render_root = os.path.join(project_root, 'render') | |
if footage_path.startswith(render_root): | |
info["dependencies"].append(os.path.dirname(footage_path)) | |
if active_sequence.get("workarea") == '1': | |
# if there's in/out points defined, use that | |
info["startFrame"] = active_sequence.get("workareaIn") | |
info["endFrame"] = active_sequence.get("workareaOut") | |
else: | |
info["startFrame"] = 0 # assume our starting point is 0:00:00 | |
endframe = 0 | |
# last clip's endpoint is our end point for the entire project | |
for clip in active_sequence.iter("clip"): | |
if int(endframe) < int(clip.get("out")): | |
endframe = clip.get("out") | |
info["endFrame"] = endframe | |
f.close() | |
return info | |
def render(self, filename, outputPath, startFrame, endFrame, format, updateCompletion, extraParams={}): | |
comp = 0.0 | |
updateCompletion(comp) | |
totalFrames = endFrame - startFrame + 1 | |
pathlib.Path(outputPath).mkdir(parents=True, exist_ok=True) | |
commandline=[self.conf["binary"], | |
"--export", os.path.join(outputPath,"file."), | |
"--export-format", format, | |
"--export-start", str(startFrame), | |
"--export-end", str(endFrame), | |
filename] | |
subprocess.check_call(commandline) | |
updateCompletion(1.0) |