flutter_vap_kit 0.1.2
flutter_vap_kit: ^0.1.2 copied to clipboard
Play Tencent VAP transparent (alpha-channel) MP4 animations with one widget: seamless looping, automatic first-frame poster, asset and network caching.
flutter_vap_kit
Transparent video animations for Flutter — gift effects, entry animations,
banners and badges — in one line.
VapPlayer.asset('assets/rocket.mp4', loop: true)
That is the whole integration. No controller to create, no waiting for a native view, no restarting the clip yourself to make it loop.
What is VAP? #
VAP is Tencent's format for video with a real alpha channel: an ordinary H.264 MP4 that carries its own transparency. It is what live-streaming and social apps use for full-screen gift effects, because it is far smaller than a PNG sequence, far richer than Lottie or SVGA can be, and hardware-decoded.
flutter_vap_kit plays those files on Android and iOS.
Why this package #
Playing a VAP file is easy. Playing it well inside a Flutter app is where the time goes. This package handles the parts you would otherwise write yourself:
| You get | What it means |
|---|---|
| Seamless looping | Loops run inside the native player on both platforms. No blink between runs. |
| Never an empty box | The clip's own first frame is shown, with its transparency, until playback starts. |
| No dropped starts | Play requests wait for the native view and are retried if it does not answer. |
| Assets copied once | Bundled clips are extracted one time, not on every play. |
| Network clips cached | Downloaded once, then played from disk. |
| Touches pass through | Buttons under or over an animation keep working. |
| Survives backgrounding | Looping clips resume when the app comes back, and restart themselves if the decoder is lost. |
| Works on the iOS simulator | Most VAP plugins show nothing there; this one renders. |
| Declarative | Change source, loop or fit and the player follows. |
Install #
dependencies:
flutter_vap_kit: ^0.1.2
| Minimum | |
|---|---|
| Android | minSdk 24 |
| iOS | 12.0 — Swift Package Manager or CocoaPods |
No permissions, no manifest or Info.plist changes.
Quick start #
A looping animation #
SizedBox(
height: 260,
child: VapPlayer.asset('assets/rocket.mp4', loop: true),
)
The player fills the box its parent gives it, so give it a size: a SizedBox,
an AspectRatio, a Positioned.
A one-shot effect #
VapPlayer.network(
'https://example.com/gift.mp4',
onComplete: () => showNextGift(),
)
An animated banner with a button on top #
Stack(
alignment: Alignment.centerRight,
children: [
AspectRatio(
aspectRatio: 750 / 176,
child: VapPlayer.asset('assets/banner.mp4', loop: true, fit: BoxFit.fill),
),
FilledButton(onPressed: join, child: const Text('Go')),
],
)
A gift queue, driven from code #
final controller = VapController();
VapPlayer.asset(
'assets/gift.mp4',
controller: controller,
autoPlay: false,
onComplete: playNextGift,
);
controller.play(); // the player's clip
controller.play(const VapSource.network(nextGiftUrl)); // a different clip
controller.stop();
controller.state is idle, loading, playing, completed or error. The
controller is a Listenable, so it works with ListenableBuilder.
Keep a widget in step with the clip #
Some clips have a moving slot for a profile picture or a name. onFrame tells
you which video frame is on screen, so your widget can follow it:
VapPlayer.asset(
'assets/winner.mp4',
onFrame: (frame) => position.value = slotPositions[frame],
)
The frame reaches the screen slightly after it is reported (a frame or two, depending on the device), so trail the reported index a little if the match has to be exact.
Warm clips up before they are needed #
await VapKit.preload(const VapSource.network('https://example.com/gift.mp4'));
Copies or downloads the clip and renders its first frame, so the player that shows it later starts at once. Good for the gifts on a gift panel.
API at a glance #
VapPlayer #
| Parameter | Default | |
|---|---|---|
source |
— | VapSource.asset, .file or .network. Or use the VapPlayer.asset / .file / .network constructors. |
loop |
false |
Repeat forever, seamlessly. |
repeat |
1 |
Times to play when loop is false. |
autoPlay |
true |
Start as soon as the player is on screen. |
fit |
BoxFit.contain |
contain, cover or fill. |
showPoster |
true |
Show the first frame while the clip gets ready. |
placeholder |
— | Your own widget for that moment instead. |
controller |
— | A VapController, when you need one. |
onStart / onComplete / onError |
— | Playback callbacks. |
onFrame |
— | Index of each video frame as it is drawn, to keep your own widgets in step with the clip. |
VapKit #
VapKit.preload(source) |
Get a clip ready ahead of time. |
VapKit.clearCache() |
Forget cached clips and delete downloads. |
Making VAP files #
Export your animation as a PNG sequence with transparency, then convert it with
Tencent's VapTool. The result
is a single .mp4 you drop into assets/.
Good to know #
- One player per animation. Each
VapPlayerowns a hardware video decoder. A handful on screen is fine; a long scrolling list of them is not — show a still there and play on tap. - Fusion animations (text or images merged into a clip at play time) are not exposed yet.
- Do not combine with other VAP plugins. This package ships its own copy of
the iOS player, so adding another plugin that brings
QGVAPlayerproduces duplicate classes.
Example #
The example app is the scene in the preview above: an animated banner with text and a working button laid over it, a looping rocket, and a one-shot effect fired from a button.
cd example
flutter run
Credits and license #
BSD-3-Clause — see LICENSE.
Built on Tencent VAP, which is MIT-licensed
and stays so. The Android side
uses Tencent's published library; the iOS side includes a copy of Tencent's
player source with two fixes — a crash in decoder set-up, and rendering when
frames are software-decoded — see ios/flutter_vap_kit/Sources/flutter_vap_kit_player/LICENSE.txt.