FAST-kanavat ansaitsevat rahaa mainoskatkoilla. Koko liiketoimintamalli perustuu yhteen oletukseen: kun kanava sanoo "siirry mainokseen," jokainen alavirran järjestelmä – mainospalvelin, SSAI-yhdyslaite, äly-TV-soitin – kuulee sen täsmälleen samalla hetkellä, täsmälleen samalla kestolla. SCTE-35 on standardiprotokolla, joka välittää tämän viestin. Jos sen tekee väärin hiljaisesti – ja hiljaisuus on oletusarvoinen virhetila – mainokset joko eivät renderöidy, käynnistyvät väärässä ruudussa tai kestävät väärän ajan. Katsoja näkee ilmoitustaulun. Tuloja ei vain synny.
Tämä on tekninen tarina siitä, kuinka mStudion FAST-kanavat lähettävät standardien mukaisia SCTE-35-viestejä operaattoriystävällisistä syötteistä, ja miksi rakensimme sen kolmella viestillä per katko yhden sijaan.
Lyhyt katsaus
| Ominaisuus | Yksityiskohta |
|---|---|
| Toimialue | SCTE-35-mainoskatkosignaalien tuottaminen AWS MediaLive FAST-kanaville |
| Operaattorin työnkulku | Ohjelmakohtainen mainoskatkoseditori – sijainti sekunteina, kesto sekunteina |
| Lähetetyt viestit per katko | Kolme – mainoksen alku TimeSignal, SpliceInsert, mainoksen loppu TimeSignal |
| Kestoa koskevat rajoitukset | 10–120 sekuntia, validoitu datakerroksessa |
| Alavirran kuluttajat | Esimerkkejä ovat soittimet, mainospalvelimet ja AWS MediaTailor (suunniteltu, mutta ei vielä kytketty). |
| Tila | SCTE-35-viestien lähetys tuotannossa; SSAI-integraatio suunnitteluvaiheessa |
Liiketoimintaongelma
Jokainen mainoskatko FAST-kanavalla on tulotapahtuma. Kanava lähettää merkin, joka sanoo "tähän tulee mainos, se kestää 30 sekuntia, ole hyvä ja valmistaudu." Alavirran järjestelmät – Google Ad Manager, AWS MediaTailor, alueelliset mainospalvelimet, äly-TV-soittimen SDK:t – lukevat tämän merkin ja päättävät, mitä yhdistetään.
Kun merkki on oikein, mainoskatko toimii moitteettomasti, näyttökerrat lasketaan ja operaattori saa maksun. Kun merkki on väärin – väärä kesto, väärä muoto, väärä formaatti – mainosjärjestelmä joko hylkää sen (mainosta ei näytetä) tai hyväksyy sen virheellisesti (vääränpituinen mainos tai mainos, joka menee yli seuraavaan ohjelmaan). Molemmat tulokset maksavat oikeaa rahaa, ja molemmat epäonnistuvat hiljaisesti. Kanava jatkaa suoratoistoa. Katsoja näkee ilmoitustaulun tai kömpelön leikkauksen. Monetisaatioputki tuottaa vain alhaisempia lukuja eikä virheilmoitusta, jota seurata.
Tekninen tavoite ei ole "tukea mainoksia." Se on: jokaisen operaattorin määrittelemän mainoskatkon on saavuttava jokaiselle alavirran kuluttajalle standardien mukaisena SCTE-35-signaalina, täsmälleen operaattorin valitsemassa ruudussa, joka kerta.
Mitä SCTE-35 todella on (90 sekunnin versio)
SCTE-35 on standardi viestien lisäämiseen videovirtaan. Viestit eivät sisällä mainossisältöä; ne sisältävät signaaleja – "mainoskatko alkaa tästä", "mainoskatko päättyy tähän", "tämä segmentti on N sekuntia pitkä." Alavirran järjestelmä lukee nämä signaalit ja toimii niiden mukaan: SSAI-kerros liittää oikean mainosaineiston HLS-manifestiin, äly-TV-soitin käynnistää peittokuvan, mainospalvelin kirjaa mainospaikan mahdollisuuden.
Kaksi viestityyppiä ovat olennaisia käyttötapauksessamme:
- SpliceInsert — alkuperäinen SCTE-35-viesti. Sisältää SpliceEventId:n, keston sekunteina ja "verkon ulkopuolinen" -lipun. Useimmat klassiset mainospalvelimet lukevat tämän.
- TimeSignal — uudempi, ilmeikkäämpi viesti. Sisältää SegmentationDescriptor:n ja SegmentationTypeId:n (52 = Provider Ad Start, 53 = Provider Ad End) sekä SegmentationDuration:n 90 000 tikkauksen yksiköissä. SSAI-järjestelmät ja modernit soittimet suosivat tätä muotoa, koska se yhdistyy selkeästi alku- ja loppupisteiden välillä.
Molempia muotoja pidetään oikeina SCTE-35-viesteinä. Eri alavirran kuluttajat suosivat eri muotoja. Vain yhden muodon lähettäminen jättää rahaa pöydälle (eli menettää tuloja).
Miksi tällä on merkitystä. Naiivi toteutus lähettää yhden SpliceInsert-viestin per mainoskatko ja pitää sitä valmiina. Mainoskatko toimii vanhoissa soittimissa ja epäonnistuu hiljaisesti SSAI:ssa. Puolet mainosinventaaristasi tuottaa tuloja; puolet ei. Et tiedä kumpi on kumpi, ennen kuin tulonumerosi ovat alhaiset.
Miksi naiivit lähestymistavat epäonnistuvat
Oikotiet ovat houkuttelevia, koska ne kaikki melkein toimivat.
- "Koodausaikaan lisää mainokset alkuperäiseen videoon." Ei joustovaraa. Operaattori ei voi A/B-testata sijoittelua, ei voi muuttaa mainoksia käyttöönoton jälkeen, ei voi näyttää alueellisia tai kohdennettuja mainoksia. Koko syy FAST-kanavien olemassaoloon on saman sisällön monetisaatio monella tavalla – mainosten polttaminen videoon koodausvaiheessa estää tämän.
- "Hyödynnä asiakaspuolen mainosten syöttöä." Mainosten estäminen on helppoa. Eri koodipolku laitekohtaisesti. Ei palvelinpuolen personointia. Ja se ohittaa SSAI:n kokonaan, mikä tarkoittaa alhaisempia CPM:iä.
- "Lähetä vain yksi SpliceInsert per katko." Yleisin tuotantovirhe. Toimii joissakin soittimissa, mutta SSAI-järjestelmät, jotka haluavat TimeSignal-viestien parittavan alku- ja loppupisteet, jättävät sen hiljaisesti huomiotta. Osittainen monetisaatio, ilman tutkittavaa virhettä.
- "Ilmaise kaikki 90 kHz:n tikkausyksiköissä, koska speksi mainitsee ne." Speksi on ärsyttävämpi kuin miltä kuulostaa. SpliceInsert.Duration on sekunteina. SegmentationDuration on 90 kHz:n tikkausyksiköissä. Niiden sekoittaminen tuottaa viestejä, jotka läpäisevät skeemavalidoinnin ja lähtevät eteenpäin, mutta epäonnistuvat sitten soittimessa virheellisinä kestoina. Kooderi ei havaitse sitä. Soitin vain ohittaa katkon.
- "Anna MediaLiven vahvistaa." Se ei tee niin. MediaLive hyväksyy päällekkäiset katkot, nollakestoiset katkot ja mahdottomat segmentoinnin kestot valittamatta. Vahvistuksen on tapahduttava ennen kuin MediaLive näkee toimenpiteen.
Vipuvarsi, joka meillä oli, oli raja operaattorin käyttöliittymän – jossa mainoskatkot ovat vain {sijainti, kesto}-pareja – ja MediaLive-aikataulun välillä, jossa jokaisen viestin on oltava täydellinen.
Ratkaisumme
Käsittele mainoskatkoa ensiluokkaisena tieto-objektina päästä päähän. Operaattori määrittelee sen mahdollisimman yksinkertaisesti. Taustaohjelma validoi sen kerran skeemakerroksessa. Lambda muuntaa sen kolmen viestin pinoksi käyttöönoton yhteydessä, kunkin viestin ilmaistuna sen oman speksin vaatimassa aikakannassa. Mikään muu pinossa ei tarvitse tietää SCTE-35:stä – käännös sijaitsee yhdessä funktiossa, samassa Lambdassa, joka vastaa kaikista muista aikataulutoiminnoista.
Kaavio 1 · Päästä päähän -mainosmerkkiputki

