How can I get an equal-power crossfade working in an AVVideoComposition
? I'm using something like the following to fade between video tracks, but when looping the same video over and over there is a very noticeable brightness dip during the transition due to whatever curve is being used internally in setOpacityRamp
.
let videoInstruction = AVMutableVideoCompositionInstruction()
let fromLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: fromCompositionTrack)
fromLayerInstruction.setOpacityRamp(fromStartOpacity: 1, toEndOpacity: 0, timeRange: timeRange)
let toLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: toCompositionTrack)
toLayerInstruction.setOpacityRamp(fromStartOpacity: 0, toEndOpacity: 1, timeRange: timeRange)
videoInstruction.timeRange = timeRange
videoInstruction.layerInstructions = [fromLayerInstruction, toLayerInstruction]
This isn’t possible. The setOpacityRamp
methods for AVMutableVideoCompositionLayerInstruction
lists the following description:
During an opacity ramp, opacity is computed using a linear interpolation.
There is an easier solution, though, which I found in the book Learning AV Foundation: A Hands-on Guide to Mastering the AV Foundation — fade out the current video track, but don’t fade in the new one. The book refers to this as a plain dissolve rather than a cross dissolve.
let videoInstruction = AVMutableVideoCompositionInstruction()
let fromLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: fromCompositionTrack)
fromLayerInstruction.setOpacityRamp(fromStartOpacity: 1, toEndOpacity: 0, timeRange: timeRange)
let toLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: toCompositionTrack)
// toLayerInstruction.setOpacityRamp(fromStartOpacity: 0, toEndOpacity: 1, timeRange: timeRange)
videoInstruction.timeRange = timeRange
videoInstruction.layerInstructions = [fromLayerInstruction, toLayerInstruction]