rendering library
The pipeline surface behind Fluvie's renderers: capture services, render sandboxes, encoding seams, media-resolver contracts, and the renderer entry points they compose.
Import it where frames are produced — a render harness, an encoder backend, a server — never inside a composition:
import 'package:fluvie/rendering.dart';
Compositions import only package:fluvie/fluvie.dart, the authoring
surface. The two barrels are disjoint: authoring stays free of pipeline
machinery, and this surface assumes you are building or hosting a
renderer.
Classes
- BeatDetectionService
-
Detects the beats of one audio track and emits them as a
BeatGridin absolute video-frame space. - CaptureSink
- A growable byte sink the capture loop appends raw frame bytes to.
- DesktopVideoRenderer
- Renders a Fluvie composition to an MP4 file with a local FFmpeg.
- DisposableResolver
- A media resolver that holds disposable native resources (decoded images) and can release them eagerly instead of waiting for garbage collection.
- FadeBox
- The render-safe fade primitive: one named place where every Fluvie fade becomes pixels.
- FfmpegRunner
- An FFmpeg runtime that can probe its version and run one encode from a pre-built argument array.
- FfmpegRunnerRegistry
- Chooses the FfmpegRunner for a platform: the native process provider everywhere except the web, where ffmpeg.wasm takes over.
- FfmpegVersion
-
An FFmpeg
major.minorversion parsed from a-versionbanner, with the>= 6.0floor this library requires. - FileRenderSandbox
- A file-backed RenderSandbox under a real directory.
- FrameCache
- Persists captured frames on disk so an unchanged render replays from cache instead of re-capturing.
- FrameCacheStore
-
Adapts a disk FrameCache to the
dart:io-freeFrameStorethe capture loop reads, computing each key from the render digest and frame index. - FrameCaptureService
- Captures the pixels of one already-pumped frame as a RawFrame.
- FrameExtractionService
- Extracts one decoded frame of a video source as a RawFrame.
- FrequencyAnalyzer
-
Analyses one audio track into a per-frame
BandTabledriving spectrum-reactive animations. - GenerativeResolver
- Produces every declared generative source before the media pre-pass and serves the resolved local source synchronously afterwards.
- MediaResolver
- Pre-resolves every media source before the frame loop and serves the resolved bytes (and decoded images) synchronously during it.
- MemoryRenderSandbox
- An in-memory RenderSandbox: every file lives in a map of bytes.
- NetworkAllowlist
- The network safety gate consulted before any media fetch.
- NoGenerativeResolver
- The generation-less GenerativeResolver: valid only for compositions that declare no AI-generated media.
- NoMediaResolver
- The media-less MediaResolver: valid only for compositions that declare no media at all.
- RawFrame
- One captured frame: raw RGBA8888 pixels plus the metadata the encoder needs to place them in the stream.
- RenderConfig
- Everything one render needs to know: output size, frame rate, the frame window to capture, encode quality, and whether the frame cache may serve repeated frames.
- RenderManifest
-
The capture sandbox's completion signal and encode plan, written last
(after the frames file is complete) as
manifest.json. - RenderProgress
- A progress update from a render: the current phase, optional frame counts while capturing, and the compositionKey so concurrent renders stay distinguishable in logs.
- RenderSandbox
- Storage for one render: the frames file, the manifest, materialized encoder inputs, and the encoded output.
- RenderService
- Drives the deterministic capture pipeline: pre-resolve media, loop the frames (cache → pump → capture → append), then write the manifest last as the completion signal.
- RepaintBoundaryCaptureService
-
The real FrameCaptureService: rasterizes the RepaintBoundary under the
given key via
toImage(pixelRatio: 1.0)and reads back raw RGBA bytes. - ResolvedAudioMix
- A whole render's audio resolved to encoder-neutral tracks plus a final masterVolume, ready for a non-FFmpeg encoder to mix.
- ResolvedAudioTrack
- One audio track resolved to encoder-neutral numbers: the source to play plus the timing and gain an encoder needs, with no FFmpeg in sight.
- SnapshotService
-
Rasterizes a
SnapshotRequestto a decoded-readySnapshotRaster— the one boundary every snapshot-backed widget rides. - VideoProbeResult
- The probed facts of one video stream.
- VideoProbeService
- Reads the stream facts of an encoded video file (codec, size, frame count, duration) — what the determinism tests assert against.
-
VideoRenderer<
T> -
Renders a composition to
Ton one platform: aFilewhere the encode lands on disk (desktop, on-device mobile), bytes where it stays in memory (the browser). - WasmRuntime
- A loaded ffmpeg.wasm instance with its in-memory virtual file system.
- WebClipDecoder
-
Decodes a video clip in the browser from its bytes — the WebCodecs seam the
web
MediaResolverprobes and extracts clip frames through.
Enums
- RenderPhase
- The stage a render is in: capturing frames, encoding them, or finished.
Properties
-
assetBundleProvider
→ Provider<
AssetBundle> -
The asset bundle media assets are read from; defaults to
rootBundleand is overridable with a fake bundle in tests.final -
ffmpegRunnerProvider
→ Provider<
FfmpegRunner> -
The encode provider for the current platform (kIsWeb dispatch),
running processes through
processRunnerProvider; overridable in tests.final -
frameCacheProvider
→ Provider<
FrameCache> -
The frame cache used by the render pipeline; defaults to the shared
fluvie_frame_cachedirectory under the system temp directory and is overridable (for example with a per-test root).final -
frameCaptureServiceProvider
→ Provider<
FrameCaptureService> -
The capture service used by the render pipeline; defaults to
RepaintBoundaryCaptureService and is overridable in tests.
final
-
frameExtractionServiceProvider
→ Provider<
FrameExtractionService> -
The frame extractor used by the clip render path; defaults to
FfmpegFrameExtractionServiceoverprocessRunnerProviderand is overridable with a fake in tests.final -
generativeResolverProvider
→ Provider<
GenerativeResolver> -
The active GenerativeResolver for a render.
final
-
mediaBytesLoaderProvider
→ Provider<
MediaBytesLoader> -
The per-kind byte source the media resolver resolves over; web-safe (the
file://branch is behind a platform seam), so both platform resolvers build over it.final -
mediaResolverProvider
→ Provider<
MediaResolver> -
The media resolver used by the native render pipeline: a real
MediaRepositoryover the injected loader plus the clip probe/extraction services, streaming clip frames through an on-diskFileClipFrameStoreso a full-resolution or long clip never has to hold every decoded frame in memory, and serving them from the persistentclipFrameCacheProviderso an unchanged clip is not re-extracted on every run. Overridable with a fake in tests;NoMediaResolverstays exported as the deliberate media-less choice.final -
networkAllowlistProvider
→ Provider<
NetworkAllowlist> -
The network safety gate consulted before any media fetch; defaults to a
host-open, https-only allowlist and is overridable to a strict set.
final
-
videoProbeServiceProvider
→ Provider<
VideoProbeService> -
The video probe used by determinism checks and tooling; defaults to
FfprobeVideoProbeServiceoverprocessRunnerProviderand is overridable in tests.final
Functions
-
collectMediaSources(
List< Scene> scenes, {GenerativeResolver? generative}) → Set<MediaSource> -
Gathers every declared MediaSource from
scenesbefore the frame loop — a pure structural walk over the constructor data, with no mounting and no async. -
collectSnapshots(
List< Scene> scenes) → List<Snapshot> -
Gathers every Snapshot widget from
scenesin deterministic build order — the in-process subtree-capture sibling of collectSnapshotSources, walking the same tree with no mounting and no async. -
collectSnapshotSources(
List< Scene> scenes) → Set<SnapshotSource> -
Gathers every declared
SnapshotSourcefromscenesbefore the frame loop — the snapshot sibling of collectMediaSources, walking the same tree with no mounting and no async. -
createWasmRuntime(
) → WasmRuntime - VM stub: there is no ffmpeg.wasm outside the browser.
-
frameCountFor(
Duration duration, int fps) → int -
The number of frames a render of
durationatfpsproduces (at least one). -
gateOptInAudio(
{required Widget composition, required bool encode, required bool warn, required int fps, required int frameCount, required void warnSink(String message), required String platformLabel, Export? export}) → ResolvedAudioMix? - The one audio-drop policy the on-device and in-browser renderers share.
-
parseAspect(
String? aspect) → Aspect? -
The Aspect for an
--aspectvalue, ornull(the composition's declared size wins) fornull/empty. Throws an ArgumentError when the name is not an Aspect. -
parseExportFormat(
String? format) → Export? -
The Export for a
--formatvalue, ornull(the mp4 default) fornull/empty/mp4. -
parsePosterTime(
String? poster) → Time? -
The Time for a
--postervalue (1.5s,30f,500ms), ornull(no poster) fornull/empty. -
parseQuality(
String? quality) → Quality? -
The Quality for a
--qualityvalue, ornull(the config default) fornull/empty. Throws an ArgumentError when the name is not a Quality. -
render(
{required Widget composition, required Aspect aspect, required int frameCount, required Directory outDir, required RenderService service, required ShellMount pumpWidget, required ShellFramePump pumpFrame, int longEdge = VideoDefaults.longEdge, int fps = VideoDefaults.fps, String compositionKey = 'render', bool cacheEnabled = false, AudioMixStager? stageAudio, Iterable< AudioSource> ? audioSources, MediaResolver? resolver, GenerativeResolver generative = const NoGenerativeResolver(), void onGenerativeProgress(GenerativeProgress progress)?}) → Future<RenderAspectResult> -
Renders
compositionfor a singleaspect— the canonical multi-aspect entry. -
renderTemplate<
P> (VideoTemplate< P> template, {required P props, required int frameCount, required Directory outDir, required RenderService service, required ShellMount pumpWidget, required ShellFramePump pumpFrame, Aspect aspect = Aspect.reels, int longEdge = VideoDefaults.longEdge, int fps = VideoDefaults.fps, String compositionKey = 'template', bool cacheEnabled = false}) → Future<RenderAspectResult> -
Renders a parameterized VideoTemplate for one
Propsvalue — the data-driven-batch entry. -
renderToSandbox(
{required Widget composition, required Aspect aspect, required int frameCount, required RenderSandbox sandbox, required FrameCaptureService capture, required SandboxMount pumpWidget, required SandboxFramePump pumpFrame, int longEdge = VideoDefaults.longEdge, int fps = VideoDefaults.fps, String compositionKey = 'render', Export? export, int? posterFrame, ProgressCallback? onProgress, VideoEncoderService encoder = const VideoEncoderService(), List< ResolvedAudioTrack> audioTracks = const [], AudioByteLoader? loadAudioBytes, double audioMasterVolume = 1, MediaResolver? resolver, GenerativeResolver generative = const NoGenerativeResolver(), void onGenerativeProgress(GenerativeProgress progress)?, FrameEncoder? frameEncoder}) → Future<RenderManifest> -
Renders
compositionforaspectintosandboxwithout touching the file system — the in-memory,dart:io-free capture-and-plan path the web encoder drives. -
renderVideo(
{required Video video, required Directory outDir, required ShellMount pumpWidget, required ShellFramePump pumpFrame, required SetViewSize setViewSize, ShellRunAsync runAsync = runAsyncDirectly, String compositionKey = 'render', int? frameCountOverride, bool cacheEnabled = false, Directory? cacheRoot, Aspect? aspect, Quality? quality, Export? export, Time? posterTime, MediaResolver? resolver, SnapshotService? snapshotService, BeatDetectionService? beatDetector, FrequencyAnalyzer? analyzer, String? defaultFontFamily, FrameCaptureService capture = const RepaintBoundaryCaptureService(), void onProgress(int completed, int total)?, void onCacheReport(int completed, int total)?}) → Future< RenderManifest> -
Captures
videointooutDir(frames.rgba+manifest.json, manifest written last) — the one capture path every Fluvie renderer drives. -
resolveAudioMix(
{required Video video, required int fps, int totalFrames = 0, GenerativeResolver? generative}) → ResolvedAudioMix -
Resolves
video's declaredAudiotracks into an encoder-neutral ResolvedAudioMix for a non-FFmpeg encoder (such asfluvie_mobile_encoder). -
resolverScope(
MediaResolver? injected, {NetworkAllowlist? networkAllowlist, WebClipDecoder? clipDecoder, int? clipDecodeMaxEdge, bool streamClipFrames = true}) → ResolverScope - Resolves the MediaResolver a render uses and the matching teardown.
-
runAsyncDirectly<
T> (Future< T> callback()) → Future<T?> -
The ShellRunAsync for a host that already has a real event loop: it simply
awaits
callback. -
runGuarded(
List< Future< cleanups, void onError(Object error, StackTrace stackTrace)) → Future<void> Function()>void> -
Runs each cleanup in
cleanupsin order, routing any thrown error toonErrorand never re-throwing. -
runStage<
T> (RenderPhase phase, Future< T> body()) → Future<T> -
Runs
body, stampingphaseonto any FluvieRenderException it throws (when not already stamped) so the failure records which render stage broke. -
stageResolvedAudioToSandbox(
{required List< ResolvedAudioTrack> tracks, required RenderSandbox sandbox, required AudioByteLoader loadBytes, double masterVolume = 1}) → Future<AudioMixPlan> -
Stages every resolved audio
tracksintosandboxand builds the encoderAudioMixPlan, without touching the file system. -
writeRenderProgress(
String path, int completed, int total) → void -
Writes
"<completed>/<total>"topathatomically, for a launcher polling a render's progress.
Typedefs
-
AudioByteLoader
= Future<
Uint8List> Function(String source) -
Loads the bytes of an audio
sourcestring (an asset key, file path, or URL). -
AudioMixLanes
= ({FfmpegAudioMix? amix, List<
FfmpegAudioNode> nodes}) -
The encoder audio lanes a render contributes: the per-track
FfmpegAudioNodes and theFfmpegAudioMixthat combines them (nullmix = no audio). -
AudioMixStager
= Future<
AudioMixLanes> Function({required MediaResolver resolver, required Directory sandbox}) -
Stages the pre-resolved audio into the render
sandboxand returns its encoder lanes. Injected sorenderingstays independent of theaudiofeature layer: the shell wires the audio layer'sstageAudioMix, tests pass a fake. - ClipMetadata = ({double fps, int frameCount, bool hasAudio, int height, int width})
-
The probed facts a
Clipneeds to resample a source video deterministically — its frame rate, frame count, pixel dimensions, and whether it carries an audio track (so the encoder mixes a clip's embedded audio only when present). -
FrameEncoder
= Future<
Uint8List> Function(Uint8List rgba, int width, int height) - Compresses one captured frame's raw RGBA pixels to encoder-ready bytes.
-
FramePump
= Future<
void> Function(int frame) -
Pumps the tree to frame
nand returns once that frame is fully built — the host (a widget test, the capture harness, the off-screen web/mobile driver) owns the pumping mechanics. - GeneratedAssetMeta = ({Duration? duration, bool hasAudio, int? height, int? width})
-
The probed facts about a produced generative asset the render needs: its
duration(audio/video), whether a video carries an embedded audio track (hasAudio), and its pixel size when known. - GenerativeProgress = ({int index, String providerId, String stage, int total})
-
Coarse progress for one generative asset during the prerender pass, surfaced
to the render's progress callback: which asset (
indexoftotal), itsproviderId, and a humanstage(for examplegenerating,downloading,cached). - ProgressCallback = void Function(int completed, int total)
-
Reports capture progress:
completedoftotalframes are written. - RenderAspectResult = ({RenderConfig config, RenderManifest manifest})
-
What render returns: the captured
manifestand theconfigwhose width and height were re-derived fromAspect.sizeForfor the rendered aspect. - RenderProgressCallback = void Function(RenderProgress progress)
-
A sink for RenderProgress updates, passed to a renderer's
render(...). - ResolvedMedia = ({Uint8List bytes, String contentHash})
-
One pre-resolved media asset: its raw
bytesand thecontentHashthat keys caches and render digests. -
ResolverScope
= ({Future<
void> Function() dispose, MediaResolver resolver}) - A media resolver for one render plus the teardown that releases it.
-
SandboxFramePump
= Future<
void> Function() - Pumps the host one frame after the controller seeks.
-
SandboxMount
= Future<
void> Function(Widget tree) - Mounts a capture shell (Widget) into the host before the frame loop.
- SetViewSize = void Function(int width, int height)
- Points the host's view at the render canvas.
-
ShellFramePump
= Future<
void> Function() -
Pumps the host one frame after the controller seeks, so the just-seeked
frame is fully built before its pixels are read. A widget test passes
() => tester.pump(); the CLI passes its binding's pump. -
ShellMount
= Future<
void> Function(Widget tree) -
Mounts
tree(the full capture shell) into the host's element tree before the frame loop starts. A widget test passestester.pumpWidget; the CLI passes its binding's pump. -
ShellRunAsync
= Future<
T?> Function<T>(Future< T> callback()) -
Runs
callbackon a real event loop, returning its result.