npx skills add ...
npx skills add nvidia/flashdreams --skill flashdreams-postprocessing
Add or modify FlashDreams video post-processing processors, sessions, presets, and runner stream wiring. Use when implementing a new VideoPostProcessorConfig / VideoPostProcessor / VideoPostProcessorSession, registering a --postprocess.preset entry point, changing VideoPostprocessStream behavior, or reasoning about streaming buffering, layouts, per-view processing, distributed execution, or postprocess tests.
npx skills add nvidia/flashdreams --skill flashdreams-postprocessing
Use this skill when adding a video post-processor or changing the runner
post-processing stream. The reference implementation is
integrations_v2/flashvsr/impl/postprocess.py.
A post-processor is usually three classes, not one class inheriting everything:
VideoPostProcessorConfig: serializable config and CLI surface. It sets
_target to the processor factory and declares fields, output_spec(),
requires_all_ranks(), and validate_execution().VideoPostProcessor: lightweight factory created from config. Its job is
start(spec) -> VideoPostProcessorSession.VideoPostProcessorSession: mutable per-stream runtime. It owns buffers,
caches, lazy model instances, counters, and process() / flush().Keep stream state in the session. Do not store per-rollout mutable state on the config or processor factory.
Pick a home:
flashdreams/flashdreams/infra/postprocess/.integrations/<name>/<pkg>/postprocess.py.Define a config subclass:
Override:
output_spec() when spatial size, channels, or timing changes.requires_all_ranks() when the processor must run on nonzero ranks under
torchrun.validate_execution() to reject unsupported distributed or shape modes
early.Every config inherits device from VideoPostProcessorConfig. Consumers
copy cached preset configs, assign device before setup(), and keep it
fixed for the processor's lifetime. Backends that need a native device
representation convert the shared string when they construct their runtime
resources. Never mutate the preset object returned by the registry.
Define the processor factory:
Define the session:
process() is synchronous but may return []: that means it consumed the
input chunk and is buffering frames until a later chunk or flush() can
complete an output window.
Handle layouts at the boundary:
VideoChunk.tensor in chunk.layout.to_bvtchw() only as a generic boundary helper..contiguous() because it can copy.Return VideoChunks:
[-1, 1] value range unless the API is intentionally changed.layout.Register presets when users should select it from CLI:
The exported object must be a VideoPostProcessorConfig, for example:
Users select it with --postprocess.preset my-postprocessor-v1.
V2 applications that also expose device placement should resolve both at launch time through the shared factory:
This copies the registered preset, assigns its shared device field, and
stores it before setup() or prepare() can load model resources. Keep
output-channel selection and application metadata pairing in the
application; the session runner cannot infer those semantics from an
ordered list of model results.
Runners create a VideoPostprocessStream through
create_runner_postprocess_stream(). The stream:
postprocess_per_view=True;session.process(VideoChunk(...)) for each AR output;[] into a zero-frame tensor so process() remains tensor-only;_append_if_nonempty();flush() once at end-of-stream and appends any tail output.Use postprocess_output_layout to describe the runner's decoded output layout.
Use postprocess_per_view=True for bvtchw outputs when each camera/view needs
an independent processor session.
Add CPU-safe tests unless the behavior genuinely requires a GPU:
flashdreams/tests/test_postprocess_presets.py.flashdreams/tests/test_postprocess_stream.py.integrations/<name>/tests/test_postprocess.py.flashdreams/tests/test_runner_postprocess.py.Every pytest test must use exactly one marker: ci_cpu, ci_gpu, or manual.
Prefer fake processor builders for CPU tests instead of loading checkpoints.
Useful focused validation: