mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
preparation scripts added from past projects
This commit is contained in:
parent
c5c6927e61
commit
3a7ce1e1b2
2 changed files with 260 additions and 0 deletions
153
pype/plugins/global/_publish_unused/transcode.py
Normal file
153
pype/plugins/global/_publish_unused/transcode.py
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
import os
|
||||
import subprocess
|
||||
|
||||
import pyblish.api
|
||||
import filelink
|
||||
|
||||
|
||||
class ExtractTranscode(pyblish.api.InstancePlugin):
|
||||
"""Extracts review movie from image sequence.
|
||||
|
||||
Offset to get images to transcode from.
|
||||
"""
|
||||
|
||||
order = pyblish.api.ExtractorOrder + 0.1
|
||||
label = "Transcode"
|
||||
optional = True
|
||||
families = ["review"]
|
||||
|
||||
def find_previous_index(self, index, indexes):
|
||||
"""Finds the closest previous value in a list from a value."""
|
||||
|
||||
data = []
|
||||
for i in indexes:
|
||||
if i >= index:
|
||||
continue
|
||||
data.append(index - i)
|
||||
|
||||
return indexes[data.index(min(data))]
|
||||
|
||||
def process(self, instance):
|
||||
|
||||
if "collection" in instance.data.keys():
|
||||
self.process_image(instance)
|
||||
|
||||
if "output_path" in instance.data.keys():
|
||||
self.process_movie(instance)
|
||||
|
||||
def process_image(self, instance):
|
||||
|
||||
collection = instance.data.get("collection", [])
|
||||
|
||||
if not list(collection):
|
||||
msg = "Skipping \"{0}\" because no frames was found."
|
||||
self.log.warning(msg.format(instance.data["name"]))
|
||||
return
|
||||
|
||||
# Temporary fill the missing frames.
|
||||
missing = collection.holes()
|
||||
if not collection.is_contiguous():
|
||||
pattern = collection.format("{head}{padding}{tail}")
|
||||
for index in missing.indexes:
|
||||
dst = pattern % index
|
||||
src_index = self.find_previous_index(
|
||||
index, list(collection.indexes)
|
||||
)
|
||||
src = pattern % src_index
|
||||
|
||||
filelink.create(src, dst)
|
||||
|
||||
# Generate args.
|
||||
# Has to be yuv420p for compatibility with older players and smooth
|
||||
# playback. This does come with a sacrifice of more visible banding
|
||||
# issues.
|
||||
# -crf 18 is visually lossless.
|
||||
args = [
|
||||
"ffmpeg", "-y",
|
||||
"-start_number", str(min(collection.indexes)),
|
||||
"-framerate", str(instance.context.data["framerate"]),
|
||||
"-i", collection.format("{head}{padding}{tail}"),
|
||||
"-pix_fmt", "yuv420p",
|
||||
"-crf", "18",
|
||||
"-timecode", "00:00:00:01",
|
||||
"-vframes",
|
||||
str(max(collection.indexes) - min(collection.indexes) + 1),
|
||||
"-vf",
|
||||
"scale=trunc(iw/2)*2:trunc(ih/2)*2",
|
||||
]
|
||||
|
||||
if instance.data.get("baked_colorspace_movie"):
|
||||
args = [
|
||||
"ffmpeg", "-y",
|
||||
"-i", instance.data["baked_colorspace_movie"],
|
||||
"-pix_fmt", "yuv420p",
|
||||
"-crf", "18",
|
||||
"-timecode", "00:00:00:01",
|
||||
]
|
||||
|
||||
args.append(collection.format("{head}.mov"))
|
||||
|
||||
self.log.debug("Executing args: {0}".format(args))
|
||||
|
||||
# Can't use subprocess.check_output, cause Houdini doesn't like that.
|
||||
p = subprocess.Popen(
|
||||
args,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
stdin=subprocess.PIPE,
|
||||
cwd=os.path.dirname(args[-1])
|
||||
)
|
||||
|
||||
output = p.communicate()[0]
|
||||
|
||||
# Remove temporary frame fillers
|
||||
for f in missing:
|
||||
os.remove(f)
|
||||
|
||||
if p.returncode != 0:
|
||||
raise ValueError(output)
|
||||
|
||||
self.log.debug(output)
|
||||
|
||||
def process_movie(self, instance):
|
||||
# Generate args.
|
||||
# Has to be yuv420p for compatibility with older players and smooth
|
||||
# playback. This does come with a sacrifice of more visible banding
|
||||
# issues.
|
||||
args = [
|
||||
"ffmpeg", "-y",
|
||||
"-i", instance.data["output_path"],
|
||||
"-pix_fmt", "yuv420p",
|
||||
"-crf", "18",
|
||||
"-timecode", "00:00:00:01",
|
||||
]
|
||||
|
||||
if instance.data.get("baked_colorspace_movie"):
|
||||
args = [
|
||||
"ffmpeg", "-y",
|
||||
"-i", instance.data["baked_colorspace_movie"],
|
||||
"-pix_fmt", "yuv420p",
|
||||
"-crf", "18",
|
||||
"-timecode", "00:00:00:01",
|
||||
]
|
||||
|
||||
split = os.path.splitext(instance.data["output_path"])
|
||||
args.append(split[0] + "_review.mov")
|
||||
|
||||
self.log.debug("Executing args: {0}".format(args))
|
||||
|
||||
# Can't use subprocess.check_output, cause Houdini doesn't like that.
|
||||
p = subprocess.Popen(
|
||||
args,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
stdin=subprocess.PIPE,
|
||||
cwd=os.path.dirname(args[-1])
|
||||
)
|
||||
|
||||
output = p.communicate()[0]
|
||||
|
||||
if p.returncode != 0:
|
||||
raise ValueError(output)
|
||||
|
||||
self.log.debug(output)
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
import os
|
||||
import tempfile
|
||||
import shutil
|
||||
|
||||
import nuke
|
||||
|
||||
import pyblish.api
|
||||
|
||||
|
||||
class ExtractNukeBakedColorspace(pyblish.api.InstancePlugin):
|
||||
"""Extracts movie with baked in luts
|
||||
|
||||
V:\Remote Apps\ffmpeg\bin>ffmpeg -y -i
|
||||
V:/FUGA/VFX_OUT/VFX_070010/v02/VFX_070010_comp_v02._baked.mov
|
||||
-pix_fmt yuv420p
|
||||
-crf 18
|
||||
-timecode 00:00:00:01
|
||||
V:/FUGA/VFX_OUT/VFX_070010/v02/VFX_070010_comp_v02..mov
|
||||
|
||||
"""
|
||||
|
||||
order = pyblish.api.ExtractorOrder
|
||||
label = "Baked Colorspace"
|
||||
optional = True
|
||||
families = ["review"]
|
||||
hosts = ["nuke"]
|
||||
|
||||
def process(self, instance):
|
||||
|
||||
if "collection" not in instance.data.keys():
|
||||
return
|
||||
|
||||
# Store selection
|
||||
selection = [i for i in nuke.allNodes() if i["selected"].getValue()]
|
||||
|
||||
# Deselect all nodes to prevent external connections
|
||||
[i["selected"].setValue(False) for i in nuke.allNodes()]
|
||||
|
||||
temporary_nodes = []
|
||||
|
||||
# Create nodes
|
||||
first_frame = min(instance.data["collection"].indexes)
|
||||
last_frame = max(instance.data["collection"].indexes)
|
||||
|
||||
temp_dir = tempfile.mkdtemp()
|
||||
for f in instance.data["collection"]:
|
||||
shutil.copy(f, os.path.join(temp_dir, os.path.basename(f)))
|
||||
|
||||
node = previous_node = nuke.createNode("Read")
|
||||
node["file"].setValue(
|
||||
os.path.join(temp_dir,
|
||||
os.path.basename(instance.data["collection"].format(
|
||||
"{head}{padding}{tail}"))).replace("\\", "/"))
|
||||
|
||||
node["first"].setValue(first_frame)
|
||||
node["origfirst"].setValue(first_frame)
|
||||
node["last"].setValue(last_frame)
|
||||
node["origlast"].setValue(last_frame)
|
||||
temporary_nodes.append(node)
|
||||
|
||||
reformat_node = nuke.createNode("Reformat")
|
||||
reformat_node["format"].setValue("HD_1080")
|
||||
reformat_node["resize"].setValue("fit")
|
||||
reformat_node["filter"].setValue("Lanczos6")
|
||||
reformat_node["black_outside"].setValue(True)
|
||||
reformat_node.setInput(0, previous_node)
|
||||
previous_node = reformat_node
|
||||
temporary_nodes.append(reformat_node)
|
||||
|
||||
viewer_process_node = nuke.ViewerProcess.node()
|
||||
dag_node = None
|
||||
if viewer_process_node:
|
||||
dag_node = nuke.createNode(viewer_process_node.Class())
|
||||
dag_node.setInput(0, previous_node)
|
||||
previous_node = dag_node
|
||||
temporary_nodes.append(dag_node)
|
||||
# Copy viewer process values
|
||||
excludedKnobs = ["name", "xpos", "ypos"]
|
||||
for item in viewer_process_node.knobs().keys():
|
||||
if item not in excludedKnobs and item in dag_node.knobs():
|
||||
x1 = viewer_process_node[item]
|
||||
x2 = dag_node[item]
|
||||
x2.fromScript(x1.toScript(False))
|
||||
else:
|
||||
self.log.warning("No viewer node found.")
|
||||
|
||||
write_node = nuke.createNode("Write")
|
||||
path = instance.data["collection"].format("{head}_baked.mov")
|
||||
instance.data["baked_colorspace_movie"] = path
|
||||
write_node["file"].setValue(path.replace("\\", "/"))
|
||||
write_node["file_type"].setValue("mov")
|
||||
write_node["raw"].setValue(1)
|
||||
write_node.setInput(0, previous_node)
|
||||
temporary_nodes.append(write_node)
|
||||
|
||||
# Render frames
|
||||
nuke.execute(write_node.name(), int(first_frame), int(last_frame))
|
||||
|
||||
# Clean up
|
||||
for node in temporary_nodes:
|
||||
nuke.delete(node)
|
||||
|
||||
shutil.rmtree(temp_dir)
|
||||
|
||||
# Restore selection
|
||||
[i["selected"].setValue(False) for i in nuke.allNodes()]
|
||||
[i["selected"].setValue(True) for i in selection]
|
||||
Loading…
Add table
Add a link
Reference in a new issue