Saluran FAST menjana wang daripada rehat komersial. Keseluruhan model perniagaan bergantung pada satu andaian: apabila saluran menyatakan "masuk iklan," setiap sistem hiliran yang mendengar — ad server, SSAI splicer, smart-TV player — mendengarnya pada saat yang sama, dengan tempoh yang sama. SCTE-35 ialah protokol standard yang membawa mesej itu. Jika ia tersalah secara senyap — dan senyap ialah mod kegagalan lalai — iklan sama ada tidak dipaparkan, dicetuskan pada bingkai yang salah, atau berlangsung pada tempoh yang salah. Penonton melihat paparan kosong. Hasil pendapatan tiada di sana.
Ini adalah kisah kejuruteraan tentang bagaimana saluran FAST mStudio mengeluarkan isyarat SCTE-35 yang mematuhi piawaian daripada input yang mesra operator, dan mengapa kami membangunkannya sebagai tiga isyarat bagi setiap rehat dan bukannya satu.
Gambaran pantas
| Aspek | Perincian |
|---|---|
| Domain | Pensinyalan ad-break SCTE-35 untuk saluran FAST AWS MediaLive |
| Aliran kerja operator | Editor ad break setiap program — kedudukan dalam saat, tempoh dalam saat |
| Isyarat yang dikeluarkan setiap rehat | Tiga — ad-start TimeSignal, SpliceInsert, ad-end TimeSignal |
| Had tempoh | 10–120 saat, disahkan pada lapisan data |
| Pengguna hiliran | Pemain, ad server, dan AWS MediaTailor (direka tetapi belum disambungkan) adalah contoh. |
| Status | Pengecualian isyarat SCTE-35 dalam pengeluaran; integrasi SSAI dalam reka bentuk |
Masalah Perniagaan
Setiap rehat komersial di saluran FAST adalah peristiwa penjanaan pendapatan. Saluran mengeluarkan penanda yang menyatakan "iklan akan dipaparkan di sini, ia akan berlangsung selama 30 saat, sila bersedia." Sistem hiliran — Google Ad Manager, AWS MediaTailor, ad server serantau, smart-TV player SDK — membaca penanda tersebut dan memutuskan apa yang perlu disisipkan.
Apabila penanda adalah betul, ad break berjalan lancar, tayangan dikira, dan operator dibayar. Apabila penanda salah — tempoh salah, bentuk salah, format salah — sistem iklan sama ada menolaknya (tiada iklan disiarkan) atau menerimanya secara tidak betul (iklan dengan tempoh yang salah, atau yang melangkau ke program seterusnya). Kedua-dua hasil ini menelan belanja yang besar, dan kedua-duanya gagal secara senyap. Saluran terus menstrim. Penonton melihat paparan kosong atau potongan yang janggal. Saluran monetisasi hanya menghasilkan angka yang lebih rendah dan tiada mesej ralat untuk dijejaki.
Matlamat kejuruteraan bukanlah "menyokong iklan." Ia adalah: setiap ad break yang ditetapkan oleh operator mesti sampai kepada setiap pengguna hiliran sebagai isyarat SCTE-35 yang mematuhi piawaian, pada bingkai tepat yang dipilih oleh operator, setiap masa.
Apa Sebenarnya SCTE-35 Itu (Versi 90-Saat)
SCTE-35 adalah piawaian untuk menyisipkan mesej isyarat ke dalam aliran video. Isyarat-isyarat tersebut tidak membawa kandungan iklan; ia membawa isyarat — "ad break bermula di sini," "ad break berakhir di sini," "segmen ini sepanjang N saat." Sistem hiliran membaca isyarat-isyarat tersebut dan bertindak ke atasnya: lapisan SSAI menyisipkan kreatif iklan sebenar ke dalam HLS manifest, smart-TV player mencetuskan tindanan, ad server merekod peluang slot.
Dua bentuk isyarat penting untuk kes penggunaan kami:
- SpliceInsert — isyarat SCTE-35 yang asal. Membawa SpliceEventId, tempoh dalam saat, dan bendera "out of network". Kebanyakan ad server klasik membaca ini.
- TimeSignal — isyarat yang lebih baru dan lebih ekspresif. Membawa SegmentationDescriptor dengan SegmentationTypeId (52 = Provider Ad Start, 53 = Provider Ad End) dan SegmentationDuration dalam unit 90,000-tick. Sistem SSAI dan pemain moden lebih suka bentuk ini kerana ia berpasangan dengan bersih antara mula dan akhir.
Kedua-dua bentuk adalah SCTE-35 yang betul. Pengguna hiliran yang berbeza memilih yang berbeza. Mengeluarkan hanya satu bentuk akan menyebabkan kehilangan potensi pendapatan.
Mengapa ini penting. Implementasi yang naif mengeluarkan satu SpliceInsert bagi setiap ad break dan menganggapnya selesai. Ad break berfungsi pada pemain legasi dan gagal secara senyap pada SSAI. Separuh daripada inventori iklan anda menjana pendapatan; separuh lagi tidak. Anda tidak akan tahu yang mana satu sehingga angka pendapatan anda rendah.
Mengapa Pendekatan Naif Gagal
Jalan pintas itu menarik kerana kesemuanya hampir berfungsi.
- "Pada masa pengekodan, sisipkan iklan ke dalam video asal." Tiada ruang untuk fleksibiliti. Operator tidak boleh menguji penempatan A/B, tidak boleh menukar iklan selepas penggunaan, tidak boleh menjalankan iklan sasaran serantau atau audiens. Seluruh sebab saluran FAST wujud adalah untuk menjana pendapatan daripada kandungan yang sama dalam pelbagai cara — memasukkan iklan pada masa pengekodan menghalang perkara itu.
- "Manfaatkan penyisipan iklan sisi klien." Penyekat iklan adalah mudah. Laluan kod yang berbeza bagi setiap peranti. Tiada pemperibadian sisi pelayan. Dan ia memintas SSAI sepenuhnya, yang bermaksud CPM yang lebih rendah.
- "Hanya mengeluarkan satu SpliceInsert bagi setiap rehat." Kesilapan pengeluaran yang paling biasa. Berfungsi pada beberapa pemain, diabaikan secara senyap oleh sistem SSAI yang mahukan isyarat TimeSignal untuk memadankan permulaan/akhir. Monetisasi separa, tanpa ralat untuk disiasat.
- "Nyatakan semuanya dalam 90 kHz tick kerana spesifikasi menyebutnya." Spesifikasi lebih menyusahkan daripada itu. SpliceInsert.Duration adalah dalam saat. SegmentationDuration adalah dalam 90 kHz tick. Mencampurkan kedua-duanya menghasilkan isyarat yang lulus pengesahan skema dan dikeluarkan, kemudian gagal pada pemain sebagai tempoh yang tidak betul. Pengekod tidak akan menangkapnya. Pemain hanya melangkau rehat tersebut.
- "Benarkan MediaLive untuk mengesahkan." Ia tidak akan berbuat demikian. MediaLive menerima rehat yang bertindih, rehat tempoh sifar, dan tempoh segmentasi yang mustahil tanpa aduan. Pengesahan perlu dilakukan sebelum MediaLive melihat tindakan tersebut.
Tuil yang kami miliki adalah sempadan antara UI operator — di mana ad break hanyalah pasangan {position, duration} — dan jadual MediaLive, di mana setiap isyarat mestilah sempurna.
Penyelesaian Kami
Anggap ad break sebagai objek data kelas pertama dari hujung ke hujung. Operator menentukannya dalam istilah yang paling mudah. Backend mengesahkannya sekali pada lapisan skema. Lambda menterjemahkannya ke dalam timbunan tiga isyarat pada masa penggunaan, dengan setiap isyarat dinyatakan dalam asas masa yang dikehendaki oleh spesifikasi masing-masing. Tiada yang lain dalam timbunan perlu tahu tentang SCTE-35 — terjemahan berada dalam satu fungsi, dalam Lambda yang sama yang memiliki setiap tindakan jadual yang lain.
Rajah 1 · Saluran Paip Penanda Iklan Hujung ke Hujung

