Skip to content
This repository has been archived by the owner on Sep 20, 2024. It is now read-only.

Flame: extracting segments with trans-coding #2547

Merged
Merged
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
6c2204c
added ability to hide publish if plugin need it
iLLiCiTiT Jan 12, 2022
5a89d91
Merge branch 'feature/OP-1562_Flame--pre-collecting-timeline-segments…
jakubjezek001 Jan 12, 2022
3653685
flame: starting render utlis modul
jakubjezek001 Jan 13, 2022
3b8cf57
Merge remote-tracking branch 'origin/feature/publisher_can_hide_if_pl…
jakubjezek001 Jan 13, 2022
aa19d69
flame: updating render_utils modul
jakubjezek001 Jan 13, 2022
574466f
flame: adding export clip to api
jakubjezek001 Jan 13, 2022
a2d414c
flame: adding exporter plugin
jakubjezek001 Jan 13, 2022
9c20580
flame: export clip to correct frame range
jakubjezek001 Jan 13, 2022
9fa024d
flame: hide gui when processing plugin
jakubjezek001 Jan 13, 2022
4a230b7
flame: add function to get flame version and root install path
jakubjezek001 Jan 14, 2022
cc20a22
flame: add function to maintain object duplication
jakubjezek001 Jan 14, 2022
f6ab7f2
flame: adding settings for `ExtractSubsetResources` plugin
jakubjezek001 Jan 14, 2022
0e96a2e
flame: update utils modules
jakubjezek001 Jan 14, 2022
183acf4
flame: update export plugin with more dynamic preset path abstraction
jakubjezek001 Jan 14, 2022
aa39f98
flame: add bool to settings to control if range will be added to repres
jakubjezek001 Jan 14, 2022
26c3ba7
flame: add frame ranges to representation
jakubjezek001 Jan 14, 2022
ea469e2
flame: fixing extract exporter
jakubjezek001 Jan 14, 2022
25b54be
flame: adding host to some extract plugins
jakubjezek001 Jan 14, 2022
7dbb46f
flame: update settings, remove camel case
jakubjezek001 Jan 17, 2022
d10d6c6
hound: classics ;)
jakubjezek001 Jan 17, 2022
dabcf62
Merge branch 'feature/OP-1562_Flame--pre-collecting-timeline-segments…
jakubjezek001 Jan 19, 2022
b0a71a8
typo
jakubjezek001 Jan 19, 2022
247e90a
Merge branch 'feature/OP-1562_Flame--pre-collecting-timeline-segments…
jakubjezek001 Jan 19, 2022
943dfc2
flame: updating filename operations
jakubjezek001 Jan 19, 2022
fdc1d5a
global: rename otio plugins and change order
jakubjezek001 Jan 19, 2022
3afdaf6
flame: remove camel case in extract resources plugin
jakubjezek001 Jan 19, 2022
9df277f
flame: removing unused module
jakubjezek001 Jan 19, 2022
c1ac832
Merge branch 'develop' into feature/OP-1537_Flame-Submitting-jobs-to-…
jakubjezek001 Jan 20, 2022
d215123
Merge branch 'develop' into feature/OP-1537_Flame-Submitting-jobs-to-…
jakubjezek001 Jan 20, 2022
c5d4374
ftrack: adding profile for flame to have ftrack family
jakubjezek001 Jan 20, 2022
4f01991
flame: adding segment index attribute to settings
jakubjezek001 Jan 20, 2022
f4655e7
global: collect hierarchy order moved higher
jakubjezek001 Jan 20, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 25 additions & 3 deletions openpype/hosts/flame/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,17 @@
get_sequence_segments,
maintained_segment_selection,
reset_segment_selection,
get_segment_attributes
get_segment_attributes,
get_clips_in_reels,
get_reformated_path,
get_frame_from_path,
get_padding_from_path,
maintained_object_duplication
)
from .utils import (
setup
setup,
get_flame_version,
get_flame_install_root
)
from .pipeline import (
install,
Expand Down Expand Up @@ -55,6 +62,10 @@
file_extensions,
work_root
)
from .render_utils import (
export_clip,
get_preset_path_by_xml_name
)

