Templates¶
Fluvie provides pre-built "Wrapped-style" templates for common video composition patterns. Templates are customizable scene compositions with standardized data contracts for consistent usage.
Overview¶
| Category | Description | Use Case |
|---|---|---|
| Intro | Opening/identity scenes | Year intro, brand reveals |
| Ranking | List/top-N displays | Top songs, favorites |
| DataViz | Data visualization | Statistics, metrics |
| Collage | Photo arrangements | Photo grids, galleries |
| Thematic | Mood/vibe scenes | Lo-fi, retro, glitch |
| Conclusion | Ending/summary scenes | Wrap-up, share CTA |
Quick Start¶
Using a Template¶
Video(
fps: 30,
width: 1080,
height: 1920,
scenes: [
// Create template and convert to Scene
TheNeonGate(
data: IntroData(
title: 'Your 2024',
subtitle: 'Wrapped',
year: 2024,
),
).toScene(),
// Add more scenes
StackClimb(
data: RankingData(
title: 'Top Songs',
items: [
RankingItem(rank: 1, label: 'Song One'),
RankingItem(rank: 2, label: 'Song Two'),
RankingItem(rank: 3, label: 'Song Three'),
],
),
).toScene(),
],
)
With Transitions¶
TheNeonGate(data: introData)
.toSceneWithCrossFade(fadeDuration: 20)
StackClimb(data: rankingData)
.toSceneWithSlide(direction: TransitionSlideDirection.left)
Template Architecture¶
WrappedTemplate Base Class¶
All templates extend WrappedTemplate:
abstract class WrappedTemplate extends StatelessWidget {
final TemplateData data; // Content data
final TemplateTheme? theme; // Visual styling
final TemplateTiming? timing; // Animation timing
int get recommendedLength; // Suggested scene length
TemplateCategory get category; // Template category
String get description; // Template description
Scene toScene(); // Convert to Scene
List<Scene> toScenes(); // Convert to multiple Scenes
}
Data Types¶
Each template category uses specific data types:
| Category | Data Type | Key Fields |
|---|---|---|
| Intro | IntroData |
title, subtitle, year, logoPath |
| Ranking | RankingData |
items, title |
| DataViz | DataVizData |
metrics, title |
| Collage | CollageData |
images, captions |
| Thematic | ThematicData |
text, images, theme |
| Conclusion | SummaryData |
stats, message, highlights |
Data Types Reference¶
IntroData¶
IntroData(
title: 'Your 2024', // Required
subtitle: 'Wrapped', // Optional
year: 2024, // Optional
logoPath: 'assets/logo.png', // Optional
userName: 'John', // Optional
profileImagePath: 'assets/profile.jpg', // Optional
)
RankingData¶
RankingData(
title: 'Top Artists',
subtitle: 'This Year',
items: [
RankingItem(
rank: 1,
label: 'Artist Name',
subtitle: '234 hours',
imagePath: 'assets/artist1.jpg',
value: 234,
metadata: {'streams': 5000},
),
RankingItem(rank: 2, label: 'Another Artist'),
RankingItem(rank: 3, label: 'Third Artist'),
],
isTopList: true,
)
DataVizData¶
DataVizData(
title: 'Your Stats',
subtitle: 'In Numbers',
metrics: [
MetricData(label: 'Hours', value: 1234, unit: 'hrs'),
MetricData.percentage(label: 'Growth', value: 45),
MetricData.minutes(label: 'Daily Average', minutes: 120),
MetricData.count(label: 'Songs', count: 5678),
],
maxValue: 2000,
)
CollageData¶
CollageData(
title: 'Your Moments',
subtitle: '2024 Gallery',
images: [
'assets/photo1.jpg',
'assets/photo2.jpg',
'assets/photo3.jpg',
],
captions: ['Beach Day', 'Mountains', 'City'],
featuredIndex: 0,
layout: TemplateCollageLayout.grid,
)
ThematicData¶
ThematicData(
text: 'Your Music Journey',
title: 'The Vibe',
subtitle: '2024 Edition',
images: ['assets/mood1.jpg', 'assets/mood2.jpg'],
statValue: '1,234',
statLabel: 'hours',
theme: 'lofi',
accentColor: Colors.purple,
)
SummaryData¶
SummaryData(
title: 'That\'s a Wrap!',
subtitle: 'See You Next Year',
name: 'John',
year: 2024,
stats: {
'Hours': '1,234',
'Songs': '5,678',
'Artists': '234',
},
highlights: [
HighlightItem(title: 'Top Fan', description: 'Top 1% of listeners'),
HighlightItem(title: 'Genre Explorer', description: '12 genres'),
],
message: 'Thanks for an amazing year!',
ctaText: 'Share Your Wrapped',
shareUrl: 'https://example.com/share',
)
Theming¶
TemplateTheme¶
Customize visual appearance:
TheNeonGate(
data: introData,
theme: TemplateTheme(
primaryColor: Colors.cyan,
secondaryColor: Colors.pink,
backgroundColor: Colors.black,
textColor: Colors.white,
accentColor: Colors.purple,
),
)
Built-in Themes¶
// Neon/cyberpunk style
theme: TemplateTheme.neon
// Spotify-inspired
theme: TemplateTheme.spotify
// Clean minimal
theme: TemplateTheme.minimal
// Warm sunset colors
theme: TemplateTheme.sunset
// Cool ocean blues
theme: TemplateTheme.ocean
Timing¶
TemplateTiming¶
Customize animation timing:
TheNeonGate(
data: introData,
timing: TemplateTiming(
entryDelay: 0, // Frames before first element
entryDuration: 30, // Entry animation duration
staggerDelay: 10, // Delay between elements
holdDuration: 60, // How long to hold at full
exitDuration: 20, // Exit animation duration
),
)
Built-in Timings¶
// Standard pacing
timing: TemplateTiming.standard
// Slower, more dramatic
timing: TemplateTiming.dramatic
// Faster, snappier
timing: TemplateTiming.snappy
// Very quick
timing: TemplateTiming.quick
Converting to Scenes¶
Basic Conversion¶
// Default scene length
template.toScene()
// Custom length
template.toScene(durationInFrames: 200)
// With transitions
template.toScene(
durationInFrames: 180,
transitionIn: SceneTransition.crossFade(durationInFrames: 20),
transitionOut: SceneTransition.slideLeft(durationInFrames: 15),
)
Convenience Methods¶
// Cross-fade both directions
template.toSceneWithCrossFade(fadeDuration: 20)
// Slide transition
template.toSceneWithSlide(
direction: TransitionSlideDirection.left,
slideDuration: 25,
)
Multiple Scenes¶
Some templates generate multiple scenes:
// Get all scenes from a template
final scenes = complexTemplate.toScenes();
Video(
scenes: [
...introTemplate.toScenes(),
...rankingTemplate.toScenes(),
...conclusionTemplate.toScenes(),
],
)
Complete Example¶
final introData = IntroData(
title: 'Your 2024',
subtitle: 'Wrapped',
year: 2024,
);
final rankingData = RankingData(
title: 'Top 5 Songs',
items: [
RankingItem(rank: 1, label: 'Song One', imagePath: 'assets/song1.jpg'),
RankingItem(rank: 2, label: 'Song Two', imagePath: 'assets/song2.jpg'),
RankingItem(rank: 3, label: 'Song Three', imagePath: 'assets/song3.jpg'),
RankingItem(rank: 4, label: 'Song Four', imagePath: 'assets/song4.jpg'),
RankingItem(rank: 5, label: 'Song Five', imagePath: 'assets/song5.jpg'),
],
);
final summaryData = SummaryData(
title: 'That\'s a Wrap!',
stats: {
'Hours': '1,234',
'Songs': '5,678',
},
message: 'See you in 2025!',
);
Video(
fps: 30,
width: 1080,
height: 1920,
backgroundMusicAsset: 'assets/music.mp3',
scenes: [
TheNeonGate(
data: introData,
theme: TemplateTheme.neon,
).toSceneWithCrossFade(),
StackClimb(
data: rankingData,
theme: TemplateTheme.spotify,
).toSceneWithSlide(direction: TransitionSlideDirection.left),
TheSummaryPoster(
data: summaryData,
).toSceneWithCrossFade(),
],
)
Related¶
- Using Templates - Detailed usage guide
- Scene - Scene widget
- Video - Video composition
- SceneTransition - Scene transitions