Arkkitehtuuri
- Frontend-mainoskatkoseditori — operaattorit lisäävät mainoskatkoja ohjelmakohtaisesti määrittämällä sijaintisiirtymän (sekuntia ohjelman alusta) ja keston (sekuntia). Puskuripaikat ovat osa datamallia ja valmiina toistokerrosta varten.
- AdMarker -kokoelma (MongoDB) — yksi dokumentti per ohjelma mainoskatkoineen, viitaten videoon. adBreaks[]-taulukko tallentaa {sijainti, kesto}-pareja Mongoose-kirjaston valvoessa 10 ≤ kesto ≤ 120 tallennuksen yhteydessä. Puskurit sisältävät adBreakId-viittauksen alavirran paritusta varten.
- NestJS backend (schedule.service.ts) — käyttöönoton yhteydessä yhdistää jokaisen aikataulun sen AdMarker-objektiin ja nimeää kentät uudelleen Lambdan sopimuksen mukaiseksi (position → offsetSeconds, duration → durationSeconds). Yksi massahaku, ei N+1-ongelmaa.
- Lambda-orkestroija (fastChannel-lambda-fun/index.js) — omistaa SCTE-35-käännöksen. Jokaiselle mainoskatkolle se lähettää kolmen viestin pinon samaan BatchUpdateScheduleCommand-komentoon, joka sisältää syötteen vaihdot ja vesileimat. Toimintojen nimet versioidaan ohjelmakohtaisesti, jotta orpojen poisto voi yhdistää ne osittaisen käyttöönoton jälkeen.
- AWS MediaLive — vastaanottaa toiminnot, lähettää #EXT-SCTE35-merkkejä HLS-manifestiin operaattorin valitsemalla sekunnilla.
Tärkeimmät tekniset päätökset
1. Kolme viestiä mainoskatkoa kohti, ei yksi
Jokainen mainoskatko lähettää kolme erillistä toimintoa ohjelman samaan loogiseen hetkeen.
Kaavio 2 · Yhden mainoskatkon elinkaari

