Audio
filmstrip folds every level in an edit into one gain curve per clip before a backend sees it, so all four backends land on the same gain.
Levels
Section titled “Levels”A clip or a track takes an AudioLevel, and the composition takes an AudioSpec.
val composition = compositionOf { clip(MediaSource.of("/path/to/interview.mp4")) { audio(AudioLevel.Volume(1.5f)) } clip(MediaSource.of("/path/to/broll.mp4")) { audio(AudioLevel.Mute) } audio(AudioSpec.Volume(0.8f)) }Inheritis the default and leaves the enclosing scope alone.Volumescales by a constant.1fis unchanged and anything above it boosts.Mutecontributes silence without changing timing or the output’s track count.
Levels multiply down the scopes and aren’t capped. A mute at any scope silences everything below it. The composition’s
AudioSpec also has Keep, Mute, Remove and AudioOnly, covered in Edits.
A negative or non-finite gain is refused with InvalidComposition at plan time.
fadeIn and fadeOut sit on a clip or a track.
val composition = compositionOf { clip(MediaSource.of("/path/to/clip.mp4")) { trim(start = 5.seconds, endExclusive = 25.seconds) audio(AudioLevel.Volume(0.5f)) fadeIn(1.seconds) fadeOut(2.seconds) } }A fade multiplies whatever audio set, so this clip rises from silence to half, not to full. Fading a mute leaves it
muted. A clip’s fades are measured against its trim, so retrimming moves them too. A track’s fade in starts where the
track does, and its fade out ends where the track does. Fades on different scopes multiply.
A fade that’s negative or longer than its scope is refused with InvalidComposition, and so is a pair that runs longer
than the scope, since the two ramps would cross.
These fades only touch audio. To fade an overlay’s picture, see Overlays.
Envelopes
Section titled “Envelopes”AudioLevel.Envelope is a gain curve you pin at points. The gain ramps linearly between neighbouring points and holds
flat before the first and after the last. Nothing is smoothed, so a curve is written as more points.
val composition = compositionOf { clip(MediaSource.of("/path/to/clip.mp4")) { audio( AudioLevel.Envelope( listOf( EnvelopePoint(at = 4.seconds, gain = 1f), EnvelopePoint(at = 5.seconds, gain = 0.2f), EnvelopePoint(at = 3.seconds, gain = 0.2f, from = EnvelopeAnchor.End), EnvelopePoint(at = Duration.ZERO, gain = 1f, from = EnvelopeAnchor.End), ), ), ) } }A point anchored at EnvelopeAnchor.End is measured back from the end of its scope, and placed once the plan knows how
long the scope runs. That lets you write a fade out before you know the clip’s length. A clip’s envelope reads against its
trimmed length, and a track’s against its whole run.
A point outside its scope, a negative gain, or points that fall out of time order once the end-anchored ones are placed
are refused with InvalidComposition.
Extra tracks
Section titled “Extra tracks”A track added with TrackContent.Audio plays alongside the primary track and is mixed in. The default content for track
carries video too, so name it, or the plan refuses it.
val composition = compositionOf { clip(MediaSource.of("/path/to/clip.mp4")) track(TrackContent.Audio) { clip(MediaSource.of("/path/to/voice-over.m4a")) startAt(3.seconds) } track(TrackContent.Audio) { clip(MediaSource.of("/path/to/music.m4a")) audio(AudioLevel.Volume(0.3f)) looping() fadeOut(2.seconds) } }startAtholds a track off until that far into the composition. A negative start is refused.loopingrepeats the track from the top until the longest non-looping track ends, and cuts the last pass where it runs past.
The composition runs as long as its longest non-looping track, offset included, so a bed longer than the picture sets the length. The picture holds the primary track’s last frame until the end.
A looping track’s scope is its whole run. Its fadeIn plays once at the start, and its fadeOut and any end-anchored
point land where the composition ends. A clip’s own fade or envelope is read against the clip, so it replays on every
pass.
A composition where every track loops has nothing to bound it, and is refused with InvalidComposition. So is a track
laying more than 2000 passes.