Seni Bina
- Editor ad-break Frontend — operator menambah ad break setiap program dengan menyatakan offset kedudukan (saat dari permulaan program) dan tempoh (saat). Slot bumper adalah sebahagian daripada model data dan sedia untuk lapisan playout.
- AdMarker collection (MongoDB) — satu dokumen bagi setiap program dengan ad break, merujuk kepada video. Array adBreaks[] menyimpan {position, duration} dengan Mongoose menguatkuasakan 10 ≤ duration ≤ 120 pada masa simpan. Bumper membawa rujukan adBreakId untuk padanan hiliran.
- NestJS backend (schedule.service.ts) — pada masa penggunaan, menyertai setiap jadual kepada AdMarkernya dan menamakan semula medan kepada kontrak Lambda (position → offsetSeconds, duration → durationSeconds). Satu pengambilan pukal, tiada N+1.
- Lambda orchestrator (fastChannel-lambda-fun/index.js) — memiliki terjemahan SCTE-35. Bagi setiap ad break, mengeluarkan timbunan tiga isyarat ke dalam BatchUpdateScheduleCommand yang sama yang membawa suis input dan tanda air. Nama tindakan adalah berversi bagi setiap program supaya pembersihan yatim piatu boleh memadankannya selepas penggunaan separa.
- AWS MediaLive — menerima tindakan, mengeluarkan penanda #EXT-SCTE35 dalam HLS manifest pada saat yang dipilih oleh operator.
Keputusan Kejuruteraan Utama
1. Tiga isyarat bagi setiap ad break, bukan satu
Setiap ad break mengeluarkan tiga tindakan diskrit terhadap detik logik yang sama dalam program.
Rajah 2 · Kitar Hayat Ad Break Tunggal