__all__ = [
# constants
Expand All @@ -80,6 +91,11 @@
"maintained_segment_selection",
"reset_segment_selection",
"get_segment_attributes",
"get_clips_in_reels",
"get_reformated_path",
"get_frame_from_path",
"get_padding_from_path",
"maintained_object_duplication",

# pipeline
"install",
Expand All @@ -96,6 +112,8 @@

# utils
"setup",
"get_flame_version",
"get_flame_install_root",

# menu
"FlameMenuProjectConnect",
Expand All @@ -111,5 +129,9 @@
"current_file",
"has_unsaved_changes",
"file_extensions",
"work_root"
"work_root",

# render utils
"export_clip",
"get_preset_path_by_xml_name"
]
142 changes: 140 additions & 2 deletions openpype/hosts/flame/api/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,8 @@ def get_sequence_segments(sequence, selected=False):
for segment in track.segments:
if segment.name.get_value() == "":
continue
if segment.hidden.get_value() is True:
continue
if (
selected is True
and segment.selected.get_value() is not True
Expand Down Expand Up @@ -519,7 +521,7 @@ def _get_shot_tokens_values(clip, tokens):


def get_segment_attributes(segment):
if str(segment.name)[1:-1] == "":
if segment.name.get_value() == "":
return None

# Add timeline segment to tree
Expand All @@ -532,6 +534,12 @@ def get_segment_attributes(segment):
"PySegment": segment
}

# head and tail with forward compatibility
if segment.head:
clip_data["segment_head"] = int(segment.head)
if segment.tail:
clip_data["segment_tail"] = int(segment.tail)

