@hypervideo-dev/expo
v0.1.2
Published
Native iOS Metal-based stacked-alpha transparent video player - fixes Skia GC crashes
Maintainers
Readme
@hypervideo-dev/expo-native
Native iOS Metal-based stacked-alpha video player for Expo/React Native.
Requirements
- Expo SDK: 54.0.0+
- React Native: 0.76.0+
- expo-modules-core: 3.0.0+
- iOS: 15.0+
- Development Build: Required (not compatible with Expo Go)
Why Native?
The standard @hypervideo-dev/expo package uses Skia for cross-platform video rendering. However, under heavy usage (e.g., continuous voice sessions with frequent video playback), you may encounter EXC_BREAKPOINT crashes caused by JsiSkImage destructors running on the Hermes GC thread instead of the main/GPU thread.
This native package bypasses JSI entirely by using a pure Metal implementation, eliminating these GC-related crashes.
Platform Support
- iOS: Full support with Metal GPU acceleration
- Android: Not yet supported (PRs welcome!)
Installation
npm install @hypervideo-dev/expo-native
# or
yarn add @hypervideo-dev/expo-native
# or
pnpm add @hypervideo-dev/expo-nativeAfter installing, rebuild your iOS app:
npx expo run:iosNote: This package requires a development build. It will not work with Expo Go since it contains native iOS code.
Usage
import { StackedAlphaVideo } from '@hypervideo-dev/expo-native';
function MyComponent() {
return (
<StackedAlphaVideo
src="https://example.com/stacked-alpha-video.mp4"
style={{ width: 300, height: 300 }}
autoPlay
loop
muted
onLoad={() => console.log('Video ready')}
onEnd={() => console.log('Video ended')}
onError={(error) => console.error('Video error:', error)}
/>
);
}
// Alternative: Using source prop (object or require)
<StackedAlphaVideo
source={{ uri: 'https://example.com/video.mp4' }}
// or: source={require('./video.mp4')}
/>Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| src | string | - | Video source URL (string) - compatible with @hypervideo-dev/expo |
| source | { uri: string } \| number | - | Video source URL or local asset via require() |
| style | ViewStyle | - | Style for the video container (controls sizing) |
| width | number | - | Optional dimension hint (debugging only) |
| height | number | - | Optional dimension hint (debugging only) |
| loop | boolean | true | Whether to loop the video |
| autoPlay | boolean | true | Whether to auto-play when loaded |
| paused | boolean | false | Whether playback is paused |
| muted | boolean | true | Whether audio is muted |
| onLoad | () => void | - | Called when video is ready |
| onEnd | () => void | - | Called when video ends (if loop=false) |
| onError | (error: string) => void | - | Called on error |
Note: Either
srcorsourcemust be provided. If both are provided,srctakes precedence.
Video Format
This component expects stacked-alpha format videos:
- Top half: RGB color frames
- Bottom half: Grayscale alpha/mask
The Metal shader samples both halves and composites them in real-time for transparent video playback.
When to Use This vs @hypervideo-dev/expo
| Use Case | Recommended Package |
|----------|---------------------|
| Cross-platform (iOS + Android) | @hypervideo-dev/expo |
| Heavy iOS usage with Skia crashes | @hypervideo-dev/expo-native |
| Maximum iOS performance | @hypervideo-dev/expo-native |
| Android-only project | @hypervideo-dev/expo |
Example App
An example app is included in the example/ directory for local testing:
cd packages/expo-native/example
# Install dependencies (use npm, not pnpm, to avoid monorepo hoisting issues)
npm install
# Run on iOS simulator
npx expo run:iosLicense
MIT
