from __future__ import with_statement from __future__ import print_function from __future__ import division import os, sys import subprocess, shlex import argparse import tempfile import numpy as np import nuke import tifffile class ffmpeg_render(KellerNukePlugin): def configurePlugin(self): workgroup = os.getenv('NUKE_PATH') nk = os.path.join(workgroup, "pythonpluginsUI/nukeffmpeg", "Preview_QT.nk") nk = nk.replace('\\','/') nk = "\"" + nk + "\"" menubar = nuke.menu("Nuke") self.m = menubar.addMenu("&Render") self.m.addCommand('FFmpeg Render', 'nuke.nodePaste({nk})'.format(nk=nk),shortcut='F6') def unconfigurePlugin(self): self.m.removeItem("FFmpeg Render") from sys import platform as __platform if __platform == "linux" or __platform == "linux2": _platform = 'linux' elif __platform == "darwin": _platform = 'osx' elif __platform == "win32": _platform = 'win' def frames_to_tc(total_frames, frame_rate): fps_int = int(round(frame_rate)) smpte_token = ":" hours = int(total_frames / (3600 * fps_int)) minutes = int(total_frames / (60 * fps_int) % 60) seconds = int(total_frames / fps_int % 60) frames = int(total_frames % fps_int) return "%02d:%02d:%02d%s%02d" % (hours, minutes, seconds, smpte_token, frames) def terminal_render(): parser = argparse.ArgumentParser(description='Render from Nuke to ffmpeg.') parser.add_argument("nuke_script", help="Nuke script to render.") parser.add_argument("-X", "--write", help="Name of the WriteFFMPEG node to render.") parser.add_argument("-F", "--framerange", help="framerange to render. Please specify -.", required=False) parser.add_argument("-o", "--output", help="Output qt to render to. Will use the value of the file knob on the WriteFFMPEG node if not specified.", required=False) args = parser.parse_args() nuke_script = args.nuke_script nuke.scriptOpen(nuke_script) node = nuke.toNode(args.write) node.begin() write = nuke.toNode('write_tmp') if args.framerange and "-" in args.framerange: fr = nuke.FrameRange() fr.setLast(int(args.framerange.split('-')[-1])) fr.setFirst(int(args.framerange.split('-')[0])) else: node_framerange = node['framerange'].getValue() if node_framerange and "-" in node_framerange: fr = nuke.FrameRange() fr.setLast(int(node_framerange.split('-')[-1])) fr.setFirst(int(node_framerange.split('-')[0])) else: fr = node.frameRange() tmpimg = tempfile.mkstemp('.tiff', "ffmpeg_temp_")[1] if _platform == 'win': write['file'].setValue(tmpimg.replace("\\","/")) else: write['file'].setValue(tmpimg) framerate = node['framerate'].getValue() output = node['file'].getValue() # create folder if necessary dir = os.path.dirname(output) osdir = nuke.callbacks.filenameFilter(dir) try: os.makedirs(osdir) except OSError: pass tc = frames_to_tc(fr.first(), framerate) ffmpeg_args = "ffmpeg -hide_banner -loglevel info -y \ -f rawvideo -pixel_format rgb48le -video_size {0}x{1} \ -framerate {2} -i pipe:0 -timecode {3} {4} {5}".format( node.width(), node.height(), framerate, tc, node['ffmpeg_args'].getValue(), output) print(ffmpeg_args) ffproc = subprocess.Popen( shlex.split(ffmpeg_args), stdin=subprocess.PIPE, stdout=subprocess.PIPE ) for i, f in enumerate(fr): nuke.execute(write, f, f) print("Rendering frame \t{0} of {1}".format(i, fr.frames())) # tifffile usage img = tifffile.imread(tmpimg) # numpy usage img.tofile(ffproc.stdin) if _platform == 'win': try: os.remove(tmpimg.replace("\\","/")) except: pass else: try: os.remove(tmpimg) except: pass result, error = ffproc.communicate() print("Rendering done.") if __name__=="__main__": terminal_render() def prep(): nuke.scriptSave() node = nuke.thisNode() ffpy = __file__ ffpy = ffpy.replace('pyc', 'py') node_framerange = node['framerange'].getValue() nk_cmd = "{0} -t {1} {2} --write {3} --output {4}".format( "\"" + nuke.EXE_PATH + "\"", ffpy, nuke.root().knob("name").value(), node.fullName(), node['file'].getValue()) print("RENDER COMMAND:\n\t{0}".format(nk_cmd)) if _platform == "win": print (os.system(nk_cmd)) return if _platform == "osx": cmd = '''osascript 2>/dev/null <