# add all available shot tokens
shot_tokens = _get_shot_tokens_values(segment, [
"<colour space>", "<width>", "<height>", "<depth>", "<segment>",
Expand All @@ -551,11 +559,141 @@ def get_segment_attributes(segment):
attr = getattr(segment, attr_name)
segment_attrs_data[attr] = str(attr).replace("+", ":")

if attr in ["record_in", "record_out"]:
if attr_name in ["record_in", "record_out"]:
clip_data[attr_name] = attr.relative_frame
else:
clip_data[attr_name] = attr.frame

clip_data["segment_timecodes"] = segment_attrs_data

return clip_data


def get_clips_in_reels(project):
output_clips = []
project_desktop = project.current_workspace.desktop

for reel_group in project_desktop.reel_groups:
for reel in reel_group.reels:
for clip in reel.clips:
clip_data = {
"PyClip": clip,
"fps": float(str(clip.frame_rate)[:-4])
}

attrs = [
"name", "width", "height",
"ratio", "sample_rate", "bit_depth"
]

for attr in attrs:
val = getattr(clip, attr)
clip_data[attr] = val

version = clip.versions[-1]
track = version.tracks[-1]
for segment in track.segments:
segment_data = get_segment_attributes(segment)
clip_data.update(segment_data)

output_clips.append(clip_data)

return output_clips


def get_reformated_path(path, padded=True):
"""
Return fixed python expression path

Args:
path (str): path url or simple file name

Returns:
type: string with reformated path

Example:
get_reformated_path("plate.1001.exr") > plate.%04d.exr

"""
padding = get_padding_from_path(path)
found = get_frame_from_path(path)

if not found:
log.info("Path is not sequence: {}".format(path))
return path

if padded:
path = path.replace(found, "%0{}d".format(padding))
else:
path = path.replace(found, "%d")

return path


def get_padding_from_path(path):
"""
Return padding number from Flame path style

Args:
path (str): path url or simple file name

Returns:
int: padding number

Example:
get_padding_from_path("plate.0001.exr") > 4

"""
found = get_frame_from_path(path)

if found:
return len(found)
else:
return None


def get_frame_from_path(path):
"""
Return sequence number from Flame path style

Args:
path (str): path url or simple file name

Returns:
int: sequence frame number

Example:
def get_frame_from_path(path):
("plate.0001.exr") > 0001

"""
frame_pattern = re.compile(r"[._](\d+)[.]")

found = re.findall(frame_pattern, path)

if found:
return found.pop()
else:
return None


@contextlib.contextmanager
def maintained_object_duplication(item):
"""Maintain input item duplication

Attributes:
item (any flame.PyObject): python api object

Yield:
duplicate input PyObject type
"""
import flame
# Duplicate the clip to avoid modifying the original clip
duplicate = flame.duplicate(item)

try:
# do the operation on selected segments
yield duplicate
finally:
# delete the item at the end
flame.delete(duplicate)
125 changes: 125 additions & 0 deletions openpype/hosts/flame/api/render_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import os


def export_clip(export_path, clip, preset_path, **kwargs):
"""Flame exported wrapper

Args:
export_path (str): exporting directory path
clip (PyClip): flame api object
preset_path (str): full export path to xml file

Kwargs:
thumb_frame_number (int)[optional]: source frame number
in_mark (int)[optional]: cut in mark
out_mark (int)[optional]: cut out mark

Raises:
KeyError: Missing input kwarg `thumb_frame_number`
in case `thumbnail` in `export_preset`
FileExistsError: Missing export preset in shared folder
"""
import flame

in_mark = out_mark = None

# Set exporter
exporter = flame.PyExporter()
exporter.foreground = True
exporter.export_between_marks = True

if kwargs.get("thumb_frame_number"):
thumb_frame_number = kwargs["thumb_frame_number"]
# make sure it exists in kwargs
if not thumb_frame_number:
raise KeyError(
"Missing key `thumb_frame_number` in input kwargs")

in_mark = int(thumb_frame_number)
out_mark = int(thumb_frame_number) + 1

elif kwargs.get("in_mark") and kwargs.get("out_mark"):
in_mark = int(kwargs["in_mark"])
out_mark = int(kwargs["out_mark"])
else:
exporter.export_between_marks = False

try:
# set in and out marks if they are available
if in_mark and out_mark:
clip.in_mark = in_mark
clip.out_mark = out_mark

# export with exporter
exporter.export(clip, preset_path, export_path)
finally:
print('Exported: {} at {}-{}'.format(
clip.name.get_value(),
clip.in_mark,
clip.out_mark
))


def get_preset_path_by_xml_name(xml_preset_name):
def _search_path(root):
output = []
for root, _dirs, files in os.walk(root):
for f in files:
if f != xml_preset_name:
continue
file_path = os.path.join(root, f)
output.append(file_path)
return output

def _validate_results(results):
if results and len(results) == 1:
return results.pop()
elif results and len(results) > 1:
print((
"More matching presets for `{}`: /n"
"{}").format(xml_preset_name, results))
return results.pop()
else:
return None

from .utils import (
get_flame_install_root,
get_flame_version
)

# get actual flame version and install path
_version = get_flame_version()["full"]
_install_root = get_flame_install_root()

# search path templates
shared_search_root = "{install_root}/shared/export/presets"
install_search_root = (
"{install_root}/presets/{version}/export/presets/flame")

# fill templates
shared_search_root = shared_search_root.format(
install_root=_install_root
)
install_search_root = install_search_root.format(
install_root=_install_root,
version=_version
)

# get search results
shared_results = _search_path(shared_search_root)
installed_results = _search_path(install_search_root)

# first try to return shared results
shared_preset_path = _validate_results(shared_results)

if shared_preset_path:
return os.path.dirname(shared_preset_path)

# then try installed results
installed_preset_path = _validate_results(installed_results)

if installed_preset_path:
return os.path.dirname(installed_preset_path)

# if nothing found then return None
jakubjezek001 marked this conversation as resolved.
Show resolved Hide resolved
return False
15 changes: 15 additions & 0 deletions openpype/hosts/flame/api/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,18 @@ def setup(env=None):
_sync_utility_scripts(env)

log.info("Flame OpenPype wrapper has been installed")


def get_flame_version():
import flame

return {
"full": flame.get_version(),
"major": flame.get_version_major(),
"minor": flame.get_version_minor(),
"patch": flame.get_version_patch()
}


def get_flame_install_root():
return "/opt/Autodesk"
2 changes: 1 addition & 1 deletion openpype/hosts/flame/otio/flame_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ def create_otio_reference(clip_data):
if is_sequence:
metadata.update({
"isSequence": True,
"padding": padding
"padding": len(padding)
})

otio_ex_ref_item = None
Expand Down
Loading