How to add Timeline Markers on Mobile

Timeline markers are a common way to show important points on a timeline. They can mark chapters, highlight events like goals in a football game, or show where ads will be.

For adding Timeline Markers via Bitmovin's Player Web SDK check out Timeline markers.

Static markers

Adding static markers on Mobile is possible in a very similar way as on web.

On both iOS and Android, static markers can be configured through the UIConfig. On iOS, this can be configured through the BitmovinUserInterfaceConfig, while on Android, this is directly on the UIConfig . On both platforms, the mentioned config contains a property customOptions which we will utilize to configure our static markers.

// Create a BitmovinUserInterfaceConfig instance
let bitmovinUserInterfaceConfig = BitmovinUserInterfaceConfig()
// Configure the timeline markers using the `customOptions` which takes a key value dictionary
bitmovinUserInterfaceConfig.customOptions = [
    "metadata": [
        "markers": [
            [
              "time": 24,
              "title": "Salto on the edge"
            ],
            [
              "time": 69,
              "title": "Interview - Marcus Gustafsson"
            ],
            [
              "time": 105,
              "title": "Parcour rating explained"
            ],
            [
              "time": 188,
              "duration": 11,
              "title": "And we have a winner!"
            ]
        ]
    ]
]

// Set the BitmovinUserInterfaceConfig on the StyleConfig of the PlayerConfig instance
playerConfig.styleConfig.userInterfaceConfig = bitmovinUserInterfaceConfig
// Configure the timeline markers using a key value dictionary
val customOptionsMap = mapOf(
    "metadata" to mapOf(
        "markers" to arrayOf(
            mapOf(
                "time" to 24,
                "title" to "Salto on the edge"
            ),
            mapOf(
                "time" to 69,
                "title" to "Interview - Marcus Gustafsson"
            ),
            mapOf(
                "time" to 105,
                "title" to "Parcour rating explained"
            ),
            mapOf(
                "time" to 188,
                "duration" to 11,
                "title" to "And we have a winner!"
            )
        )
    )
)

// Provide the dictionary as JSON string to the PlayerViewConfig using the customOptions property
val viewConfig = PlayerViewConfig(
    uiConfig = UiConfig.WebUi(
        customOptions = JSONObject(customOptionsMap).toString()
    ),
)

Dynamic markers

In contrast to the Bitmovin Player Web SDK, adding Timeline Markers to the seek bar on Mobile requires slightly more work.

Since there is no API on the mobile PlayerView to add and remove Timeline Markers dynamically yet, we need to use a CustomMessageHandler in combination with a custom UI build. Check out Add a custom Button component and Using a customized UI for details on that.

  1. Register a customMessageHandler in your custom UI implementation. It can be as easy as modifying the buildDefaultSmallScreenUI of the UIFactory to something like this:
export function buildDefaultSmallScreenUI(player: PlayerAPI, config: UIConfig = {}): UIManager {
  const uiManager = UIFactory.buildModernSmallScreenUI(player, config);

  // Register the customMessageHandler if availble (on iOS and Android)
  if (window.bitmovin.customMessageHandler) {
    // Register a listener for the custom event
    window.bitmovin.customMessageHandler.on('addTimelineMarker', (data?: string) => {
      // Parse the payload to an Object
      let marker = JSON.parse(data);

      // Add the timeline marker
      uiManager.addTimelineMarker(marker);
    });
  }

  return uiManager;
}
  1. On the native side, find the correct place to emit the event we just subscribed to in the UI. This could be, e.g., on a user interaction or, for a more advanced use case, when Ads are scheduled to indicate them on the seek bar.
// Create Timeline Marker payload
let payload: [String: Any] = [
    "time": 5,
    "title": "Foo Bar"
]

// Serialize the Timeline Marker to JSON
guard let jsonData = try? JSONSerialization.data(withJSONObject: payload, options: []),
    let jsonString = String(data: jsonData, encoding: .utf8) else {
    print("JSON serialization failed")
    return
}

// Send the event to the UI
customMessageHandler?.sendMessage(
    "addTimelineMarker",
    withData: jsonString
)
// Create Timeline Marker payload
val payload = mapOf(
    "time" to 5,
    "title" to "Foo Bar"
)

// Send the event to the UI
customMessageHandler.sendMessage(
    "addTimelineMarker",
    // Serialize the Timeline Marker to JSON
    JSONObject(payload).toString()
)

See Add a custom Button component - Reuse on Mobile SDKs for a full step by step guide how to set up the CustomMessageHandler.