Do fades shift my cuts? Timeline start times with transitions
In Timeline 1.0 a slot's declared start is its place on the audio spine, fade or no fade. The compiler compensates for the xfade overlap; gaps hold a frame.

No. In Sume Timeline 1.0, video[].start is the on-spine start of each slot, and the docs call declared starts authoritative: the compiler compensates for the xfade overlap and never pre-shifts. If slot two starts at 8 s with a 0.5 s fade, it still starts at 8 s on the spine, and a third slot declared at 16 s is not pulled earlier by the first fade.
Why this is the right behaviour
A crossfade in a plain concat chain eats time: each fade shortens the running length by its duration, so after N fades everything after them lands early and drifts away from a voice-over. The compiler's own note states the invariant it proves in tests: after compensation the accumulated offset equals the next slot's start, so declared starts are never shifted by (N-1) times the fade length. The effect for you is simple. Write the starts from the script timings and you do not need to subtract anything for transitions.
What you still have to respect
| Rule | Value | Error or behaviour |
|---|---|---|
| First slot start | must be 0 | timeline_must_start_at_zero |
| Later starts | must increase | invalid_segment_timing |
| Fade on first slot | not allowed | transition_on_first_segment |
| Fade length | at most 1 s and 50% of the shorter neighbour | transition_too_long |
| Fade frame alignment | at least one output frame | transition_not_frame_aligned |
| Adjacent fades in a row | at most 8 | too_many_chained_transitions |
| Slot longer than next start plus fade | not allowed | segment_overlap |
| Gap between a slot's end and the next start | previous frame is held | timeline_gap_filled warning |
A three-slot example
The spine is 24 seconds. Slots start at 0, 8 and 16, and the second and third come in on a short fade. Because starts are authoritative you can line the 8 s cut up with a sentence boundary in the voice and the 16 s one with the next, and the fades happen across those boundaries.
{
"audio": {
"url": "https://media.sume.com/artifacts/artf_demo/voice.wav",
"duration_seconds": 24
},
"video": [
{ "source_url": "https://media.sume.com/artifacts/artf_demo/a.mp4", "start": 0, "duration": 8 },
{ "source_url": "https://media.sume.com/artifacts/artf_demo/b.mp4", "start": 8, "duration": 8,
"transition": { "type": "fade", "duration": 0.5 } },
{ "source_url": "https://media.sume.com/artifacts/artf_demo/c.mp4", "start": 16, "duration": 8,
"transition": { "type": "fade", "duration": 0.5 } }
]
}Check before you pay
Call POST /v1/timeline-1.0/plan first. It runs the schema, host checks and the pure compiler, and returns duration_seconds, segment_count and billable_minutes without creating a job. A plan cannot predict warnings about short sources that get padded or looped, so read warnings[] in the render result. Rendering costs $0.10 per ceil output minute.
Sources
Related posts
More in Media tools
- Two-voice dialogue audio on Sume: TTS lines joined with audio concat
Build a role-play or interview track by generating one TTS line per turn in each speaker's voice, then joining up to 20 turns into one gapless file for $0.01.
- One lip-sync model per video: Fabric runs at 25 fps, measure H3 Max
Mixing Fabric and MiniMax H3 Max lip-sync clips in one Sume video risks a frame-rate mismatch. Pick one per run and check fps with ffprobe on the first clip.
- video-filter dim amount 0 or 1.2 is refused: the (0, 1] range
Dim amount takes values above 0 up to 1. Zero, negatives and 1.2 return video_filter_amount_out_of_range. What it does, and how to lift a dark clip.
- video-filter invalid_filtergraph: every reason and the fix for each
A video-filter filtergraph is refused for eight reasons, from a [0:v] label to a quote character. What each one means and how to rewrite the graph so it passes.
Written by Sume