MicrocosmWorksІнновації та архітектура цифрового космосу
Про насКонтакт
MicrocosmWorksІнновації та архітектура цифрового космосу

Надаємо IT-рішення, які мають значення. Ми захоплені технологіями, безпекою та допомогою бізнесу зростати завдяки надійній, інноваційній IT-інфраструктурі.

[email protected]
+91 7011868196
New Delhi, India

Центр зростання AI

AI HubІнновації для стартапівПрискорювач для підприємств

Рішення

Всі рішенняДодатки для здоров'я та фітнесуAI відео платформаРозробка AI агентів

Ресурси

ІнсайтиГалузеві ПосібникиШаблони ВикористанняАрхітектурні ШаблониКейси

Компанія

Про НасКонтактНаша Робота

Послуги

Цифровий КонсалтингХмарна ІнфраструктураРозробка SaaSРозробка AIВідео Технології
Розробка ERPНалаштування ZohoРозробка OdooІнтеграція SalesforceРозробка Користувацьких CRM
Інтеграція QuickBooksРішення IoTРозробка Блокчейну
Консалтинг з КібербезпекиІТ Підтримка - L3

© 2026 MicrocosmWorks. Усі права захищено.

Політика КонфіденційностіУмови Обслуговування
Назад до інсайтів
Cloud Solutions

One Input, Multiple FAST Channel Programs

Driving several scheduled programs from a single MediaLive input without spinning up duplicate channels or inputs.

Untitled (612 x 640 px) (512 x 640 px) (512 x 600 px).webpPankaj
•
July 15, 2026
•
5 min read
Illustration showing one media input powering multiple FAST channel programs through cloud-based automation and live streaming workflows. (1).webp
5 min read

One Input, Hundreds of Programs — Running 24/7 FAST Channels on MediaLive

A 24/7 FAST channel plays hundreds of unique programs a day, every day, forever. AWS MediaLive caps a channel at 20 input attachments. The naive design — one input per video — runs out of slots before lunch and forces a channel restart that takes the live stream offline. We solved this with one dynamic input that serves every program the channel will ever play, and a layer of program-level orchestration on top that keeps the timeline self-healing across deploys, partial failures, and operator edits.

This is the engineering story of how that orchestration actually works.

Quick overview

AspectDetail
Domain24/7 FAST channel orchestration on AWS MediaLive
Input attachments per channel1 dynamic + 1 slate (+ optional SRT) — well under the 20-input cap
Per-program identity8-byte hex programId embedded in every action name
Slate fill thresholdGaps ≥ 6 seconds get a slate-switch action
Schedule capacity1500 actions per channel (AWS hard limit, preflighted)
Self-healingOrphan-action sweep runs after every deploy
StatusIn production

The Business Problem

A FAST channel is a 24/7 service. Operators schedule a full week or month of unique videos in advance, and the channel has to play each one at the right second — switch sources cleanly, hold the watermark steady, emit ad-break cues, fill any gaps with a station-branded slate. The viewer should never see a black frame, a stuck logo, or last week's program looping.

That orchestration has to survive everything operators do to it: editing tomorrow's lineup, adding ad breaks mid-week, redeploying after a single failed program, racing two clicks of Deploy. The system either lands every change atomically against the live channel or recovers cleanly. "The channel is now in a state nobody understands" is not an acceptable outcome on infrastructure that's airing live.

A 60-Second MediaLive Primer

AWS MediaLive is a long-running cloud encoder. You give it one or more inputs (source streams or file URLs) and a schedule of timed actions — switch to this input, turn this overlay on, insert this cue. The encoder runs forever, executing actions at their scheduled timestamps and emitting an HLS manifest the viewer's player consumes.

Two AWS limits shape everything downstream:

  • 20 input attachments per channel. Hard limit. A "Top 20 movies" channel naively designed with one input per video fills the cap on movie 21.
  • 1500 schedule actions per channel. Also a hard limit. Each program is several actions (input switch, watermark per rendition, ad cues, slate switch), so the real ceiling is closer to a few hundred programs at any one time.

Both limits matter for a 24/7 channel that's expected to play unique content indefinitely.

Why Naive Approaches Fail

The obvious paths each break in different ways:

  • "One input per program." completes the first day's 20-attachment cap. Adding more requires recreating the channel — and channel recreation takes 60–90 seconds during which the live stream is gone. Unacceptable on a 24/7 service.
  • "Recreate the channel for every deploy." Same problem, every deploy. Viewers experience an outage every time programming changes. This is not a real option for a channel that's supposed to be live.
  • "Pre-encode the entire week into one giant looping file." Kills the editing model. Want to reorder tomorrow? Re-encode the whole week. Want to insert an ad? Re-encode. The whole reason FAST channels work as a business is dynamic programming and per-break ad insertion — burning everything into a single file forecloses on both.
  • "Run multiple channels in parallel." Needs the player to switch between them, multiplies the cost of AWS, and breaks up the audio, MediaPackage, and CDN pipeline. Doesn't solve the problem so much as multiply it.

The lever we had was a single AWS-documented feature — the $urlPath$ placeholder on a dynamic input — and the freedom to build whatever orchestration we wanted on top of it.

Why this matters. The trick isn't using $urlPath$. AWS documents it. The trick is building a self-healing orchestration layer on top of it that survives partial deploys, operator edits, and concurrent retries — without ever putting the live channel into a state nobody can describe from the UI.

Our Solution

One MediaLive channel. One dynamic input linked to the exact URL $urlPath$. One slate input for gap fills. At every program boundary, an InputSwitchScheduleActionSettings action overrides the dynamic input's URL with that program's actual S3 path. The channel never needs a new input attachment, never needs a restart, never goes offline.

The interesting work is the orchestration layer that runs on top of that one input — naming every action with a program ID so orphans can be cleaned up after a failure, filling gaps ≥ 6 seconds with a slate so the viewer never sees a hold-frame, activating the watermark a measured moment after every input switch so the overlay doesn't strobe through buffering frames, and preflighting against the 1500-action ceiling so deploys fail in the UI instead of mid-flight on AWS.

Diagram 1 · Channel ArchitecturePasted image.webp

Architecture

  • Slate input — a static asset attached to the channel for filling gaps between programs.
  • Dynamic input — created once with Sources: [{ Url: "$urlPath$" }], Type: MP4_FILE. The URL is a placeholder; the actual path is supplied per program at schedule time.
  • Lambda orchestrator (fastChannel-lambda-fun/index.js) — owns each activity that appears on the channel. Generates an 8-byte hex programId per program and tags every related action with it.
  • MediaLive schedule — a single ordered list of actions, all flowing through one BatchUpdateScheduleCommand. Capped at 1500 actions by AWS.
  • Backend preflight (schedule.service.ts) — calls Lambda's GET_SCHEDULE_COUNT before every deploy and refuses to proceed if the new actions would exceed the cap.
  • Orphan sweep (sweepIncompleteProgramGroups) — runs after every deploy. Groups actions by programId, deletes any group missing its anchor input-switch action.

Key Engineering Decisions

1. One dynamic input, one URL override per program

The dynamic input is created with Sources: [{ Url: "$urlPath$" }]. At each program boundary, the Lambda emits an InputSwitchScheduleActionSettings action that supplies UrlPath: [program.videoUrl] — the actual S3 URL of that program's MP4. MediaLive substitutes the placeholder at execution time and pulls from the real source.

One input attachment now serves every program the channel will ever play — effectively unlimited unique videos over the channel's lifetime, bounded only by the per-deploy schedule-action limit at any single point in time. The 20-input cap stops being a constraint, and the channel never needs a restart to add new content.

Diagram 2 · Dynamic Input URL Override

Pasted image (2).webp
 

Tradeoff we intentionally made. A dynamic input doesn't pre-validate the URL — MediaLive only resolves the placeholder at switch time, so a 404 surfaces as a stream-side error rather than a deploy-time rejection. We accept that cost in exchange for the architectural simplicity of one input. The backend's separate ffprobe validation catches malformed sources before deploy.

2. Program-tagged action names enable self-healing

Every action emitted by the Lambda carries the program's 8-byte hex programId in its name: input-switch-${programId}, watermark-on-${programId}-${rendition}, ad-break-start-${programId}-${i}, program-end-${programId}, slate-switch-${programId}.

After every deploy, sweepIncompleteProgramGroups lists every action currently on the channel, groups them by their embedded programId, and deletes any group whose anchor input-switch action is missing. That's the cleanup path for failed partial deploys, racy edits, and any other condition that could leave the channel with half a program's actions stranded.

The action-name encoding is the entire identity mechanism. MediaLive itself has no concept of a "program" — the orchestration layer projects one onto it via naming conventions.

Why this matters. Without the program ID embedded in every action name, the orphan sweep would have no way to know which actions belong together. Action-level cleanup would either delete too much (whole channel reset) or too little (stranded watermarks that never turn off). The naming convention is the data model.

3. The 6-second slate rule

Programs rarely abut perfectly — there's almost always a gap of a few seconds between the end of one MP4 and the start of the next scheduled program. The orchestration emits a slate-switch action whenever that gap is ≥ 6 seconds (MIN_SLATE_GAP_MS = 6000).

The threshold is not arbitrary. MediaLive enforces a 5-second minimum spacing between any two schedule actions; emitting a slate-switch closer than that to the next program's input-switch produces a rejection. The 6-second rule gives MediaLive its required gap and leaves the orchestration layer one second of clock-drift safety margin. Under 6 seconds, we let the prior program's last frame freeze briefly rather than risk a deploy rejection.

4. Per-rendition watermark with measured activation delay

The watermark is a StaticImageOutputActivate action emitted per output rendition (1080p, 720p, 480p, 360p) — four actions per program. Each action fires 1,500 ms after that program's input-switch.

The delay exists because the first frames after an input switch are still buffering; activating the overlay at the exact switch moment can produce a brief flicker as the overlay paints on a not-yet-fully-rendered frame. 1,500 ms was the value that consistently produced a clean activation across all four renditions in testing. It's a measured constant, not a documented MediaLive parameter — and it lives in one place in the code so future tuning is a one-line change.

Tradeoff we intentionally made. Per-rendition overlay actions cost 4× the action count vs. a single global overlay. We accept the cost because the per-rendition path lets each output get a watermark sized exactly for its pixel dimensions, rather than letting MediaLive downscale a single overlay across all four. The result is a visibly sharper logo on SD outputs — and it leaves enough action budget for hundreds of programs before the 1500 cap matters.

5. The 1500-action ceiling, preflighted in the UI

AWS hard-caps a MediaLive channel at 1500 schedule actions. With ~7–8 actions per program (input switch + 4 watermarks + 2 ad cues + occasional slate), the channel holds roughly 180–200 active programs depending on ad density and slate frequency. That's a real ceiling for long-horizon deploys, and the exact number depends on per-program complexity.

Before every deploy, the backend calls Lambda's GET_SCHEDULE_COUNT, which counts live actions on the channel via DescribeScheduleCommand and returns { liveCount, capacity: 1500 }. If liveCount + (newPrograms × 8) would exceed 1500, the backend throws SCHEDULE_ACTION_CAP_EXCEEDED with the exact headroom number — before it submits anything to MediaLive. The operator sees the limit in the UI with guidance to clear past programs first. The deploy never half-runs into the wall.

Diagram 3 · One Program's Action Timeline

Pasted image (3).webp

 

Results

  • A single MediaLive channel serves effectively unlimited unique programs over its lifetime, on one dynamic input attachment. The 20-input cap is no longer a constraint we have to plan around — capacity at any one time is governed by the schedule-action limit, not the input limit.
  • Channel orchestration is self-healing: every deploy ends with an orphan sweep, so failed partial deploys can't leave the schedule in an inconsistent state.
  • Schedule capacity is bounded and visible. Operators see the 1500-action ceiling in the UI before they click, not as an opaque AWS rejection mid-deploy.
  • The program-ID naming convention is the entire identity layer — and it's a string. No new infrastructure, no extra storage, no dependencies. The simplest possible projection of "program" onto MediaLive's flat action list.

Technology Stack: AWS MediaLive · AWS Lambda · NestJS · MongoDB · TypeScript · Node 18 · AWS SDK v3 (@aws-sdk/client-medialive)




 

AWS MediaLiveFAST ChannelsSCTE-35Live TV
Untitled (612 x 640 px) (512 x 640 px) (512 x 600 px).webp

Про автора

Pankaj

AI & Cloud Solutions Expert at MicrocosmWorks

Building innovative AI-powered solutions and helping businesses transform through cutting-edge technology.

Бажаєте дізнатися більше?

Зв'яжіться з нами, щоб обговорити, як ми можемо допомогти впровадити ці рішення для вашого бізнесу.

Зв'яжіться з нами

Comments (0)

Share your thoughts and join the conversation

Leave a Comment

Your email will not be published

No comments yet

Be the first to share your thoughts!