Skip to content

lasagnastack.stages.reel_pipeline.render

lasagnastack.stages.reel_pipeline.render

RenderStage

RenderStage(adapter: VideoEditorAdapter | None = None)

Bases: Stage

Stage 5: translate the approved cut list into a video editor draft.

Initialise with an optional video editor adapter.

Parameters:

Name Type Description Default
adapter VideoEditorAdapter | None

Adapter used to build and export the draft. Defaults to PyCapCutAdapter when None.

None
Source code in src/lasagnastack/stages/reel_pipeline/render.py
def __init__(self, adapter: VideoEditorAdapter | None = None) -> None:
    """Initialise with an optional video editor adapter.

    Args:
        adapter: Adapter used to build and export the draft. Defaults to
            ``PyCapCutAdapter`` when ``None``.
    """
    self._adapter = adapter

completion_message

completion_message(state: PipelineState) -> str

Return the post-stage confirmation message.

Parameters:

Name Type Description Default
state PipelineState

Current pipeline state.

required

Returns:

Type Description
str

Human-readable completion string.

Source code in src/lasagnastack/stages/reel_pipeline/render.py
def completion_message(self, state: PipelineState) -> str:
    """Return the post-stage confirmation message.

    Args:
        state: Current pipeline state.

    Returns:
        Human-readable completion string.
    """
    return "Stage 6 complete."

run

Run the render stage.

Parameters:

Name Type Description Default
state PipelineState

Current pipeline state. state.cut_list must be set.

required

Returns:

Type Description
PipelineState

Updated pipeline state with draft_path set.

Source code in src/lasagnastack/stages/reel_pipeline/render.py
def run(self, state: PipelineState) -> PipelineState:
    """Run the render stage.

    Args:
        state: Current pipeline state. ``state.cut_list`` must be set.

    Returns:
        Updated pipeline state with ``draft_path`` set.
    """
    assert isinstance(state, ReelPipelineState)
    assert state.cut_list is not None
    draft_path = run(
        state.cut_list,
        state.output_dir,
        state.input_dir,
        adapter=self._adapter,
        reel_style_sheet=state.reel_style_sheet,
    )
    return dataclasses.replace(state, draft_path=draft_path)

run

run(
    cut_list: CutList,
    output_dir: Path,
    input_dir: Path,
    adapter: VideoEditorAdapter | None = None,
    reel_style_sheet: ReelStyleSheet | None = None,
) -> Path

Translate the final cut list into a video editor draft folder.

Uses original source clips (not normalised) for full resolution. Delegates draft construction and editor-app export to adapter.

Parameters:

Name Type Description Default
cut_list CutList

Approved cut list from Stage 4.

required
output_dir Path

Pipeline root; draft created at output_dir/draft/.

required
input_dir Path

Folder containing the original source clips.

required
adapter VideoEditorAdapter | None

Video editor adapter to use. Defaults to PyCapCutAdapter.

None
reel_style_sheet ReelStyleSheet | None

Optional visual styling from Stage 5.

None

Returns:

Type Description
Path

Path to the draft folder inside the editor app (or output_dir/draft/

Path

if the editor was not found).

Source code in src/lasagnastack/stages/reel_pipeline/render.py
def run(
    cut_list: CutList,
    output_dir: Path,
    input_dir: Path,
    adapter: VideoEditorAdapter | None = None,
    reel_style_sheet: ReelStyleSheet | None = None,
) -> Path:
    """Translate the final cut list into a video editor draft folder.

    Uses original source clips (not normalised) for full resolution.
    Delegates draft construction and editor-app export to adapter.

    Args:
        cut_list: Approved cut list from Stage 4.
        output_dir: Pipeline root; draft created at output_dir/draft/.
        input_dir: Folder containing the original source clips.
        adapter: Video editor adapter to use. Defaults to PyCapCutAdapter.
        reel_style_sheet: Optional visual styling from Stage 5.

    Returns:
        Path to the draft folder inside the editor app (or output_dir/draft/
        if the editor was not found).
    """
    if adapter is None:
        adapter = PyCapCutAdapter()

    draft_parent = io.draft_dir(output_dir)
    draft_parent.mkdir(parents=True, exist_ok=True)

    title = cut_list.reel_meta.title
    timestamp = _make_timestamp()
    folder_name = _draft_folder_name(title, timestamp)
    display_name = _draft_display_name(title, timestamp)

    draft_path = adapter.build_draft(
        cut_list, draft_parent, folder_name, display_name, input_dir, reel_style_sheet
    )
    capcut_path = adapter.export(draft_path, input_dir, cut_list)
    final_path = capcut_path if capcut_path is not None else draft_path
    log.info("render_done", draft=str(final_path))
    return final_path