vse_toolbox/operators/exports.py

286 lines
10 KiB
Python

import time
import re
from pathlib import Path
import os
import bpy
from bpy.types import Operator
from bpy.props import BoolProperty
from vse_toolbox.sequencer_utils import (get_strips, render_strip, render_sound,
render_scene, get_render_attributes)
from vse_toolbox.bl_utils import (get_scene_settings, background_render)
from vse_toolbox.file_utils import install_module, expand
class VSETB_OT_render(Operator):
bl_idname = "vse_toolbox.strips_render"
bl_label = "Render Shots Strips"
bl_description = "Render Shots Strips"
bl_options = {"REGISTER", "UNDO"}
#selected_only : BoolProperty(name="Selected Only", default=False)
@classmethod
def poll(cls, context):
settings = get_scene_settings()
return settings.active_project
def invoke(self, context, event):
scn = context.scene
settings = get_scene_settings()
return context.window_manager.invoke_props_dialog(self, width=500)
def draw_export_row(self, layout, text, data, enable_prop, template_prop):
row = layout.split(factor=0.1)
heading = row.row(align=True)
heading.alignment = 'RIGHT'
heading.label(text=text)
heading.prop(data, enable_prop, text='')
row = row.row(align=True)
row.enabled = getattr(data, enable_prop)
row.prop(data, template_prop, text='')
def draw(self, context):
scn = context.scene
settings = get_scene_settings()
layout = self.layout
#layout.use_property_split = True
#layout.use_property_decorate = False
box = layout.box()
col = box.column()
row = col.row(align=True)
row.prop(settings.active_project, "render_single_file", text='')
row.label(icon='FILE_MOVIE')
row.label(text='Single File')
if settings.active_project.render_single_file:
self.draw_export_row(col ,'Video', settings.active_project,
'render_video',
'render_video_template'
)
self.draw_export_row(col, 'Audio', settings.active_project,
'render_audio',
'render_audio_template'
)
#layout.separator()
box = layout.box()
col = box.column()
row = col.row(align=True)
row.prop(settings.active_project, "render_sequence", text='')
row.label(icon='SEQUENCE')
row.label(text='One file per sequence')
if settings.active_project.render_sequence:
self.draw_export_row(col ,'Video', settings.active_project,
'render_video_per_sequence',
'render_video_sequence_template'
)
self.draw_export_row(col, 'Audio', settings.active_project,
'render_audio_per_sequence',
'render_audio_sequence_template'
)
#col.prop(settings, 'channel', text='Channel')
#col.prop(self, 'selected_only')
#layout.separator()
box = layout.box()
col = box.column()
row = col.row(align=True)
row.prop(settings.active_project, "render_shot", text='')
row.label(icon='SEQ_SEQUENCER')
row.label(text='One file per shot')
if settings.active_project.render_shot:
self.draw_export_row(col ,'Video', settings.active_project,
'render_video_per_strip',
'render_video_strip_template'
)
self.draw_export_row(col, 'Audio', settings.active_project,
'render_audio_per_strip',
'render_audio_strip_template'
)
row = layout.row()
row.prop(settings.active_project, "render_selected_only", text='Selected Only')
#col.prop(settings, 'channel', text='Channel')
#col.prop(self, 'selected_only')
def execute(self, context):
scn = context.scene
settings = get_scene_settings()
project = settings.active_project
project_templates = {t.name: t.value for t in project.templates}
format_data = {**settings.format_data, **project.format_data}
single_file = False
sequence_strips = []
shot_strips = []
render_attrs = get_render_attributes()
start_time = time.perf_counter()
if project.render_single_file:
single_file = True
if project.render_video:
video_template = expand(project.render_video_template, **project_templates)
video_path = video_template.format(**format_data)
render_scene(video_path, attributes=render_attrs)
#background_render(output=video_path)
if project.render_audio:
audio_template = expand(project.render_audio_template, **project_templates)
audio_path = audio_template.format(**format_data)
bpy.ops.sound.mixdown(filepath=audio_path)
if project.render_sequence:
print('Render Sequences...')
sequence_strips = get_strips(channel='Sequences', selected_only=project.render_selected_only)
for strip in sequence_strips:
#print(strip.name)
strip_settings = strip.vsetb_strip_settings
strip_data = {**format_data, **strip_settings.format_data}
if project.render_sequence and project.render_video_per_sequence:
video_sequence_template = expand(project.render_video_sequence_template, **project_templates)
sequence_render_path = video_sequence_template.format(**strip_data)
render_strip(strip, sequence_render_path, attributes=render_attrs)
if project.render_shot and project.render_audio_per_sequence:
audio_sequence_template = expand(project.render_audio_sequence_template, **project_templates)
audio_render_path = audio_sequence_template.format(**strip_data)
render_sound(strip, audio_render_path)
if project.render_shot:
shot_strips = get_strips(channel='Shots', selected_only=project.render_selected_only)
for strip in shot_strips:
strip_settings = strip.vsetb_strip_settings
strip_data = {**format_data, **strip_settings.format_data}
if project.render_video_per_strip:
video_strip_template = expand(project.render_video_strip_template, **project_templates)
strip_render_path = video_strip_template.format(**strip_data)
render_strip(strip, strip_render_path, attributes=render_attrs)
if project.render_audio_per_strip:
audio_strip_template = expand(project.render_audio_strip_template, **project_templates)
audio_render_path = audio_strip_template.format(**strip_data)
render_sound(strip, audio_render_path)
if not single_file and not sequence_strips and not shot_strips:
self.report({"ERROR"}, f'No strips rendered, select sequence or shot strips')
return {"CANCELLED"}
self.report({"INFO"}, f'Strips rendered in {time.perf_counter()-start_time} seconds')
return {"FINISHED"}
class VSETB_OT_export_edl(Operator):
bl_idname = "vse_toolbox.export_edl"
bl_label = "Export Edl"
bl_description = "Export Edl"
bl_options = {"REGISTER", "UNDO"}
#selected_only : BoolProperty(name="Selected Only", default=False)
@classmethod
def poll(cls, context):
settings = get_scene_settings()
return settings.active_project
def invoke(self, context, event):
scn = context.scene
settings = get_scene_settings()
return context.window_manager.invoke_props_dialog(self)
def draw(self, context):
scn = context.scene
settings = get_scene_settings()
layout = self.layout
col = layout.column()
col.use_property_split = True
col.use_property_decorate = False
#col.prop(settings, 'channel', text='Channel')
#col.prop(self, 'selected_only')
col.prop(settings.active_project, "export_edl_template")
def execute(self, context):
opentimelineio = install_module('opentimelineio')
from opentimelineio.schema import (Clip, Timeline, Track, ExternalReference)
from opentimelineio.opentime import (RationalTime, TimeRange)
start_time = time.perf_counter()
scn = context.scene
settings = get_scene_settings()
fps = scn.render.fps
project = settings.active_project
format_data = {**settings.format_data, **project.format_data}
output_edl = project.export_edl_template.format(**format_data)
output_edl = os.path.abspath(bpy.path.abspath(output_edl))
output_edl = Path(output_edl)
timeline = Timeline(output_edl.stem)
track = Track(f"Track 1")
track.kind = "Video"
timeline.tracks.append(track)
for strip in get_strips(channel='Shots', selected_only=False):
strip_data = {**format_data, **strip.vsetb_strip_settings.format_data}
strip_render_path = project.render_video_strip_template.format(**strip_data)
clip = Clip(Path(strip_render_path).name)
clip.metadata.setdefault("cmx_3600", {})
clip.metadata['cmx_3600']['reel'] = strip.name
#clip.metadata['cmx_3600']['flags'] = 'IS_CLIP'
#clip.media_reference = ExternalReference(f'//render/{strip.name}.mov')
#clip.media_reference.name = strip.name
#clip.available_range = TimeRange(RationalTime(0, fps), RationalTime(strip.frame_duration, fps))
clip.source_range = TimeRange(RationalTime(strip.frame_offset_start, fps), RationalTime(strip.frame_final_duration, fps))
track.append(clip)
output_edl.parent.mkdir(exist_ok=True, parents=True)
edl = opentimelineio.adapters.write_to_string(timeline, 'cmx_3600')
output_edl.write_text(edl)
#opentimelineio.adapters.write_to_file(timeline, str(output_edl), 'cmx_3600')
self.report({"INFO"}, f'Edl Exported in {time.perf_counter()-start_time} seconds')
return {"FINISHED"}
classes = (
VSETB_OT_render,
VSETB_OT_export_edl
)
def register():
for cls in classes:
bpy.utils.register_class(cls)
def unregister():
for cls in reversed(classes):
bpy.utils.unregister_class(cls)