O writer tinha 4.199 linhas, das quais 3.300 numa única classe com dezoito
assuntos dentro. Achar o trecho de zoom exigia rolar por marcadores,
velocidade e legendas.
Agora é o pacote fcpxml/writer/, com um arquivo por assunto e o
FCPXMLModifier montado por composição de mixins. Mixins, e não objetos
separados, porque todas essas operações mexem no mesmo documento e nos
mesmos índices — separá-las em objetos independentes transformaria toda
chamada interna em travessia de fronteira sem nada em troca. A divisão que
importa aqui é de leitura, não de estado.
Nenhuma mudança de comportamento e nenhuma alteração nos ~50 pontos que
importam do writer: o __init__ re-exporta tudo, inclusive os nomes com
underscore que a suíte já usava.
core 723 carga, índices, navegação na spine, save
titles 600 títulos e legendas dinâmicas
cut 333 dividir, cortar faixas, apagar
speed 297 velocidade e zoom
(+ 20 módulos menores)
Único ajuste de chamada: quatro testes faziam patch em
fcpxml.writer.subprocess, que agora mora em writer.document (ver
Engine/docs/05_EXPERIENCIAS.md #23).
Lint zerado, 1441 testes passando.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
50 lines
1.7 KiB
Python
50 lines
1.7 KiB
Python
"""Clipes conectados (lanes acima/abaixo da spine).
|
|
|
|
Extraído de writer.py — ver fcpxml/writer/__init__.py para o conjunto.
|
|
"""
|
|
|
|
import xml.etree.ElementTree as ET
|
|
from typing import Optional
|
|
|
|
|
|
class ConnectedMixin:
|
|
"""Clipes conectados (lanes acima/abaixo da spine)."""
|
|
|
|
# CONNECTED CLIP OPERATIONS (v0.5.0)
|
|
# ========================================================================
|
|
|
|
def add_connected_clip(
|
|
self,
|
|
parent_clip_id: str,
|
|
asset_id: Optional[str] = None,
|
|
asset_name: Optional[str] = None,
|
|
offset: str = "0s",
|
|
duration: Optional[str] = None,
|
|
lane: int = 1,
|
|
) -> ET.Element:
|
|
"""Add a connected clip (B-roll, title, audio) to an existing timeline clip.
|
|
|
|
Args:
|
|
parent_clip_id: Name/ID of the clip to attach to
|
|
asset_id: Asset reference ID
|
|
asset_name: Asset name (alternative to asset_id)
|
|
offset: Position relative to parent clip start
|
|
duration: Duration of connected clip (default: full asset)
|
|
lane: Lane number (positive=above, negative=below)
|
|
|
|
Returns:
|
|
The created connected clip element
|
|
"""
|
|
parent = self._require_clip(parent_clip_id)
|
|
asset, asset_id = self._resolve_asset(asset_id, asset_name)
|
|
clip_duration, source_start = self._resolve_clip_duration(asset, duration)
|
|
|
|
new_clip = self._make_asset_clip(
|
|
asset_id, asset.get('name', 'Untitled'),
|
|
self._parse_time(offset), source_start, clip_duration,
|
|
parent=parent, lane=str(lane),
|
|
)
|
|
return new_clip
|
|
|
|
# ========================================================================
|