100ms Logo



Search docs

HLS Timed Metadata

HLS Timed Metadata feature helps you synchronise certain events with the HLS stream. This can be useful for showing interactive quizzes / product overlays etc.


  • 100ms iOS SDK version 0.4.1 or higher
  • Active HLS stream

Sending HLS Timed Metadata

To add HLS timed metadata cue to the currently running HLS stream use sendHLSTimedMetadata API like this:

let metadata = HMSHLSTimedMetadata(payload: "quiz id: 3") hmsSDK.sendHLSTimedMetadata([metadata], completion: { [weak self] _, error in if let error = error as? HMSError { print("Unable to send metadata: \(error)") } else { print("Metadata sent") } })

Receiving HLS Timed Metadata

To receive metadata on the HLS player side use AVPlayerItemMetadataCollector. Detailed documentation is available here but to briefly summarize:

  1. Create a metadata collector and pass a delegate:
metadataCollector = AVPlayerItemMetadataCollector() metadataCollector.setDelegate(self, queue: DispatchQueue.main)
  1. Add metadata collector to your AVPlayerItem item
  1. Conform to the AVPlayerItemMetadataCollectorPushDelegate protocol to save collected metadata
func metadataCollector(_ metadataCollector: AVPlayerItemMetadataCollector, didCollect metadataGroups: [AVDateRangeMetadataGroup], indexesOfNewGroups: IndexSet, indexesOfModifiedGroups: IndexSet) { self.metadataGroups = metadataGroups }
  1. Add playback observer to show the metadata when playback time reaches the timestamp defined by the metadata
player.addPeriodicTimeObserver(forInterval: CMTime(seconds: 1.0, preferredTimescale: CMTimeScale(NSEC_PER_SEC)), queue: .main, using: { [weak self] time in self?.updateMetadataView(for: time) })
func updateMetadataView(for currentTime: CMTime) { hideCurrentMetadataViewIfNeeded() guard currentMetadataGroup == nil, let playerItem = playerItem else { return } for group in metadataGroups { if group.shouldShow(for: playerItem) { showMetadataView(for: group) break } } } func hideCurrentMetadataViewIfNeeded() { guard let currentMetadataGroup = currentMetadataGroup, let playerItem = playerItem, !currentMetadataGroup.shouldShow(for: playerItem) else { return } self.currentMetadataGroup = nil metadataView.isHidden = true } func showMetadataView(for group: AVDateRangeMetadataGroup) { guard currentMetadataGroup != group else { return } currentMetadataGroup = group metadataView.isHidden = false metadataView.text = group.items.first?.stringValue }
extension AVDateRangeMetadataGroup { func shouldShow(for item: AVPlayerItem) -> Bool { guard let endDate = endDate, let currentDate = item.currentDate() else { return false } return startDate <= currentDate && currentDate < endDate } }

👀 To see an example of HLS Timed Metadata implementation using 100ms SDK, checkout our example project.

Have a suggestion? Recommend changes ->

Was this helpful?