Alun ja lopun TimeSignal-viestit jakavat SegmentationUpid:n, jotta alavirran järjestelmät voivat yhdistää ne deterministisesti. SpliceInsert-viesti sisältää ainutlaatuisen SpliceEventId:n soittimen tason duplikaattien poistamiseksi. Eri kuluttajat lukevat eri viestejä. Kaikkien kolmen lähettäminen kattaa kaikki sopimukset, joista välitämme tänään ja kaikki uskottavat tulevaisuudessa.
Yleinen tuotantovirhe. Lähetä yksi SpliceInsert-viesti ja oleta, että muu ekosysteemi hoitaa loput. SSAI-järjestelmät pudottavat hiljaisesti katkot, joista puuttuvat vastaavat TimeSignal-viestit; klassiset mainospalvelimet jättävät TimeSignal-vain signaalit huomiotta. Ilman kaikkia kolmea, osa alavirran pinostasi monetoioi jokaisen mainoskatkon ja loput jättävät sen väliin – ja saat tiedon tuloraportista, et lokeista.
2. Kaksi aikakantaa, yhdessä funktiossa sovitettuina
SpliceInsert.Duration on sekunteina. SegmentationDuration TimeSignal-kuvaajan sisällä on 90 000 tikkauksen yksiköissä. Sama looginen kesto, kaksi koodausta – ja yleisin SCTE-35-bugi kentällä on niiden sekoittaminen.
Kaavio 3 · Ajanmuunnoslogiikka

