Sample CodemacOS 10.15+Reviewed 2026-07-21View on Apple Developer

Using HEVC video with alpha

At a glance

Item Summary
Purpose Demonstrate HEVC-alpha playback, SceneKit-to-AVAssetWriter generation, and several AVAssetExportSession conversions.
App architecture One workspace contains three independent targets: playback app, asset-writing app, and command-line export examples.
Main patterns Linear media pipelines, framework delegate, callback completion, per-target composition.
Project style Separate project folders and resources for Playback, AssetWriting, and Exports; intentionally little shared app infrastructure.

Project structure

HEVC-Videos-With-Alpha.xcworkspace
├── HEVC-Videos-With-Alpha-Playback/
│   ├── ViewController.swift
│   └── Resources/
├── HEVC-Videos-With-Alpha-AssetWriting/
│   ├── AppDelegate.swift
│   └── Resources/
└── HEVC-Videos-With-Alpha-Exports/
    ├── main.swift
    └── Resources/

These are complementary demonstrations, not layers of a single application. Architecture and ownership therefore need to be read per target.

Overall architecture

Reference code

HEVC-Videos-With-Alpha-Playback/HEVC-Videos-With-Alpha-Playback/ViewController.swift:31 — the playback target is deliberately direct (abridged).

guard let alphaMovieURL = Bundle.main.url(
    forResource: "puppets_with_alpha_hevc", withExtension: "mov"
) else { return }
videoPlayer = AVPlayer(url: alphaMovieURL)
let video = SKVideoNode(avPlayer: videoPlayer)
scene.addChild(video)
videoPlayer.play()

The playback app composes the alpha video over a SpriteKit scene. It does not share services with the writing or export targets.

Ownership and state

Ownership evidence

HEVC-Videos-With-Alpha-AssetWriting/HEVC-Videos-With-Alpha-AssetWriting/AppDelegate.swift:31 — the writing app owns long-lived renderer resources and creates writer resources per export (abridged).

let renderer = SCNRenderer(device: nil, options: nil)
var lampMaterials: SCNNode!
var metalTextureCache: CVMetalTextureCache!
var frameCounter = 0

func makeAssetWriter(outputURL: URL, fileType: AVFileType) throws
    -> (assetWriter: AVAssetWriter,
        writerInput: AVAssetWriterInput,
        adaptor: AVAssetWriterInputPixelBufferAdaptor) {
    // ... creates one writer graph for an export
}
Owner Object or state Relationship Mutation authority
Playback ViewController Player and created video node Controller-lifetime playback Controller starts playback; SpriteKit scene owns the added node.
Asset-writing AppDelegate Renderer, texture cache, frame counter App-lifetime render resources App delegate renders and advances frames.
One export invocation Writer/input/adaptor tuple Local closure-captured graph Writing callback appends buffers and finishes it.
CLI top-level workflow Export sessions and dispatch group Local operation lifetime Each helper configures its own session; callbacks report status.

Class and protocol design

Reference code

HEVC-Videos-With-Alpha-AssetWriting/HEVC-Videos-With-Alpha-AssetWriting/AppDelegate.swift:21 — the writing app uses framework protocols, not an app-defined abstraction (abridged).

@NSApplicationMain
class AppDelegate: NSObject,
                   NSApplicationDelegate,
                   SCNSceneRendererDelegate {
    // ...
    func renderer(_ renderer: SCNSceneRenderer,
                  updateAtTime time: TimeInterval) {
        let angle = CGFloat(Double.pi * 2 * time / ExportSettings.duration.seconds)
        lampMaterials.eulerAngles = SCNVector3(x: 0, y: angle, z: 0)
    }
}

No custom protocol-oriented layer exists. The sample relies on AVFoundation, SceneKit, SpriteKit, and AppKit protocol/class contracts directly.

Access control

Symbol Access Verified effect Likely rationale
Most target types and properties internal default Visible throughout their app/CLI target. Educational sample favors direct examples over encapsulated subsystems.
ExportSettings values internal static let Shared constants within the asset-writing target. Groups fixed output configuration without an instance.
AVAssetExportSession.Status.description public Satisfies a publicly visible description witness on the extended framework type. Makes status printable; it is not an app service API.
Export helper locals lexical local scope Sessions and compositions exist only inside one operation. Operation lifetime itself provides encapsulation.

HEVC-Videos-With-Alpha-Exports/HEVC-Videos-With-Alpha-Exports/main.swift:14 (abridged):

extension AVAssetExportSession.Status: CustomStringConvertible {
    public var description: String {
        switch self {
        case .completed: return "completed"
        case .failed: return "failed"
        // ...
        }
    }
}

Logic ownership and placement

Logic Owning type or file Placement rationale
Alpha playback composition Playback ViewController Tiny target needs one scene/player integration point.
Scene frame rendering AssetWriting AppDelegate Owns renderer delegate and app UI action.
Writer configuration/append loop AssetWriting AppDelegate methods Keeps pixel buffer pool, timestamps, and finish lifecycle together.
Preset export/fallback/chroma-key recipes Exports main.swift helpers Each top-level function is one standalone conversion recipe.

Design patterns

Pattern Source evidence Purpose or tradeoff
Media pipeline HEVC-Videos-With-Alpha-AssetWriting/HEVC-Videos-With-Alpha-AssetWriting/AppDelegate.swift:164 Renders frames, appends pixel buffers, then finishes one writer.
Framework delegate HEVC-Videos-With-Alpha-AssetWriting/HEVC-Videos-With-Alpha-AssetWriting/AppDelegate.swift:120 SceneKit requests per-frame animation updates.
Callback completion HEVC-Videos-With-Alpha-Exports/HEVC-Videos-With-Alpha-Exports/main.swift:29 Export helpers return asynchronous status without shared state.
Multi-target examples HEVC-Videos-With-Alpha.xcworkspace/contents.xcworkspacedata:1 Keeps playback, generation, and conversion independently runnable.

Naming conventions

  • Target names describe use cases: Playback, AssetWriting, and Exports.
  • Functions name source/destination transformations (exportToHEVCWithAlpha..., exportFromHEVCWithAlphaToAVC...).
  • Fixed encoding dimensions/timing live under ExportSettings.
  • Framework-generic names (AppDelegate, ViewController) reflect the very small target scope.

Architecture takeaways

  • Read this archive as three small pipelines, not one app architecture.
  • Keep writer/input/adaptor lifetime together for a single export operation.
  • Local helper functions can be sufficient boundaries for a recipe-style command-line target.
  • App-defined protocol abstraction is absent; framework protocols are the collaboration contracts.

Source map

Source file Relevant symbols
HEVC-Videos-With-Alpha-Playback/HEVC-Videos-With-Alpha-Playback/ViewController.swift SpriteKit/AVPlayer playback
HEVC-Videos-With-Alpha-AssetWriting/HEVC-Videos-With-Alpha-AssetWriting/AppDelegate.swift Scene rendering and asset writing
HEVC-Videos-With-Alpha-Exports/HEVC-Videos-With-Alpha-Exports/main.swift Export recipes and chroma key
HEVC-Videos-With-Alpha.xcworkspace/contents.xcworkspacedata Three-project composition

Source caveat: the targets intentionally duplicate small amounts of setup and do not form a reusable HEVC-alpha library.