Billionmail/BillionMail · error
no scenes provided
Error message
no scenes provided
What it means
CompositeVideo builds the FFmpeg argument list via BuildFFmpegArgs; that builder returns nil when cfg.Scenes is empty/absent. CompositeVideo detects the nil args and aborts with 'no scenes provided' before invoking ffmpeg, because there is nothing to composite. It is a fast-fail validation for an empty composite job.
Source
Thrown at core/internal/service/video_gen/composite.go:185
// Places the lip sync video in the bottom-right corner at 25% of frame size.
func buildPiPFilter(lipSyncIdx int, baseVideo string, cfg CompositeConfig) string {
pipW := cfg.Width / 4
pipH := cfg.Height / 4
pipX := cfg.Width - pipW - 20 // 20px margin
pipY := cfg.Height - pipH - 20
return fmt.Sprintf(
"[%d:v]scale=%d:%d[pip];[%s][pip]overlay=%d:%d:shortest=1[vpip]",
lipSyncIdx, pipW, pipH, baseVideo, pipX, pipY,
)
}
// CompositeVideo runs FFmpeg to combine screenshots + audio into a final video.
// Requires: ffmpeg installed and in PATH.
func CompositeVideo(ctx context.Context, cfg CompositeConfig) (*CompositeResult, error) {
args := BuildFFmpegArgs(cfg)
if args == nil {
return nil, fmt.Errorf("no scenes provided")
}
// Ensure output directory exists
if err := os.MkdirAll(filepath.Dir(cfg.OutputPath), 0755); err != nil {
return nil, fmt.Errorf("create output dir: %w", err)
}
cmd := exec.CommandContext(ctx, "ffmpeg", args...)
out, err := cmd.CombinedOutput()
if err != nil {
return nil, fmt.Errorf("ffmpeg compositing failed: %w\noutput: %s", err, string(out))
}
// Calculate total duration from scenes
var totalDuration time.Duration
for _, scene := range cfg.Scenes {
totalDuration += scene.Duration
}View on GitHub (pinned to fc36c76c05)
Solutions
- Populate cfg.Scenes with at least one scene (screenshot + audio + duration) before calling CompositeVideo
- Check the upstream screenshot/annotate steps: if they failed silently, fix that first and re-run
- Validate scenes length at the pipeline entry point and fail early with a clearer message
- If an empty video is legitimate for your flow, guard the call: skip compositing when len(scenes)==0
Example fix
// before
res, err := video_gen.CompositeVideo(ctx, cfg) // cfg.Scenes may be empty
// after
if len(cfg.Scenes) == 0 {
return nil, errors.New("cannot composite: no scenes were produced by the screenshot step")
}
res, err := video_gen.CompositeVideo(ctx, cfg) Defensive patterns
Strategy: validation
Validate before calling
if cfg.Scenes == nil || len(cfg.Scenes) == 0 {
return errors.New("cannot composite video: no scenes were produced")
}
res, err := video_gen.CompositeVideo(ctx, cfg) Try / catch
res, err := video_gen.CompositeVideo(ctx, cfg)
if err != nil {
if err.Error() == "no scenes provided" {
log.Warn("skipping compositing: empty scene list (check screenshot step)")
return nil // or surface upstream pipeline failure
}
return err
} Prevention
- Validate len(cfg.Scenes) > 0 at the pipeline entry point
- Check the screenshot step's logs — an empty scene list usually means it failed silently
- Never pass an uninitialized CompositeConfig struct
- Decide explicitly how empty output should be handled (skip vs fail) and encode it in the pipeline
When it happens
Trigger: Calling CompositeVideo with a CompositeConfig whose Scenes slice is nil or has zero entries (e.g. no screenshots were captured upstream, or the scenes slice was reset).
Common situations: Upstream screenshot/annotate step produced zero scenes (all screenshots failed); passing an uninitialized struct; a filter dropping all scenes before compositing; wiring bug that never appends to cfg.Scenes.
Related errors
- Content cannot be empty
- contact %d missing website_url
- required column 'email' not found
- You cannot create more than 5000 batches
- No log files found in the given date range
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/129ad5f8376be4f0.
Report an issue: GitHub.