Skip to content

Instantly share code, notes, and snippets.

@ZoomTen
Last active April 9, 2020 14:32
Show Gist options
  • Save ZoomTen/0005986d7e41d35bfd8ffbb95d7e3c41 to your computer and use it in GitHub Desktop.
Save ZoomTen/0005986d7e41d35bfd8ffbb95d7e3c41 to your computer and use it in GitHub Desktop.

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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment