package playback import ( "context" "errors" "fmt" ) type videoSinkError struct { err error } func (e *videoSinkError) Error() string { return fmt.Sprintf("consume video: %v", e.err) } func (e *videoSinkError) Unwrap() error { return e.err } func runVideoAttempt( ctx context.Context, factory VideoReaderFactory, sink VideoSink, config FeedConfig, ) (resultErr error) { reader, err := factory.OpenVideo(ctx, config) if err != nil { return fmt.Errorf("open video: %w", err) } defer func() { if closeErr := reader.Close(); closeErr != nil { closeErr = fmt.Errorf("close video: %w", closeErr) resultErr = errors.Join(resultErr, closeErr) } }() for { frame, err := reader.ReadVideo(ctx) if err != nil { if ctx.Err() != nil { return ctx.Err() } return fmt.Errorf("read video: %w", err) } if err := sink.ConsumeVideo(ctx, frame); err != nil { if ctx.Err() != nil { return ctx.Err() } return &videoSinkError{err: err} } } }