Managing Media Offline/Missing State and Relinking Workflows in Palmier Pro
Palmier Pro tracks offline media through three distinct reference sets maintained in EditorViewModel.swift, providing automatic detection, real-time preview overlays, and bulk relinking capabilities via the relinkOfflineAssets(fromFolder:) API.
Managing media offline/missing state and relinking workflows in Palmier Pro centers on a robust asset verification system that treats every imported file as a managed resource. The palmier-io/palmier-pro repository implements deterministic state tracking across the editor, preview, and export pipelines to ensure projects remain functional even when source files move or become corrupted. All offline state lives as a single source of truth in the view model, with dedicated resolution paths for both individual asset relinking and bulk folder reconciliation.
Understanding Offline Media States
Palmier Pro categorizes problematic assets into three complementary sets stored in EditorViewModel.swift:
offlineMediaRefs: Asset IDs whose source files cannot be found on disk or are inaccessible.unprocessableMediaRefs: Asset IDs whose files exist but cannot be decoded (e.g., unsupported codec).missingMediaRefs: Asset IDs referenced in a project but never scanned (used for lazy-loading).
These sets drive all downstream decisions in the preview renderer and export pipeline. When the app launches or the user opens the Media panel, showMediaPanelMediaTab() triggers refreshMissingMediaCache(), which walks the filesystem off the main thread to populate offlineMediaRefs and unprocessableMediaRefs.
Real-Time Detection and Refresh Cycles
The editor registers an observer for NSApplication.didBecomeActiveNotification that automatically calls refreshMissingMediaCache() whenever Palmier Pro regains focus. This design ensures that external file system changes—such as a user moving assets in Finder while the app is backgrounded—are immediately reflected in the UI and any pending export jobs.
Visual Feedback and Preview Handling
The preview system reads offline state directly from EditorViewModel and renders appropriate placeholders. In PreviewContainerView.swift, the offlineOverlay(timelineState:) helper extracts offline clips, while offlinePreview(assetId:path:isUnprocessable:) draws the semi-transparent overlay. When all offline references are cleared, the preview automatically recovers without requiring a manual refresh.
CompositionBuilder receives the complete set of offline references via ctx.offlineMediaRefs and omits those clips from the render graph. It also tags the builder’s context with offlineMediaRefs so downstream exporters can report missing assets accurately.
Relinking Workflows and APIs
The relinking logic resides in EditorViewModel+Relink.swift, exposing two primary APIs for restoring broken references:
Single Asset Relinking
// Repoint a specific asset to a new URL and refresh its state
func relinkAsset(id: String, to newURL: URL)
Bulk Folder Relinking
// Recursively scan a folder, match filenames (case-insensitive) to offline assets,
// and rewire them in bulk. Returns (relinked, total) for UI feedback.
@discardableResult
func relinkOfflineAssets(fromFolder folder: URL) -> (relinked: Int, total: Int)
Both functions delegate to applyRelink(id:to:), which performs five atomic operations:
- Updates the asset’s
urlproperty. - Clears cached denoise results (
denoiseFailed,denoiseBaked). - Invalidates the visual cache via
mediaVisualCache.invalidate(id). - Updates the manifest entry to keep the project file synchronized.
- Triggers
finalizeImportedAssetto re-run import-time analyses (e.g., speaker identification).
The bulk relink algorithm walks the target folder once to build a dictionary of lower-cased filename-to-URL mappings, then attempts to match each offline asset’s original filename. This guarantees O(N) complexity for the folder scan plus O(M) for the offline asset list, where N is the number of files in the folder and M is the number of offline assets.
Export Pipeline Safety
ExportService and ExportQueue include offline media sets in their status reports. The queue adds offlineMediaRefs.count + unprocessableMediaRefs.count to its work-item validation, causing export jobs to fail early if required media is missing. The UI surfaces a concise "X media files are offline" toast, preventing wasted rendering time.
Graceful degradation ensures that when a manifest cannot be parsed, the project degrades to "media offline" rather than being lost entirely, as implemented in VideoProject.swift.
Practical Code Examples
Relink a single clip selected in the Media panel:
let clipID = "a1b2c3"
let newLocation = URL(fileURLWithPath: "/Volumes/ExternalDrive/Clips/scene-01.mov")
editorViewModel.relinkAsset(id: clipID, to: newLocation)
Bulk-relink all offline clips by pointing to a folder containing the originals:
let folder = URL(fileURLWithPath: "/Users/me/Projects/Project-Assets")
let result = editorViewModel.relinkOfflineAssets(fromFolder: folder)
print("Re-linked \(result.relinked) of \(result.total) offline assets")
Force a refresh of offline status after external file moves:
editorViewModel.refreshMissingMediaCache()
Export while respecting offline media—the exporter automatically aborts if any required asset remains offline:
let exportOptions = ExportOptions(preset: .highQuality)
exportService.startExport(projectID: editorViewModel.projectId ?? "", options: exportOptions) { status in
switch status {
case .completed: print("Export succeeded")
case .failed(let error): print("Export failed: \(error)")
}
}
Summary
- Palmier Pro maintains three distinct reference sets (
offlineMediaRefs,unprocessableMediaRefs,missingMediaRefs) inEditorViewModel.swiftas the single source of truth for media state. - Automatic detection occurs via
refreshMissingMediaCache(), triggered on app activation and Media panel access. - The preview pipeline in
PreviewContainerView.swiftrenders semi-transparent overlays for offline assets, whileCompositionBuilderexcludes them from the render graph. - Relinking supports both single-asset updates (
relinkAsset) and bulk reconciliation (relinkOfflineAssets) with deterministic O(N+M) performance. - The export pipeline validates offline state before processing, failing early with clear user feedback when source files are unavailable.
Frequently Asked Questions
How does Palmier Pro detect when media goes offline?
Palmier Pro detects offline media by calling refreshMissingMediaCache() in EditorViewModel.swift, which runs off the main thread to verify file existence for all managed assets. This method populates offlineMediaRefs when files are missing and unprocessableMediaRefs when files exist but cannot be decoded. The system also listens for NSApplication.didBecomeActiveNotification to automatically refresh state when the app returns to the foreground.
What is the difference between offline and unprocessable media in Palmier Pro?
Offline media refers to assets whose source files cannot be found at their recorded URLs, typically due to files being moved, renamed, or deleted. Unprocessable media refers to assets whose files exist on disk but cannot be decoded by the pipeline, such as those with unsupported codecs or corruption. These states are tracked separately in offlineMediaRefs and unprocessableMediaRefs to allow different UI treatments and relinking strategies.
Can I relink multiple offline files at once in Palmier Pro?
Yes. The relinkOfflineAssets(fromFolder:) method in EditorViewModel+Relink.swift performs bulk relinking by scanning a folder recursively and matching filenames (case-insensitive) to offline asset references. This operation returns a tuple of (relinked: Int, total: Int) for UI feedback and operates with O(N+M) efficiency by indexing the folder contents before attempting matches.
What happens if I try to export a project with offline media?
The export pipeline in ExportService and ExportQueue validates the offlineMediaRefs and unprocessableMediaRefs sets before rendering begins. If any required assets are offline, the export job fails immediately with a status report indicating the number of missing files. This prevents wasted processing time and allows the UI to display a "X media files are offline" toast directing the user to relink before retrying.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →