Re-use SCTE 35 events from a live stream

Unified Remix benefits from not only being able to create new SCTE 35 events (as described above) but also re-use any SCTE 35 events in your source media.

Remix VOD2Live can be incorporated into any existing Unified Remix - nPVR workflow where normally the remixed asset would be presented as a VOD clip, instead now can be presented VOD2Live.

An nPVR archive would store multiple clips over a given time-range that's been captured from a live channel. If the live channel is already conditioned with SCTE 35 based ad replacement opportunities, these would be present within the source clips when captured using unified_capture against the DASH presentation.

Below is an example of how existing SCTE 35 events can be re-used.

Capture the source stream

With a live stream running, we have identified a portion of the live event we would like to capture between 11:59:50 and 12:00:30. This existing live stream contains a SCTE 35 ad-replacement opportunity at 12:00:00.

So we capture the clip using unified_capture.

#!/bin/bash

unified_capture \
--remix \
-o captured-clip.mp4 \
"http://live.unified-streaming.com/scte35/scte35.isml/.mpd?vbegin=2021-04-07T11:59:50Z&vend=2021-04-07T12:00:30Z"

The SCTE 35 event capture can then be verified using mp4split:

#!/bin/bash

mp4split -v0 -o stdout:.xml captured-clip.mp4

Which returns:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?xml version="1.0" encoding="utf-8"?>
<!-- Created with Unified Streaming Platform  (version=1.11.0-24004) -->
<smil
  xmlns="http://www.w3.org/2001/SMIL20/Language">
  <body>
    <seq>
      <par>
        <EventStream
          xmlns="urn:mpeg:dash:schema:mpd:2011"
          schemeIdUri="urn:scte:scte35:2013:xml"
          timescale="1">
          <!-- 2021-04-07T12:00:00Z -->
          <Event
            presentationTime="1617796800"
            duration="19"
            id="917">
            <Signal
              xmlns="http://www.scte.org/schemas/35/2016">
              <SpliceInfoSection>
                <SpliceInsert
                  spliceEventId="917"
                  outOfNetworkIndicator="1"
                  spliceImmediateFlag="1"
                  uniqueProgramId="49152"
                  availNum="0"
                  availsExpected="0">
                  <Program>
                  </Program>
                  <BreakDuration
                    autoReturn="1"
                    duration="1710000" />
                </SpliceInsert>
              </SpliceInfoSection>
            </Signal>
          </Event>
        </EventStream>
      </par>
    </seq>
  </body>
</smil>

Remix the captured clip

We can now use captured-clip.mp4 as input to unified_remix using the below SMIL file to create remixed-clip.mp4. The stdout messaging from unifed_remix will signal the presence of a SCTE 35 with a statement Event Messages received.

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<smil xmlns="http://www.w3.org/2001/SMIL20/Language">
  <body>
    <seq>
        <video src="capture-clip.mp4" />
    </seq>
  </body>
</smil>
#!/bin/bash

unified_remix -o remixed-clip.mp4 remixed-clip.smil

Which will print:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
unified_remix version=1.11.0 (24004)    Copyright 2015-2021 CodeShop B.V.

I0.000 input: file:///data/remixed-clip.smil
I0.000 output: file:///data/remixed-clip.mp4
I0.027 Target track selection set:
I0.027 [1/2]: id=1 timescale=48000 lang=und
I0.027 soun/mp4a dref=1 bitrate=69000/69000 tag=255 samplerate=48000 channels=1 sample_size=16 packet_size=2
I0.027 [2/2]: id=2 timescale=90000 lang=und
I0.027 vide/avc1 dref=1 bitrate=700000/493000 size=1280x720 sar=1:1 dar=16:9 codecs=avc1.64001F
I0.028 event id=917 (scheme_id=urn:scte:scte35:2013:bin): presentationTime=00:00:10.000000(10/1) -> 00:00:08.405333(756480/90000)
I0.028 event id=917 (scheme_id=urn:scte:scte35:2013:bin): duration=00:00:19.000000(19/1) -> 00:00:19.200000(96/5)
I0.028 [1/2]: movie=00:00:00.000000
I0.028 [2/2]: movie=00:00:00.005333
I0.029 [1/2]: movie=00:00:40.000000
I0.029 [2/2]: movie=00:00:40.005333
I0.029 emsg[917] presentation_time=756480 duration=1728000/90000
I0.029 1 Event Messages received of which 1 are unique.
I0.029 stat: url=file:///data/remixed-clip.smil, reads=1, size=197 bytes
I0.029 stat: url=file:///data/captured-clip.mp4, reads=3, size=91 KB
I0.029 writing 5 buckets for a total of 21 KB
I0.067 total running time is 0.067135 seconds
Status: 200 FMP4_OK

