VideoEditor is an R&D / educational iOS video editing app experiment targeting iOS 16.0+. The goal is to explore modern Swift, UIKit, and media technologies (e.g. AVFoundation) with a sustainable and testable architecture.
Production notice: This project is currently a “playground” and should not be considered production-ready.
- Modularity: Clear separation of UI, Domain, and Data layers.
- Testability: Dependencies are injected via DI.
- Simplicity: KISS principle; avoid unnecessary abstraction.
- UIKit-first: Screens are built with programmatic UIKit + Auto Layout.
- Xcode: 26.3
- iOS Deployment Target: 16.0+
- Language: Swift 5.5+
The editor preview is not a raw file player. It rebuilds an AVFoundation composition from the current project state whenever you load or press play.
This diagram shows how EditorPlaybackManager coordinates loadPreview / play, how PreviewTimelineCompositionBuilder scans tracks and aggregates sources, and how the assembler + AVFoundation produce an AVPlayerItem for the preview layer.
EditingProject(Domain/Models/): The serializable project — tracks, clips, timeline/source time ranges, export settings. Track order implies z-order (later tracks draw on top).CompositionBuilding(Domain/Protocols/CompositionBuilding.swift):build(from: EditingProject)→CompositionBuildResult(AVPlayerItem+AVComposition+AVVideoComposition, plus optional overlay layers).
PreviewTimelineCompositionBuilder implements CompositionBuilding:
- Computes project duration and a fixed preview render size (1080×1920).
- Walks video and overlay tracks and turns each supported clip into internal preview sources (file video maps source range → timeline; still images use a tiny bundled donor video so AVFoundation has real samples).
PreviewCompositionAssembler(PreviewVideoCompositionCore.swift) builds anAVMutableCompositionand a customAVMutableVideoComposition(Core Image–based compositing for stacking, effects, transitions).- Audio clips are inserted on separate composition audio tracks; tracks are padded to the full project length with empty ranges where needed.
- Wraps the composition in
AVPlayerItem, attachesvideoComposition/audioMixwhen present, and returns the result.
Other asset types (e.g. some identifiers) may be skipped until implemented — the builder only includes what it can turn into composition segments.
EditorViewModel.projectSnapshot()produces anEditingProjectthat reflects the current timeline (including edits). Playback always uses this snapshot, not a stale copy.EditorPlaybackManagerholds aCompositionBuildinginstance (default:PreviewTimelineCompositionBuilder), anAVPlayer, and anAVPlayerLayerplaced insideEditorRenderView’s canvas.- First appearance:
EditorViewControllercallsloadPreview: build composition, attach/replace the player item, pause at time zero (thumbnail-style first frame). - Toolbar play:
playrunsbuildagain with the latest snapshot, thenplayer.play(). Pause only pauses — no rebuild.
Playhead updates come from a periodic time observer on the player; reaching the end triggers pause and resets the toolbar play state.
- Media import (Photos / Videos / Audio) ✅
- Timeline + trim media items ✅
- Create Composition builder (accepts image & video & audio and converts them into composition & playerItem) ✅
- Composition builder optimizations (working on it)
- EditorTimelineView optimizations for play, fast scrub debounce etc.
- Add transition between media items ✅
- Add overlay media items support like sticker and text
- Add applying effects to media items (like glitch etc)
- Add applying core image & custom filter to media items
- HDR support
- Higher render size support
- Export pipeline (presets/bitrate)
