Define layouts with a custom VideoCompositorSettings

Users might want to edit multiple media assets together such that more than one media item appears at the same time in the final video. This includes arranging items in layouts such as picture-in-picture, side-by-side, or a grid. Here are some examples of such projects:

Video with picture-in-picture layout
Media items arranged in a picture-in-picture layout.
Video with grid layout
Media items arranged in a 2x2 grid layout.

You can explore an implementation of these layouts in the Composition demo app.

Implement a VideoCompositorSettings

The VideoCompositorSettings interface contains 2 methods:

Configure the presentation of a sequence with an OverlaySettings

Your implementation of getOverlaySettings() should return an instance of the OverlaySettings interface for each sequence in your project. The inputId parameter identifies which sequence the settings will be applied to. To build an instance, you can use the StaticOverlaySettings class included in Media3. See the StaticOverlaySettings.Builder reference page for a full list of configuration options, which includes visual modifications like alpha transparency and HDR luminance, positional modifications like anchor point and location within the frame, and transformations like rotation and scale.

override fun getOverlaySettings(inputId: Int, presentationTimeUs: Long): OverlaySettings {
  return when (inputId) {
    // Position the first sequence in the top-left
    0 -> {
      StaticOverlaySettings.Builder()
        // Scale the video down to 1/4th the size of the frame
        .setScale(0.5f, 0.5f)
        // Anchor the sequence in the middle of frame
        .setOverlayFrameAnchor(0f, 0f)
        // Position the video in the top-left section of the frame
        .setBackgroundFrameAnchor(-0.5f, 0.5f)
        .build()
    }
    // Add more cases for remaining input sequences
    else -> StaticOverlaySettings.Builder().build()
  }
}

Using the presentationTimeUs parameter of the getOverlaySettings() method, you can modify these settings based on the position of the video, as demonstrated by the moving picture-in-picture example earlier on this page.

override fun getOverlaySettings(inputId: Int, presentationTimeUs: Long): OverlaySettings {
  return if (inputId == 0) {
    // Use the first sequence as the overlay
    val cycleRadians = 2 * PI * (presentationTimeUs.toDouble() / cycleTimeUs)
    StaticOverlaySettings.Builder()
      // Scale the overlay down
      .setScale(0.35f, 0.35f)
      // Anchor the overlay in the top-middle of the frame
      .setOverlayFrameAnchor(0f, 1f)
      // Move the overlay over time
      .setBackgroundFrameAnchor(sin(cycleRadians).toFloat() * 0.5f, -0.2f)
      // Rotate the overlay over time
      .setRotationDegrees(cos(cycleRadians).toFloat() * -10f)
      .build()
  } else {
    // Present the second sequence in the background as normal
    StaticOverlaySettings.Builder().build()
  }
}

Feedback

If you have any feedback or feature requests for video compositing use-cases, file an issue on the Media3 GitHub repository.