Generate the server manifest

Next we create a VOD2Live server manifest with the required --timed_metadata and --splice_media options to support the signalling of SCTE 35 events in the client manifests.

The stdout from mp4split will signal the presence of a meta track contained in the source.

Where running:

#!/bin/bash

mp4split -o vod2live-remixed-clip.isml \
--vod2live \
--dvr_window_length=30 \
--archiving=false \
--hls.client_manifest_version=4 \
--hls.minimum_fragment_length=48/25 \
--timed_metadata --splice_media \
remixed-clip.mp4

Will print:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
mp4split version=1.11.0 (24004)    Copyright 2007-2021 CodeShop B.V.

I0.015 Manifest file:///data/vod2live-remixed-clip.isml
I0.030 Track 1:
I0.030 src=remixed-clip.mp4
I0.030 audio bitrate=69000 name=audio
I0.030 id=1 timescale=48000 lang=und
I0.030 soun/mp4a dref=1 bitrate=69000/69000 tag=255 samplerate=48000 channels=1 sample_size=16 packet_size=2
I0.030 soun/mp4a dref=2 (captured-clip.mp4) bitrate=69000/69000 tag=255 samplerate=48000 channels=1 sample_size=16 packet_size=2
I0.030 Track 2:
I0.030 src=remixed-clip.mp4
I0.030 video bitrate=700000/493000 name=video
I0.030 id=2 timescale=90000 lang=und
I0.030 vide/avc1 dref=1 bitrate=700000/493000 size=1280x720 sar=1:1 dar=16:9 codecs=avc1.64001F
I0.030 vide/avc1 dref=2 (captured-clip.mp4) bitrate=700000/493000 size=1280x720 sar=1:1 dar=16:9 codecs=avc1.64001F
I0.030 Track 3:
I0.030 src=remixed-clip.mp4
I0.030 meta bitrate=1000 name=meta
I0.030 id=3 timescale=375 lang=und
I0.030 scheme_id=urn:scte:scte35:2013:bin
I0.030 meta/urim dref=1 bitrate=1000/0
I0.032 writing 1 buckets for a total of 2390 bytes
I0.060 stat: url=file:///data/remixed-clip.mp4, reads=1, size=21 KB
I0.060 stat: url=file:///data/captured-clip.mp4, reads=1, size=20 KB
Status: 200 FMP4_OK

Request the VOD2Live client manifest

The 30second captured clip containing the existing SCTE 35 ad-replacement opportunities can now be played out VOD2Live in a continuous loop.

The example manifest below shows the previous SCTE 35 event being re-used as part of the VOD2Live stream. Where the necessary timing information for both the source clip and required presentationTime of the event have been realigned as part of the live stream.

Using mp4split to generate Origin output and print it to stdout from the command-line:

#!/bin/bash

mp4split -v0 -o stdout: vod2live-remixed-clip.isml/.mpd