Muunnos sijaitsee buildProgramActions-funktiossa ja vain siellä. On yksi kanoninen paikka tarkistaa, jos viestin kesto menee pieleen, ja yksi paikka muuttaa, jos speksi kehittyy.
Tietoinen kompromissi, jonka teimme. Olisimme voineet tallentaa molemmat aikakannat AdMarker-dokumenttiin ja antaa Lambdan kopioida ne läpi. Emme tehneet sitä tarkoituksella: vain sekuntiarvon tallentaminen tarkoittaa, että operaattorilla on vain yksi asetettava numero, yksi numero validoitavaksi ja vain yksi numero, joka voi olla väärä. 90 kHz:n arvo on johdettu, ei koskaan tallennettu. Johdettu data ei voi ajautua.
3. Sijainti on suhteellinen, käynnistysaika on absoluuttinen
Operaattori sanoo "mainoskatko 720 sekunnin kohdalla ohjelmasta." Lambda laskee todellisen UTC-käynnistysajan kaavalla programStartTime + offsetSeconds × 1000 ja leimaa sen toimintoon. Kaikki muut aikataulutoiminnot – syötteen vaihto, vesileima päälle, ohjelman loppu – käyttävät samaa siirtymä-aikaleima-putkea. Mainosviestit osuvat samoihin ruutujen rajoihin kuin kaikki muukin, ilman epäselvyyttä siitä, mikä kello omistaa aikajanan.
4. Validointi datakerroksessa, ei siirtokerroksessa
AdMarker-skeema valvoo keston ∈ [10, 120] sekuntia Mongoose-tallennuksen yhteydessä. Rajojen ulkopuolinen katko ei koskaan pääse Lambdaan. Mainoskatkot, jotka ulottuisivat ohjelman loppupisteen yli, katkaistaan rakennusvaiheessa sen sijaan, että ne hylättäisiin – operaattorit eivät menetä työtään yhden huonon katkon takia. Virhetyypit, joita ei voi tapahtua, ovat mielenkiintoisempia kuin ne, jotka voivat.
5. Viestien lähetys irrotettu SSAI:sta
Tänään toimitamme signaalikerroksen. Palvelinpuolen mainosten upottaminen AWS MediaTailorin kautta – joka kuluttaisi näitä viestejä liittääkseen todellisia mainosaineistoja HLS-manifestiin – on täysin suunniteltu, mutta ei vielä kytketty. Tarkoituksellinen järjestys: saata viestikerros ensin oikein, tuotannossa, todellisten kanavien käyttämänä, ennen SSAI:n käyttöönottoa. Kun integraatio otetaan käyttöön, viestit ovat jo siellä. Alavirran järjestelmä saa puhtaan sopimuksen kulutettavaksi heti alusta alkaen.
Miksi tällä järjestyksellä on merkitystä. SSAI:n virheenjäljitys on armotonta, kun viestisi ovat vääriä, koska jokainen virhe näyttää SSAI-virheeltä, vaikka viestit olisivat syyllisiä. Toimittamalla viestikerroksen ensin erillään ja validoimalla sen todellisia soittimia ja mainospalvelimia vastaan, poistimme kokonaisen luokan integraatioon liittyviä sekaannuksia ennen kuin ne ehtivät syntyä.
Tulokset
- Jokainen operaattorin määrittelemä mainoskatko lähettää standardien mukaisen kolmen viestin SCTE-35-pinon kanavan HLS-manifestiin – oikealla sekunnilla, oikeaan aikakantaan.
- Käännöskerros sijaitsee yhdessä funktiossa. Speksimuutokset tai uudet alavirran kuluttajat vaativat yhden tiedoston muutoksen, eivät etsintää koko koodikannasta.
- Keston validointi suoritetaan datakerroksessa, ennen kuin yksikään viesti pääsee kooderiin. Operaattorin virheet ilmenevät käyttöliittymässä, eivät hiljaisesti lähetysaikana – virheelliset viestit eivät voi päästä MediaLiveen.
- Viestien luominen on determinististä: identtinen operaattorin syöte tuottaa identtiset SCTE-35-toiminnot, joten sama katko käyttäytyy samalla tavalla jokaisessa käyttöönotossa ja jokaisessa kanavassa.
- Signaalikerros on toimitettu ja käytössä. SSAI-kuluttaja (MediaTailor) on suunniteltu ja valmiina kytkettäväksi – ja kun se kytketään, jokaisen olemassa olevan kanavan viestit ovat jo siellä odottamassa.
Teknologiapino: AWS MediaLive · AWS Lambda · NestJS · MongoDB · TypeScript · Node 18 · SCTE-35 (Scte35TimeSignalSettings, Scte35SpliceInsertSettings) · AWS SDK v3

