Managing Clip Linking and Sync‑Lock Track Relationships in Palmier Pro

Palmier Pro maintains audio‑video synchronization through orthogonal mechanisms: clip linking groups related media via linkGroupId while sync‑lock tracks use the syncLocked boolean to control ripple edit participation, with both systems interacting during timeline mutations to preserve editorial invariants.

The Palmier Pro video editor manages complex timeline relationships through two distinct but complementary systems. Understanding how clip linking and sync‑lock track relationships interact is essential for maintaining synchronization across audio and video elements while controlling which tracks move during ripple edits. This guide examines the source code implementation to show exactly how these mechanisms function.

Clip Linking Mechanics

Clip linking in Palmier Pro operates at the clip level, treating associated media as a single logical unit for editing operations.

A link group is identified by a linkGroupId stored on each Clip instance. All clips sharing the same identifier are treated as a single unit for selection, movement, trimming, and deletion. In Sources/PalmierPro/Editor/ViewModel/EditorViewModel+Linking.swift, the linkIndex property builds a reverse mapping from group IDs to clip IDs in a single pass over every track, operating at O(tracks·clips) complexity (lines 17‑26).

Expanding Selections and Finding Partners

The linking system provides several utility methods for working with groups:

  • expandToLinkGroup(_:) – Expands a partial selection to include the full link group, ensuring commands affect the entire set (lines 37‑55)
  • linkedPartnerIds(of:) – Returns the other members of a clip’s group, excluding the clip itself (lines 57‑63)

Propagating Moves and Timing Changes

When you manipulate a linked clip, Palmier Pro automatically computes transformations for partners:

  • partnerMoves(forMoveOf:toFrame:) – Calculates the same frame delta for every partner clip, preserving audio/video sync when moving linked media (lines 65‑77)
  • timingPropagationPartners(of:) – Returns all clips requiring uniform duration, trim, or speed changes when any group member is edited (lines 79‑88)
  • linkGroupOffsets() – Scans both plain link groups and multicam groups to compute per‑clip offsets when members drift apart after operations like trimming (lines 91‑139)

The editor exposes explicit commands for managing groups:

// Create a new link group from selected clips
let selectedIds: Set<String> = ["clipA", "clipB"]
editor.linkClips(ids: selectedIds)  // Creates UUID, stamps clips, merges existing groups

In EditorViewModel+Linking.swift, linkClips(ids:) creates a new UUID, stamps it on every clip in the set, and merges any pre‑existing groups (lines 141‑148). Conversely, unlinkClips(ids:) expands the selection to the full group and clears linkGroupId on each member (lines 150‑157).

Trim and Slip Propagation

When committing a trim operation, the system optionally expands the edit set to linked partners via the propagateToLinked parameter. The commitTrim method calls trimClips with computed start/end frames after expanding the selection (lines 66‑86).

For slip operations, commitSlip works on slip‑eligible clips (audio/video content that is not image or text based and not part of a multicam group). It propagates the source‑frame shift only to partners that also satisfy eligibility checks through slipPropagationPartnerIds (lines 98‑118).

Track Sync‑Lock Mechanics

While linking controls relationships between clips, sync‑lock controls track behavior during ripple edits.

The syncLocked Property

Each track stores a syncLocked boolean flag (defaulting to true). When syncLocked is true, the track moves in lock‑step with ripple edits that shift nearby tracks; when false, the track remains independent. This property is defined in Sources/PalmierPro/Models/Timeline.swift and decodes with a fallback default of true for legacy projects (lines 88‑126).

The UI exposes this through a toggle button in TimelineHeaderView.swift, displaying a "link" symbol for locked tracks and "personalhotspot.slash" for unlocked tracks (lines 90‑94).

Ripple Editing Integration

During ripple insertion (rippleInsertClips in EditorViewModel+Ripple.swift), the engine first gathers the set of locked tracks using timeline.tracks.filter(\.syncLocked) (lines 65‑95). It then computes left‑room and right‑room constraints only for those tracks.

