Adding SCTE 35 Metadata

Using FFmpeg

Please take a look at the Your own Live streaming demo that is part of the evaluation for an example that uses FFmpeg as an encoder, ingesting a livestream into a Unified Origin Live publishing point.

The following sections enhance this basic live demo with SCTE 35 metadata.

Adding SCTE 35

When streaming Live, metadata can be used to ‘mark’ a certain timestamp in the stream. Such a mark is also called a ‘cue’. Markers are pushed to a publishing point as part of a separate track and are carried in SCTE 35 messages which, like the contents of all other tracks, need to be packaged in fMP4 containers.

SCTE 35 messages can contain any relevant data however we are interested in their ability to cue splice points in a stream.

A splice point is a specific timestamp correspsonding to an IDR frame offering the opportunity to seamlessly switch the livestream between different clips. Splice points can be used to cue:

  • (Ad) insertion opportunities
  • Start and endpoints of a programs

If the cue to mark a splice point does not correspond with the start of a media segment, IDR frame, in the stream by default, the encoder pushing the livestream needs to insert an additional IDR frame at the timestamp signaled in the cue. If the --splice_media option is enabled, Origin will splice frame accurately and the part of the media segment containing the splice point will be merged with the previous or next segment.

In addition to splicing media segments if necessary, Origin will signal the splice points in the Apple HLS and MPEG DASH client manifests. A third party service can then be used to insert a clip at the splice point to create an ad insertion or ad replacement workflow.

Adding Timed Metadata

First create a new publishing point with the additional options --timed_metadata to enable passthrough of timed metadata and --splice_media to enable Origin to slice media segments at SCTE 35 markers:


mp4split -o channel1.isml \
  --hls.minimum_fragment_length=144/25 \
  --hls.client_manifest_version=4 \
  --archiving=1 \
  --archive_length=1200 \
  --archive_segment_length=300 \
  --dvr_window_length=600 \
  --restart_on_encoder_reconnect \
  --timed_metadata \

# The API would run the following lines, but for brevity
# this isn't set up for the certification

sudo mkdir -p /var/www/live/channel1
sudo mv channel2.isml /var/www/live/channel1
sudo chown -R www-data:www-data /var/www/live/channel1

Next we start FFmpeg, pointed at channel2 using the following steps.

Push a livestream to the publishing point that you have just created, using



export FRAME_RATE=25
export GOP_LENGTH=24
export PUB_POINT_URI=${URL}'/Streams(test)'


Test playback (remember to use the URL that is specific to your playout format of choice):

curl -v http://${hostname}/live/channel1/channel1.isml/.mpd

It is also possible to use the player.

With the live stream running we now can insert metadata. Here, we do this with push_input_stream (where --avail 24 specifies the interval at which the markers are inserted):



push_input_stream -u ${URL} --avail 24

The metadata will be present in the media playlist(s), you can check this by getting the master playlist and then a media playlist/variant.

fMP4 Ingest Toolset

The push_input_stream command referenced in the previous seciont in an internal tool, it would be better to use the fMP4 tools, which are publicly available and contains dashEventfmp4 which can be used to convert convert an mpd with events to a metadata track.

This metadata track then can be posted with curl to a Unified Origin to add the metadata track to the ingest.


TODO - Add outline of how to use fMP4 tools.

Best Practices

  • Always set hls_minimum_fragment_length equal to or multiple of (if encoder splices) the GOP, unless the source encoder segmentation divides evenly into the default value of 4 seconds
  • SCTE markers are received by the Origin ahead of the desired presentation. At least 2x ahead of the target fragment length. If this is not possibe, time shift can be used to delay the presentaiton live edge allowing time for stream conditioning. [Example]
  • Should mpd_minumum_fragment_length be set ensure mpd_segment_template is also set to equal either time or number.
  • dvr_window_length should always be set to a duration greater than the longest duration advertisement.