mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-25 21:32:15 +01:00
137 lines
4.2 KiB
Python
137 lines
4.2 KiB
Python
import os
|
|
import subprocess
|
|
import contextlib
|
|
|
|
import capture_gui
|
|
import clique
|
|
|
|
import pype.maya.lib as lib
|
|
import pype.api
|
|
import avalon.maya
|
|
|
|
from maya import cmds, mel
|
|
import pymel.core as pm
|
|
from pype.vendor import ffmpeg
|
|
reload(ffmpeg)
|
|
|
|
|
|
# TODO: move codec settings to presets
|
|
class ExtractQuicktime(pype.api.Extractor):
|
|
"""Extract Quicktime from viewport capture.
|
|
|
|
Takes review camera and creates review Quicktime video based on viewport
|
|
capture.
|
|
|
|
"""
|
|
|
|
label = "Quicktime"
|
|
hosts = ["maya"]
|
|
families = ["review"]
|
|
optional = True
|
|
|
|
def process(self, instance):
|
|
self.log.info("Extracting capture..")
|
|
|
|
# get scene fps
|
|
fps = mel.eval('currentTimeUnitToFPS()')
|
|
|
|
# if start and end frames cannot be determined, get them
|
|
# from Maya timeline
|
|
start = instance.data.get("startFrameReview")
|
|
end = instance.data.get("endFrameReview")
|
|
if start is None:
|
|
start = cmds.playbackOptions(query=True, animationStartTime=True)
|
|
if end is None:
|
|
end = cmds.playbackOptions(query=True, animationEndTime=True)
|
|
self.log.info("start: {}, end: {}".format(start, end))
|
|
handles = instance.data.get("handles", 0)
|
|
if handles:
|
|
start -= handles
|
|
end += handles
|
|
|
|
# get cameras
|
|
camera = instance.data['review_camera']
|
|
capture_preset = ""
|
|
try:
|
|
preset = lib.load_capture_preset(capture_preset)
|
|
except:
|
|
preset = {}
|
|
self.log.info('using viewport preset: {}'.format(capture_preset))
|
|
|
|
preset['camera'] = camera
|
|
preset['format'] = "image"
|
|
# preset['compression'] = "qt"
|
|
preset['quality'] = 50
|
|
preset['compression'] = "jpg"
|
|
preset['start_frame'] = start
|
|
preset['end_frame'] = end
|
|
preset['camera_options'] = {
|
|
"displayGateMask": False,
|
|
"displayResolution": False,
|
|
"displayFilmGate": False,
|
|
"displayFieldChart": False,
|
|
"displaySafeAction": False,
|
|
"displaySafeTitle": False,
|
|
"displayFilmPivot": False,
|
|
"displayFilmOrigin": False,
|
|
"overscan": 1.0,
|
|
"depthOfField": cmds.getAttr("{0}.depthOfField".format(camera)),
|
|
}
|
|
|
|
stagingdir = self.staging_dir(instance)
|
|
filename = "{0}".format(instance.name)
|
|
path = os.path.join(stagingdir, filename)
|
|
|
|
self.log.info("Outputting images to %s" % path)
|
|
|
|
preset['filename'] = path
|
|
preset['overwrite'] = True
|
|
|
|
pm.refresh(f=True)
|
|
|
|
refreshFrameInt = int(pm.playbackOptions(q=True, minTime=True))
|
|
pm.currentTime(refreshFrameInt - 1, edit=True)
|
|
pm.currentTime(refreshFrameInt, edit=True)
|
|
|
|
with maintained_time():
|
|
playblast = capture_gui.lib.capture_scene(preset)
|
|
|
|
self.log.info("file list {}".format(playblast))
|
|
# self.log.info("Calculating HUD data overlay")
|
|
|
|
collected_frames = os.listdir(stagingdir)
|
|
collections, remainder = clique.assemble(collected_frames)
|
|
input_path = os.path.join(
|
|
stagingdir, collections[0].format('{head}{padding}{tail}'))
|
|
self.log.info("input {}".format(input_path))
|
|
|
|
movieFile = filename + ".mov"
|
|
full_movie_path = os.path.join(stagingdir, movieFile)
|
|
self.log.info("output {}".format(full_movie_path))
|
|
with avalon.maya.suspended_refresh():
|
|
try:
|
|
(
|
|
ffmpeg
|
|
.input(input_path, framerate=fps, start_number=int(start))
|
|
.output(full_movie_path)
|
|
.run(overwrite_output=True,
|
|
capture_stdout=True,
|
|
capture_stderr=True)
|
|
)
|
|
except ffmpeg.Error as e:
|
|
ffmpeg_error = 'ffmpeg error: {}'.format(e.stderr)
|
|
self.log.error(ffmpeg_error)
|
|
raise RuntimeError(ffmpeg_error)
|
|
|
|
if "files" not in instance.data:
|
|
instance.data["files"] = list()
|
|
instance.data["files"].append(movieFile)
|
|
|
|
|
|
@contextlib.contextmanager
|
|
def maintained_time():
|
|
ct = cmds.currentTime(query=True)
|
|
try:
|
|
yield
|
|
finally:
|
|
cmds.currentTime(ct, edit=True)
|