Search Docs
Loading...
Skip to content

Lock Video Design

Protect video clips, overlays, and placeholders from unwanted edits using CE.SDK’s scope-based permission system.

10 mins
estimated time
GitHub

CE.SDK uses global scopes and block-level scopes to decide which editing operations are allowed. For video designs, the same model can lock the whole scene, keep watermarks protected, and make only selected clips or overlays editable.

The backing sample creates a small headless video scene with one clip, one editable title overlay, and one locked watermark. Those blocks provide context for the scope calls below.

Understanding Scope Permissions#

Scopes control what operations users can perform on video clips, text overlays, watermarks, and other design blocks. CE.SDK combines global scope settings with block-level settings to determine the effective permission.

Global ScopeBlock ScopeResult
.allowanyPermitted
.denyanyBlocked
.deferenabledPermitted
.deferdisabledBlocked

Global scopes have three possible values:

  • .allow: The operation is always permitted, regardless of block-level settings
  • .deny: The operation is always blocked, regardless of block-level settings
  • .defer: The permission depends on the block-level scope setting

Block-level scopes are binary. They only take effect when the matching global scope is set to .defer.

Lock the Entire Video Design#

To lock all editing operations, discover the current scope keys with engine.editor.findAllScopes() and set each global scope to .deny.

let scopes = engine.editor.findAllScopes()
for scope in scopes {
try engine.editor.setGlobalScope(key: scope, value: .deny)
}

When all scopes are denied, users cannot select, move, edit text, replace fills, or delete blocks. This also prevents changes to video clips and overlays until you defer the global scope and enable the matching block-level scope on the blocks you want editable.

Enable Selection for Editable Video Blocks#

Before users can interact with any block, enable editor/select. Setting the global scope to .defer delegates the decision to each block, so only selected clips or overlays become interactive.

try engine.editor.setGlobalScope(key: "editor/select", value: .defer)
try engine.block.setScopeEnabled(videoClip, key: "editor/select", enabled: true)
try engine.block.setScopeEnabled(titleOverlay, key: "editor/select", enabled: true)
try engine.block.setScopeEnabled(watermarkOverlay, key: "editor/select", enabled: false)

Selective Video Locking Patterns#

Lock everything first, then selectively enable the capabilities that each video block needs. This keeps the default state restrictive while allowing controlled editing.

Text Overlay Editing#

Enable text/edit for text changes and text/character when users should also adjust text styling. The sample applies both scopes only to the title overlay.

try engine.editor.setGlobalScope(key: "text/edit", value: .defer)
try engine.editor.setGlobalScope(key: "text/character", value: .defer)
try engine.block.setScopeEnabled(titleOverlay, key: "text/edit", enabled: true)
try engine.block.setScopeEnabled(titleOverlay, key: "text/character", enabled: true)

The title text can now be edited while unrelated layout, fill, and lifecycle operations stay locked unless another section enables them.

Video Clip Replacement#

Enable fill/change on a video placeholder when users may replace the media source but should not change layout. The sample keeps movement, resize, and rotation denied on the video clip.

try engine.editor.setGlobalScope(key: "fill/change", value: .defer)
try engine.block.setScopeEnabled(videoClip, key: "fill/change", enabled: true)

Overlay Layout Adjustments#

Enable layout scopes only for blocks that users may reposition. The sample allows moving, resizing, and rotating the title overlay while keeping the video clip layout fixed.

try engine.editor.setGlobalScope(key: "layer/move", value: .defer)
try engine.editor.setGlobalScope(key: "layer/resize", value: .defer)
try engine.editor.setGlobalScope(key: "layer/rotate", value: .defer)
try engine.block.setScopeEnabled(titleOverlay, key: "layer/move", enabled: true)
try engine.block.setScopeEnabled(titleOverlay, key: "layer/resize", enabled: true)
try engine.block.setScopeEnabled(titleOverlay, key: "layer/rotate", enabled: true)

Protected Overlays#

Keep scopes disabled for watermarks, legal text, brand marks, or other protected overlays. Explicitly disabling the relevant block-level scopes makes the intent clear when the matching global scopes are deferred elsewhere.

let lockedOverlayScopes = [
"text/edit",
"text/character",
"fill/change",
"layer/move",
"layer/resize",
"layer/rotate",
]
for scope in lockedOverlayScopes {
try engine.block.setScopeEnabled(watermarkOverlay, key: scope, enabled: false)
}