Isyarat TimeSignal mula dan akhir berkongsi SegmentationUpid supaya sistem hiliran dapat memadankannya secara deterministik. SpliceInsert membawa SpliceEventId yang unik untuk deduplikasi peringkat pemain. Pengguna yang berbeza membaca isyarat yang berbeza. Mengeluarkan ketiga-tiganya merangkumi setiap kontrak yang kami ambil berat hari ini dan setiap kontrak yang munasabah esok.
Kesilapan pengeluaran biasa. Mengeluarkan satu SpliceInsert dan menganggap ekosistem lain akan menyelesaikannya. Sistem SSAI secara senyap menggugurkan rehat yang tidak mempunyai isyarat TimeSignal yang sepadan; ad server klasik mengabaikan isyarat TimeSignal-sahaja. Tanpa ketiga-tiganya, setiap ad break dimonetisasi oleh sebahagian daripada timbunan hiliran anda dan terlepas oleh yang lain — dan anda mengetahuinya dari laporan pendapatan, bukan log.
2. Dua asas masa, diselaraskan dalam satu fungsi
SpliceInsert.Duration adalah dalam saat. SegmentationDuration di dalam deskriptor TimeSignal adalah dalam unit 90,000-tick. Tempoh logik yang sama, dua pengekodan — dan bug SCTE-35 yang paling biasa ditemui adalah mencampuradukkan keduanya.
Rajah 3 · Logik Penukaran Masa

