Sample CodemacOS 26.0, Xcode 26.0Reviewed 2026-07-21View on Apple Developer

Adding a display mask rectangle metadata track to a movie file

At a glance

Item Summary
Purpose Copy a QuickTime movie while adding a timed display-mask metadata track associated with its enabled video track.
App architecture A two-file command-line tool: an AsyncParsableCommand validates arguments and hands one operation to MovieProcessor.
Main patterns Command entry point, orchestration facade, asynchronous reader-to-writer pipeline.
Project style Flat executable target with one entry file, one processor file, and small supporting value/error types.

Project structure

AVAddDisplayMaskTrack.swift       # ArgumentParser entry point
MovieProcessor.swift             # Asset validation, track setup, transfer, metadata generation
AVAddDisplayMaskTrack.xcodeproj/
Configuration/
README.md
video-raging-river.mp4            # Input fixture

Structure observations

  • Feature code is flat because the executable has one use case.
  • MovieProcessor.swift keeps the workflow and its VideoTrackInfo, BouncingBoxInfo, and ProcessingError support types together.
  • There is no UI, persistence layer, protocol abstraction, or package boundary in the extracted source.

Overall architecture

Reference code

AVAddDisplayMaskTrack.swift:41run()

mutating func run() async throws {
    let processor = MovieProcessor()
    try await processor.processMovie(
        inputPath: inputPath,
        outputPath: outputPath,
        displayMaskType: displayMaskType
    )
}

Interpretation

The entry point owns argument handling only. MovieProcessor owns the complete media operation: it creates the reader and writer, wires passthrough tracks, adds metadata, and waits for completion. This is directly observed, not an inferred multi-layer architecture.

Ownership and state

Ownership evidence

MovieProcessor.swift:11 — processor state

class MovieProcessor {
    private var readerOutputs: [AVAssetReaderOutput] = []
    private var writerInputs: [AVAssetWriterInput] = []
    private var metadataInput: AVAssetWriterInput?
    private var currentBoxInfo = BouncingBoxInfo()
}
Owner Object or state Relationship Mutation authority
AVAddDisplayMaskTrack MovieProcessor Creates a processor for one command invocation The local run() scope owns the reference.
MovieProcessor Reader outputs and writer inputs Retains corresponding track endpoints during transfer MovieProcessor only.
MovieProcessor Metadata adaptor/input Creates and retains the new metadata-track writer endpoint MovieProcessor only.
MovieProcessor Bouncing box and sample time Advances animation state while appending timed groups MovieProcessor only.

Class and protocol design

There is no app-defined protocol boundary. The concrete MovieProcessor is the single service object, while structs carry track and animation data.

Type Responsibility Depends on
AVAddDisplayMaskTrack Parse CLI arguments and start the use case ArgumentParser, MovieProcessor
MovieProcessor Coordinate asset validation, passthrough, metadata creation, and completion AVAssetReader, AVAssetWriter, Core Media metadata APIs
VideoTrackInfo Carry dimensions, duration, timescale, and frame rate CoreGraphics, CoreMedia
BouncingBoxInfo Carry mutable rectangle position and direction Swift value types
ProcessingError Convert workflow failures into user-facing descriptions LocalizedError

Access control

Symbol Access Verified effect Likely rationale
Reader/writer and animation properties private Only MovieProcessor can read or mutate transfer state Keeps asynchronous pipeline invariants inside its coordinator.
Setup, transfer, metadata, and progress helpers private Callers see only processMovie(...) Presents one use-case-level operation and hides step ordering.
processMovie(...) implicit internal The executable target can invoke it, but external modules cannot No public library API is needed for a command target.
Supporting structs and error enum implicit internal Available within the executable module They are implementation-level collaborators, not exported contracts.

Reference code

MovieProcessor.swift:78 — hidden pipeline step

private func setupExistingTracksForPassthroughAndReturnEnabledVideoInput(
    from asset: AVAsset,
    reader: AVAssetReader,
    writer: AVAssetWriter
) async throws -> (videoInput: AVAssetWriterInput, videoInfo: VideoTrackInfo) {
    // ...
}

No public, open, or fileprivate declaration appears in the two Swift source files.

Logic ownership and placement

Logic Owning type or file Placement rationale
Argument parsing and console outcome AVAddDisplayMaskTrack Kept at the process boundary.
Input validation and output replacement MovieProcessor.processMovie Part of orchestration before AVFoundation setup.
Existing-track passthrough MovieProcessor private helper Must coordinate paired reader outputs and writer inputs.
Static/dynamic rectangle calculation MovieProcessor private helpers Shares the processor’s sample time and bouncing-box state.
Domain error text ProcessingError Centralizes failure cases apart from media operations.

Design patterns

Pattern Source evidence Purpose or tradeoff
Command entry point AVAddDisplayMaskTrack.swift:15 and AsyncParsableCommand Maps terminal arguments to one asynchronous operation.
Facade/orchestrator MovieProcessor.swift:22 and processMovie(...) Gives the entry point one method while retaining step ordering internally.
Reader-writer pipeline MovieProcessor.swift:183 and setupMediaDataTransfer(...) Streams existing samples without transcoding, alongside a generated metadata track.
Strategy by value MovieProcessor.swift:236 and maskType branch Selects fixed or bouncing-mask behavior without separate strategy types; compact but integer-driven.

Naming conventions

  • Types: role-oriented nouns (MovieProcessor, VideoTrackInfo, ProcessingError).
  • Methods: command phrases (processMovie, addDisplayMaskMetadataTrack, monitorProgress).
  • Booleans/status: framework-style is... checks such as isReadable and isEnabled.
  • Files: the entry file matches the executable type; the service file matches its primary class.

Architecture takeaways

  • A one-use-case CLI can keep a minimal two-object boundary: parsing at the edge and media orchestration in one service.
  • Private step methods make the required reader/writer setup order explicit without exposing partial operations.
  • Passthrough and generated metadata share one writer session, so their lifecycle and completion are intentionally co-owned.
  • The lack of protocol abstraction is proportionate to a fixed, non-interactive sample rather than evidence of a reusable library design.

Source map

Source file Relevant symbols
AVAddDisplayMaskTrack.swift AVAddDisplayMaskTrack, run()
MovieProcessor.swift MovieProcessor, VideoTrackInfo, BouncingBoxInfo, ProcessingError