Check Effective Permissions#

Use engine.block.isAllowedByScope(_:key:) to verify what the current scope configuration actually permits. This method evaluates both global and block-level settings.

let canSelectVideoClip = try engine.block.isAllowedByScope(videoClip, key: "editor/select")
let canReplaceVideoClip = try engine.block.isAllowedByScope(videoClip, key: "fill/change")
let canMoveVideoClip = try engine.block.isAllowedByScope(videoClip, key: "layer/move")
let canEditTitle = try engine.block.isAllowedByScope(titleOverlay, key: "text/edit")
let canMoveTitle = try engine.block.isAllowedByScope(titleOverlay, key: "layer/move")
let canSelectWatermark = try engine.block.isAllowedByScope(watermarkOverlay, key: "editor/select")
let titleTextEditEnabled = try engine.block.isScopeEnabled(titleOverlay, key: "text/edit")
let textEditGlobalScope = try engine.editor.getGlobalScope(key: "text/edit")
print("Permission status:")
print("- Can select video clip:", canSelectVideoClip) // true
print("- Can replace video clip fill:", canReplaceVideoClip) // true
print("- Can move video clip:", canMoveVideoClip) // false
print("- Can edit title:", canEditTitle) // true
print("- Can move title:", canMoveTitle) // true
print("- Can select watermark:", canSelectWatermark) // false
print("- Title text/edit block scope enabled:", titleTextEditEnabled) // true
print("- text/edit global is .defer:", textEditGlobalScope == .defer) // true

The distinction between checking methods is:

  • isAllowedByScope(_:key:) returns the effective permission after evaluating both levels
  • isScopeEnabled(_:key:) returns only the block-level setting
  • getGlobalScope(key:) returns only the global setting

Discover Available Scopes#

Use engine.editor.findAllScopes() instead of hardcoding a complete scope list. This keeps locking code aligned with the scopes available in the current engine.

let availableScopes = engine.editor.findAllScopes()
print("Available scopes:", availableScopes)
for scope in availableScopes {
let globalSetting = try engine.editor.getGlobalScope(key: scope)
print("- \(scope) is .defer:", globalSetting == .defer)
}

Available Scopes Reference#

ScopeDescription
layer/moveMove block position
layer/resizeResize block dimensions
layer/rotateRotate block
layer/flipFlip block horizontally or vertically
layer/cropCrop block content
layer/opacityChange block opacity
layer/blendModeChange blend mode
layer/visibilityToggle block visibility
layer/clippingChange clipping behavior
fill/changeChange fill content or text color
fill/changeTypeChange fill type
stroke/changeChange stroke properties
shape/changeChange shape type
text/editEdit text content
text/characterChange text styling such as font or size
appearance/adjustmentsChange color adjustments
appearance/filterApply or change filters
appearance/effectApply or change effects
appearance/blurApply or change blur
appearance/shadowApply or change shadows
appearance/animationApply or change animations
lifecycle/destroyDelete the block
lifecycle/duplicateDuplicate the block
editor/addAdd new blocks
editor/selectSelect blocks

Troubleshooting#

IssueCauseSolution
Block is still editableThe global scope is .allowSet the global scope to .deny or .defer
Block is unexpectedly lockedThe global scope is .denySet the global scope to .defer and enable the block-level scope
Users cannot select a blockeditor/select is still lockedEnable editor/select for blocks users should select
Permission check returns falseThe code checks the wrong scope levelUse isAllowedByScope(_:key:) for the effective permission
New scopes are not lockedThe code uses a hardcoded scope listUse findAllScopes() to discover scopes dynamically

API Reference#

MethodPurpose
engine.editor.findAllScopes()Get all available scope names
engine.editor.setGlobalScope(key:value:)Set a global scope to .allow, .deny, or .defer
engine.editor.getGlobalScope(key:)Get the current global setting for one scope
engine.block.setScopeEnabled(_:key:enabled:)Enable or disable a scope on one block
engine.block.isScopeEnabled(_:key:)Check only the block-level scope setting
engine.block.isAllowedByScope(_:key:)Check the effective permission after global and block-level scopes are evaluated

Next Steps#

  • Lock Content — Lock design elements to prevent unwanted modifications using CE.SDK’s scope-based permission system.
  • Lock Templates - Lock templates for consistent reuse
  • Rules Overview - Understand the broader rules system