I’ve been playing around with the AVAsset AVFoundation API.

The AVAsset object is at the core of representing an imported movie. An AVAssetTrack is AVFoundation’s representation of a track in a movie. There are multiple ways to get AVAssetTracks from an AVAsset.

You can get a list of all the tracks:

let movie:AVAsset = ...
let tracks:[AVAssetTrack] = movie.tracks

You can get a list of tracks with a specific characteristic, for example a visual characteristic:

let movie:AVAsset = ...
let tracks:[AVAssetTrack] = movie.tracksWithMediaCharacteristic(AVMediaCharacteristicVisual)

Or you can get a list of tracks which have a specific media type, for example audio:

let movie:AVAsset = ...
let tracks:[AVAssetTrack] = movie.tracksWithMediaType(AVMediaTypeAudio)

You can obtain a single AVAssetTrack object if you know it’s persistent track identifier value.

The persistent track identifier is of type CMPersitentTrackID which is 32 bit integer typedef and the invalid track reference kCMPersistentTrackID_Invalid is an anonymous enum with value 0.

Unfortunately the only way to get the track id of a track in an imported movie is querying a AVAssetTrack object so the persistent track id is useful when later on you want to reference a track that you have previously identified.

From what I understand the AVAssetTrack objects are fairly lightweight so keeping a list of AVAssetTrack objects is not going to be too much of a drain, but you might still prefer to keep a list of persistent track id values to request a AVAssetTrack object when you need it rather than holding onto a reference to an AVAssetTrack object.

To get a track using the tracks persistent identifier

let track:AVAssetTrack = movie.trackWithTrackID(2)

Tracks have segments and a segment specifies when one bit of content in a track starts and finishes based on a within the time range of a track. Each segment contains a time mapping between the source and target. You can get a list of all the segments in a track and this will often be a list of 1 segment which lasts the full length of the track but this is not necessarily the case.

To get a list of segments from a track:

let segments = track.segments

You can get the segment that corresponds to a specific track time:

let trackTime = CMTimeMake(60000, 600)
let segment = track.segmentForTrackTime(trackTime)

I’ve created a gist which is a very simple command line tool written in swift demonstrating this blog post.