mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-25 05:14:40 +01:00
Add OTIO export action
This commit is contained in:
parent
6aa2b73bbb
commit
bf848cddfd
2 changed files with 216 additions and 0 deletions
|
|
@ -281,3 +281,32 @@ def get_media_range_with_retimes(otio_clip, handle_start, handle_end):
|
|||
returning_dict.update(version_data)
|
||||
|
||||
return returning_dict
|
||||
|
||||
|
||||
def create_clip(path, name, frames, framerate):
|
||||
range = otio.opentime.TimeRange(
|
||||
start_time=otio.opentime.RationalTime(0, framerate),
|
||||
duration=otio.opentime.RationalTime(frames, framerate)
|
||||
)
|
||||
|
||||
media_reference = otio.schema.ExternalReference(
|
||||
available_range=range,
|
||||
target_url=f"file://{path}"
|
||||
)
|
||||
|
||||
return otio.schema.Clip(
|
||||
name=name,
|
||||
media_reference=media_reference,
|
||||
source_range=range
|
||||
)
|
||||
|
||||
|
||||
def export_otio(clips_data, output_path):
|
||||
clips = []
|
||||
for name, data in clips_data.items():
|
||||
clips.append(
|
||||
create_clip(data["path"], name, data["frames"], data["framerate"])
|
||||
)
|
||||
|
||||
timeline = otio.schema.timeline_from_clips(clips)
|
||||
otio.adapters.write_to_file(timeline, output_path)
|
||||
|
|
|
|||
187
client/ayon_core/plugins/load/export_otio.py
Normal file
187
client/ayon_core/plugins/load/export_otio.py
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
from collections import defaultdict
|
||||
|
||||
from qtpy import QtWidgets, QtCore, QtGui
|
||||
|
||||
from ayon_core.client import (
|
||||
get_representations,
|
||||
get_version_by_id
|
||||
)
|
||||
from ayon_core.pipeline import load, Anatomy
|
||||
from ayon_core import resources, style
|
||||
from ayon_core.pipeline.editorial import export_otio
|
||||
from ayon_core.pipeline.load import get_representation_path_with_anatomy
|
||||
from ayon_core.lib import run_subprocess
|
||||
|
||||
|
||||
class ExportOTIO(load.SubsetLoaderPlugin):
|
||||
"""Export selected versions to OpenTimelineIO."""
|
||||
|
||||
is_multiple_contexts_compatible = True
|
||||
sequence_splitter = "__sequence_splitter__"
|
||||
|
||||
representations = ["*"]
|
||||
families = ["*"]
|
||||
tool_names = ["library_loader"]
|
||||
|
||||
label = "Export OTIO"
|
||||
order = 35
|
||||
icon = "save"
|
||||
color = "#d8d8d8"
|
||||
|
||||
def load(self, contexts, name=None, namespace=None, options=None):
|
||||
try:
|
||||
dialog = ExportOTIOOptionsDialog(contexts, self.log)
|
||||
dialog.exec_()
|
||||
except Exception:
|
||||
self.log.error("Failed to export OTIO.", exc_info=True)
|
||||
|
||||
|
||||
class ExportOTIOOptionsDialog(QtWidgets.QDialog):
|
||||
"""Dialog to select template where to deliver selected representations."""
|
||||
|
||||
def __init__(self, contexts, log=None, parent=None):
|
||||
super(ExportOTIOOptionsDialog, self).__init__(parent=parent)
|
||||
|
||||
self.setWindowTitle("AYON - Export OTIO")
|
||||
icon = QtGui.QIcon(resources.get_ayon_icon_filepath())
|
||||
self.setWindowIcon(icon)
|
||||
|
||||
self.setWindowFlags(
|
||||
QtCore.Qt.WindowStaysOnTopHint
|
||||
| QtCore.Qt.WindowCloseButtonHint
|
||||
| QtCore.Qt.WindowMinimizeButtonHint
|
||||
)
|
||||
|
||||
self.setStyleSheet(style.load_stylesheet())
|
||||
|
||||
input_widget = QtWidgets.QWidget(self)
|
||||
input_layout = QtWidgets.QGridLayout(input_widget)
|
||||
|
||||
self._project_name = contexts[0]["project"]["name"]
|
||||
|
||||
representations_by_version_id = defaultdict(list)
|
||||
self._version_by_representation_id = {}
|
||||
all_representation_names = set()
|
||||
self._version_path_by_id = {}
|
||||
for context in contexts:
|
||||
version_id = context["version"]["_id"]
|
||||
version = get_version_by_id(self._project_name, version_id)
|
||||
representations = list(get_representations(
|
||||
self._project_name, version_ids=[version_id]
|
||||
))
|
||||
representations_by_version_id[version_id] = representations
|
||||
|
||||
for representation in representations:
|
||||
all_representation_names.add(representation["name"])
|
||||
id = representation["_id"]
|
||||
self._version_by_representation_id[id] = version
|
||||
|
||||
self._version_path_by_id[version_id] = "{}/{}/{}/v{:03d}".format(
|
||||
representations[0]["context"]["hierarchy"],
|
||||
representations[0]["context"]["asset"],
|
||||
representations[0]["context"]["subset"],
|
||||
representations[0]["context"]["version"]
|
||||
)
|
||||
|
||||
all_representation_names = sorted(all_representation_names)
|
||||
|
||||
input_layout.addWidget(QtWidgets.QLabel("Representations:"), 0, 0)
|
||||
toggle_all_checkboxes = {}
|
||||
for count, name in enumerate(all_representation_names):
|
||||
checkbox = QtWidgets.QCheckBox(name)
|
||||
input_layout.addWidget(
|
||||
checkbox,
|
||||
0,
|
||||
count + 1,
|
||||
alignment=QtCore.Qt.AlignCenter
|
||||
)
|
||||
toggle_all_checkboxes[name] = checkbox
|
||||
checkbox.stateChanged.connect(self.toggle_all)
|
||||
|
||||
self._representation_checkboxes = defaultdict(list)
|
||||
row = 1
|
||||
items = representations_by_version_id.items()
|
||||
for version_id, representations in items:
|
||||
version_path = self._version_path_by_id[version_id]
|
||||
input_layout.addWidget(QtWidgets.QLabel(version_path), row, 0)
|
||||
|
||||
representations_by_name = {x["name"]: x for x in representations}
|
||||
for count, name in enumerate(all_representation_names):
|
||||
checkbox = QtWidgets.QCheckBox()
|
||||
checkbox.setChecked(False)
|
||||
if name in representations_by_name.keys():
|
||||
self._representation_checkboxes[name].append(
|
||||
{
|
||||
"checkbox": checkbox,
|
||||
"representation": representations_by_name[name]
|
||||
}
|
||||
)
|
||||
else:
|
||||
checkbox.setEnabled(False)
|
||||
|
||||
input_layout.addWidget(
|
||||
checkbox, row, count + 1, alignment=QtCore.Qt.AlignCenter
|
||||
)
|
||||
|
||||
row += 1
|
||||
|
||||
export_widget = QtWidgets.QWidget()
|
||||
export_layout = QtWidgets.QVBoxLayout(export_widget)
|
||||
|
||||
widget = QtWidgets.QWidget()
|
||||
layout = QtWidgets.QHBoxLayout(widget)
|
||||
layout.addWidget(QtWidgets.QLabel("Output Path:"))
|
||||
self.lineedit_output_path = QtWidgets.QLineEdit()
|
||||
layout.addWidget(self.lineedit_output_path)
|
||||
export_layout.addWidget(widget)
|
||||
|
||||
self.checkbox_inspect_otio_view = QtWidgets.QCheckBox(
|
||||
"Inspect with OTIO view"
|
||||
)
|
||||
export_layout.addWidget(self.checkbox_inspect_otio_view)
|
||||
|
||||
self.btn_export = QtWidgets.QPushButton("Export")
|
||||
export_layout.addWidget(self.btn_export)
|
||||
|
||||
layout = QtWidgets.QVBoxLayout(self)
|
||||
layout.addWidget(input_widget)
|
||||
layout.addWidget(export_widget)
|
||||
|
||||
self.btn_export.clicked.connect(self.export)
|
||||
|
||||
def toggle_all(self, state):
|
||||
representation_name = self.sender().text()
|
||||
state = self.sender().checkState()
|
||||
for item in self._representation_checkboxes[representation_name]:
|
||||
item["checkbox"].setCheckState(state)
|
||||
|
||||
def export(self):
|
||||
representations = []
|
||||
for name, items in self._representation_checkboxes.items():
|
||||
for item in items:
|
||||
check_state = item["checkbox"].checkState()
|
||||
if check_state == QtCore.Qt.CheckState.Checked:
|
||||
representations.append(item["representation"])
|
||||
|
||||
anatomy = Anatomy(self._project_name)
|
||||
clips_data = {}
|
||||
for representation in representations:
|
||||
version = self._version_by_representation_id[representation["_id"]]
|
||||
name = self._version_path_by_id[version["_id"]]
|
||||
clips_data[name] = {
|
||||
"path": get_representation_path_with_anatomy(
|
||||
representation, anatomy
|
||||
),
|
||||
"frames": (
|
||||
version["data"]["frameEnd"] -
|
||||
version["data"]["frameStart"]
|
||||
),
|
||||
"framerate": version["data"]["fps"]
|
||||
}
|
||||
|
||||
output_path = self.lineedit_output_path.text()
|
||||
export_otio(clips_data, output_path)
|
||||
|
||||
check_state = self.checkbox_inspect_otio_view.checkState()
|
||||
if check_state == QtCore.Qt.CheckState.Checked:
|
||||
run_subprocess(["otioview", output_path])
|
||||
Loading…
Add table
Add a link
Reference in a new issue