Playback
useVideoCompositionPlayer plays a composition in real time: it drives the
decoders, calls your drawFrame into an offscreen GPU surface every vsync,
and returns the resulting SkImage as a Reanimated derived value.
import { Canvas, Image } from '@shopify/react-native-skia';
import { useVideoCompositionPlayer } from '@azzapp/react-native-skia-video';
const CompositionPlayer = ({ composition, width, height }) => {
const { currentFrame, player } = useVideoCompositionPlayer({
composition,
drawFrame,
width,
height,
autoPlay: true,
isLooping: true,
onError: (error, retry) => {
console.warn(error);
retry();
},
});
return (
<Canvas style={{ width, height }}>
<Image image={currentFrame} x={0} y={0} width={width} height={height} />
</Canvas>
);
};
Options
| Option | Type | Description |
|---|---|---|
composition | VideoComposition | null | The composition to play; null skips creating the player. |
drawFrame | FrameDrawer | Worklet that draws each frame (concepts). |
width / height | number | Output size in density-independent points (the backing surface is scaled by the device pixel ratio). |
autoPlay | boolean | Start as soon as the composition is ready. |
isLooping | boolean | Loop when the end is reached. |
beforeDrawFrame / afterDrawFrame | () => T / (context: T) => void | Run around every frame; the returned context is passed to drawFrame. Handy for allocating/releasing per-frame resources. |
onReadyToPlay | () => void | The composition is prepared. |
onComplete | () => void | Playback reached the end. |
onError | (error, retry) => void | Decoding failed; call retry() to re-create the player. |
Returns
currentFrame—DerivedValue<SkImage | null>: the freshly rendered frame. Pass it straight to a Skia<Image>component.player— a controller withplay(),pause(),seekTo(seconds),currentTimeandisPlaying.
Performance notes
- Give video items a
resolutionno larger than what you display: decoding 1080p to show a 300pt preview wastes decoder bandwidth and memory. drawFrameruns on the UI thread — keep per-frame allocations low and cache expensive Skia objects (paragraphs, runtime effects) between frames.- The player owns the frame textures; don't hold on to
VideoFrames across frames. Dispose anySkImagewrappers you create once drawn. - Re-creating the player (new
compositionobject identity) is not free: memoize the composition and only rebuild it when playback inputs actually change.