Which will print the MPD:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
<?xml version="1.0" encoding="utf-8"?>
<!-- Created with Unified Streaming Platform  (version=1.11.0-24004) -->
<MPD
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="urn:mpeg:dash:schema:mpd:2011"
  xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
  type="dynamic"
  availabilityStartTime="1970-01-01T00:00:00Z"
  publishTime="2021-04-07T13:02:43.874153Z"
  minimumUpdatePeriod="PT2S"
  timeShiftBufferDepth="PT30S"
  maxSegmentDuration="PT3S"
  minBufferTime="PT10S"
  profiles="urn:mpeg:dash:profile:isoff-live:2011,urn:hbbtv:dash:profile:isoff-live:2012">
  <Period
    id="1"
    start="PT0S">
    <BaseURL>dash/</BaseURL>
    <EventStream
      schemeIdUri="urn:scte:scte35:2014:xml+bin"
      timescale="720000">
      <!-- 2021-04-07T13:02:06.384000Z -->
      <Event
        presentationTime="1164816378996480"
        duration="13824000"
        id="353014667">
        <Signal
          xmlns="http://www.scte.org/schemas/35/2016">
          <Binary>/DAgAAAAAAAAAP/wDwUAAAOVf//+ABoXsMAAAAAAACt+1iQ=</Binary>
        </Signal>
      </Event>
    </EventStream>
    <AdaptationSet
      id="1"
      group="1"
      contentType="audio"
      segmentAlignment="true"
      audioSamplingRate="48000"
      mimeType="audio/mp4"
      codecs="mp4a.40.2"
      startWithSAP="1">
      <AudioChannelConfiguration
        schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011"
        value="1" />
      <InbandEventStream
        schemeIdUri="urn:scte:scte35:2014:xml+bin">
      </InbandEventStream>
      <Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
      <SegmentTemplate
        timescale="48000"
        initialization="vod2live-remixed-clip-$RepresentationID$.dash"
        media="vod2live-remixed-clip-$RepresentationID$-$Time$.dash">
        <!-- 2021-04-07T13:02:13.978666Z / 1617800533 - 2021-04-07T13:02:44Z -->
        <SegmentTimeline>
          <S t="77654425630976" d="96256" r="2" />
          <S d="95232" />
          <S d="96256" />
          <S d="76800" />
          <S d="115712" />
          <S d="95232" />
          <S d="96256" r="2" />
          <S d="95232" />
          <S t="77654426783232" d="96256" r="2" />
        </SegmentTimeline>
      </SegmentTemplate>
      <Representation
        id="audio=69000"
        bandwidth="69000">
      </Representation>
    </AdaptationSet>
    <AdaptationSet
      id="2"
      group="2"
      contentType="video"
      par="16:9"
      segmentAlignment="true"
      width="1280"
      height="720"
      sar="1:1"
      frameRate="25"
      mimeType="video/mp4"
      codecs="avc3.64001F"
      startWithSAP="1">
      <InbandEventStream
        schemeIdUri="urn:scte:scte35:2014:xml+bin">
      </InbandEventStream>
      <Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
      <SegmentTemplate
        timescale="600"
        initialization="vod2live-remixed-clip-$RepresentationID$.dash"
        media="vod2live-remixed-clip-$RepresentationID$-$Time$.dash">
        <!-- 2021-04-07T13:02:14.063333Z / 1617800534 - 2021-04-07T13:02:44.468333Z -->
        <SegmentTimeline>
          <S t="970680320438" d="1152" r="11" />
          <S d="528" />
          <S t="970680334793" d="1584" />
          <S d="1152" r="1" />
        </SegmentTimeline>
      </SegmentTemplate>
      <Representation
        id="video=700000"
        bandwidth="700000"
        scanType="progressive">
      </Representation>
    </AdaptationSet>
  </Period>
  <UTCTiming
    schemeIdUri="urn:mpeg:dash:utc:http-iso:2014"
    value="https://time.akamai.com/?iso" />
</MPD>

Note

When capturing and re-using SCTE 35 events as part of an nPVR, AVOD or VOD2Live based workflow the same requirements apply.

Such as ensuring your source SCTE 35 event aligns with IDR video frames and/or segment boundaries. If not, remix will automatically update the desired presentationTime and duration to align the valid boundaries.

If the SCTE 35 event spans 2 archive clips, both clips need to be referenced as sources within the remix smil (necessary clipBegin or clipEnd timing can also be applied).