If a track is locked but does not contain clips being inserted, the edit still reserves space on that track via syncLockedLeftRoom to maintain visual and audio alignment (lines 95‑106). When deleting or shifting gaps, the ripple logic respects the syncLocked flag to ensure locked tracks move together while unlocked tracks remain stationary (lines 152‑181).

Toggle the flag programmatically using the generic helper:

// Toggle sync‑lock on track 2
editor.toggleTrackFlag(
    trackIndex: 2,
    keyPath: \.syncLocked,
    onName: "Sync Lock Track",
    offName: "Unlock Track Sync"
)

This method resides in Sources/PalmierPro/Editor/ViewModel/EditorViewModel+Tracks.swift (lines 98‑105).

Agent Tool Integration

The Agent system exposes syncLocked as a mutable property in the manage_tracks command. In ToolExecutor+Timeline.swift, the default track configuration includes "syncLocked": true (lines 129‑130). Validation logic in ToolExecutor+Clips.swift enforces that at least one of muted, hidden, or syncLocked is supplied when altering track flags (lines 1123‑1134).

How Linking and Sync‑Lock Work Together

Although linking operates at the clip level and sync‑lock at the track level, both mechanisms cooperate during ripple editing:

  1. Linked clips may span multiple tracks. When a linked clip moves, partnerMoves ensures every partner receives the same frame delta, regardless of the tracks’ syncLocked state.

  2. Sync‑locked tracks guarantee that ripples shifting one track also shift other locked tracks, preserving the temporal relationship of linked clips across tracks.

For example, dragging a linked video clip on a locked video track triggers the ripple engine to shift the locked audio track, while the linked‑clip logic applies the same frame delta to the audio clip partner.

Summary

  • Clip linking uses linkGroupId to bind related clips into logical units, with automatic propagation of moves, trims, and slips via methods in EditorViewModel+Linking.swift
  • Sync‑lock tracks use the syncLocked boolean (default true in Timeline.swift) to determine participation in ripple edits, with constraints calculated in EditorViewModel+Ripple.swift
  • Cross‑track synchronization is maintained when linked groups span multiple tracks and those tracks are sync‑locked, ensuring audio‑video alignment during complex edits
  • Agent API exposes both mechanisms, allowing automated tools to manage track sync states and clip relationships

Frequently Asked Questions

What happens when linked clips span tracks with different sync‑lock states?

The clip linking mechanism operates independently of track sync‑lock states. When you move a linked clip, partnerMoves calculates the same frame delta for all partners regardless of their track's syncLocked value. However, if the edit triggers a ripple operation, only tracks with syncLocked set to true will shift together. The moved clip’s partners outside the ripple zone maintain their relative positions through the link group offset calculations.

How does Palmier Pro handle unlinking when only one clip in a group is selected?

The unlinkClips(ids:) method automatically expands the selection to include the full link group before clearing the linkGroupId on each member. As implemented in EditorViewModel+Linking.swift (lines 150‑157), passing a single clip ID effectively unlinks the entire group, removing the association between all previously linked clips.

Can sync‑locked tracks be edited without affecting ripple operations?

Yes. The syncLocked flag only controls behavior during ripple edits (insertions, deletions, and gap shifts). Direct edits like moving clips, trimming, or slipping content on a sync‑locked track do not trigger automatic shifts in other tracks unless those edits specifically involve ripple operations. For non‑ripple workflows, sync‑locked tracks behave identically to unlocked tracks.

How does the Agent API expose sync‑lock functionality?

The Agent tool executor exposes syncLocked through the manage_tracks command in ToolExecutor+Timeline.swift. When updating track properties via the Agent, you must supply at least one of muted, hidden, or syncLocked according to the validation logic in ToolExecutor+Clips.swift (lines 1123‑1134). The property defaults to true in the trackDefaults dictionary, ensuring new tracks maintain synchronization with the timeline by default.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →