Video ad end card: add a fade-in and fade-out with Timeline

Close an ad with a 1-second fade-out and open it with a 0.5-second fade-in using output.fade_in_seconds and fade_out_seconds in a Timeline 1.0 render.

5 min readSume
All posts

To end a video ad on a clean fade, set output.fade_out_seconds in a Timeline 1.0 render, and output.fade_in_seconds for the opening. Each accepts 0 to 5 seconds, and their sum must not exceed the output length, or the plan fails with edge_fades_exceed_output. A render is $0.10 per output minute, rounded up, at the public rate; the plan call is unbilled.

Source: Timeline 1.0: assemble clips into one MP4. Confirm the live price in GET /v1/catalog.

Fades or an end card clip?

A fade is a style choice; an end card is content. A logo card with a call to action should be its own clip or still, put in the last video[] slot, because stills are static holds in Timeline. Then output.fade_out_seconds fades the whole result to black after it. That is the combination most ads need: a still end card for a few seconds with a short fade at the end. A hard cut to black on the last frame can look like a rendering mistake.

The document

The ad below is 15 seconds: 12 seconds of footage with a 3-second end card, then a half-second fade-in at the start and a one-second fade-out at the end. fit: "cover" is the default and fills the frame, and blur fills a mismatched ratio with a blurred copy; for an end card with text near the edges, use contain so nothing gets cropped. Stills accept a motion field that the render ignores, with a motion_ignored warning, which is not a failure.

import json, os, urllib.request

doc = {
    "audio": {
        "url": "https://media.sume.com/artifacts/artf_demo/voice-15s.wav",
        "duration_seconds": 15,
    },
    "video": [
        {"source_url": "https://media.sume.com/artifacts/artf_demo/ad-12s.mp4",
         "start": 0, "duration": 12},
        {"source_url": "https://media.sume.com/artifacts/artf_demo/end-card.png",
         "start": 12, "duration": 3, "fit": "contain",
         "transition": {"type": "fade", "duration": 0.25}},
    ],
    "output": {"width": 1080, "height": 1920, "fade_in_seconds": 0.5,
               "fade_out_seconds": 1},
}
req = urllib.request.Request(
    "https://api.sume.com/v1/timeline-1.0/plan",
    data=json.dumps(doc).encode(),
    headers={"Authorization": "Bearer " + os.environ["SUME_API_KEY"],
             "Content-Type": "application/json"},
)
with urllib.request.urlopen(req) as r:
    print(json.load(r))

Limits that trip people up

A transition is only allowed on slots after the first, its duration is at most 1 second and at most half the shorter neighbour, and it must land on at least one output frame. More than 8 adjacent fades are refused with too_many_chained_transitions. The first slot's start must be 0. Coverage can stop at most 0.5 seconds before the end of the spine. If the frame rate of your sources differs from the one you ask for, the render reports output_fps_resamples_sources, so leave output.fps out unless you need a specific rate.

Fade and transition limits from Sume's Timeline 1.0 page, read 2026-10-06.
FieldAllowedRefusal
output.fade_in_seconds0 to 5edge_fades_exceed_output if the sum is too long
output.fade_out_seconds0 to 5Same
transition.durationUp to 1 s and half the neighbourtransition_too_long
Transition on first slotNot allowedtransition_on_first_segment
Adjacent fadesAt most 8too_many_chained_transitions

Run the plan before the render

Plan first, because it checks every one of those rules without charging you. When it passes, submit the same document to /v1/timeline-1.0/render with an Idempotency-Key, and check the result's warnings[]. If the end card is hard to read, regenerate the card, not the whole ad.

The plan answer carries duration_seconds, segment_count, billable_minutes and estimated_cost_usd_micros. For the 15-second document above you should see one billable minute, because a render reserves ceil(audio.duration_seconds / 60) minutes. Check that number before you render, since a longer end card or a second ad in the same document is the usual way a cheap render becomes a two-minute one.

Soft warnings are not failures. A source that is shorter than its slot is padded or looped, a still reports motion_ignored if you gave it a motion, and a transition may be snapped to the frame grid. They appear in warnings[] on the render so you can decide whether the result is acceptable. A fade in, a fade out and a short transition into the card are three different controls, and it helps to change only one at a time when you compare two renders of the same ad.

Sources

Related posts

More in Use cases

All Use cases posts

Written by Sume