Penukaran berada dalam buildProgramActions dan hanya di sana. Terdapat satu tempat kanonikal untuk melihat apabila tempoh isyarat tersilap, dan satu tempat untuk diubah jika spesifikasi berubah.
Pertukaran yang sengaja kami lakukan. Kami boleh menyimpan kedua-dua asas masa pada dokumen AdMarker dan membiarkan Lambda menyalinnya. Kami sengaja tidak berbuat demikian: menyimpan hanya nilai saat bermakna hanya ada satu nombor untuk ditetapkan oleh operator, hanya satu nombor untuk disahkan, dan hanya satu nombor yang boleh salah. Nilai 90 kHz adalah terbitan, tidak pernah disimpan. Data terbitan tidak boleh melayang.
3. Kedudukan adalah relatif, masa pencetus adalah mutlak
Operator berkata "ad break pada 720 saat ke dalam program." Lambda mengira masa pencetus UTC sebenar sebagai programStartTime + offsetSeconds × 1000 dan menetapkannya pada tindakan tersebut. Setiap tindakan jadual lain — suis input, tanda air aktif, tamat program — menggunakan saluran paip offset-ke-timestamp yang sama. Isyarat iklan mendarat pada sempadan bingkai yang sama seperti yang lain, tanpa kekaburan tentang jam mana yang memiliki garis masa.
4. Pengesahan pada lapisan data, bukan wayar
Skema AdMarker menguatkuasakan duration ∈ [10, 120] saat pada masa simpan Mongoose. Rehat di luar julat tidak pernah sampai ke Lambda. Ad break yang akan melebihi akhir program dipotong pada masa pembinaan dan bukannya ditolak — operator tidak kehilangan kerja mereka kerana satu rehat yang buruk. Jenis pepijat yang tidak boleh berlaku lebih menarik daripada yang boleh berlaku.
5. Pengeluaran isyarat dipisahkan daripada SSAI
Apa yang kami sediakan hari ini adalah lapisan pensinyalan. Penyisipan iklan sisi pelayan melalui AWS MediaTailor — yang akan menggunakan isyarat-isyarat ini untuk menyisipkan kreatif iklan sebenar ke dalam HLS manifest — telah direka sepenuhnya dan belum disambungkan. Urutan yang disengajakan: dapatkan lapisan isyarat betul dahulu, dalam pengeluaran, digunakan oleh saluran sebenar, sebelum mengaktifkan SSAI. Apabila integrasi diaktifkan, isyarat-isyarat sudah tersedia. Sistem hiliran mendapat kontrak yang bersih untuk digunakan dari hari pertama.
Mengapa susunan ini penting. Penyahpepijatan SSAI sangat sukar apabila isyarat anda salah, kerana setiap kegagalan kelihatan seperti kegagalan SSAI walaupun isyarat yang bersalah. Dengan menyediakan lapisan isyarat secara berasingan dahulu dan mengesahkannya terhadap pemain dan ad server sebenar, kami menghapuskan seluruh kategori kekeliruan integrasi sebelum ia berlaku.
Hasil
- Setiap ad break yang ditetapkan oleh operator mengeluarkan timbunan tiga isyarat SCTE-35 yang mematuhi piawaian dalam HLS manifest saluran — pada saat yang betul, berbanding asas masa yang betul.
- Lapisan terjemahan berada dalam satu fungsi. Perubahan spesifikasi atau pengguna hiliran baharu adalah perubahan satu fail, bukan pencarian merentasi codebase.
- Pengesahan tempoh berjalan pada lapisan data, sebelum sebarang isyarat mencapai pengekod. Kesilapan operator muncul dalam UI, bukan secara senyap pada waktu siaran — isyarat yang tidak betul tidak boleh mencapai MediaLive.
- Penjanaan isyarat adalah deterministik: input operator yang sama menghasilkan tindakan SCTE-35 yang sama, jadi rehat yang sama berkelakuan sama di setiap penggunaan dan setiap saluran.
- Lapisan pensinyalan telah dihantar dan beroperasi. Pengguna SSAI (MediaTailor) telah direka dan sedia untuk disambungkan — dan apabila ia disambungkan, isyarat setiap saluran sedia ada akan berada di sana menunggunya.
Timbunan Teknologi: AWS MediaLive · AWS Lambda · NestJS · MongoDB · TypeScript · Node 18 · SCTE-35 (Scte35TimeSignalSettings, Scte35SpliceInsertSettings) · AWS SDK v3

