Reference version

Expo LivePhoto

GitHub

npm

A library that allows displaying Live Photos on iOS.

iOS
Bundled version:
~0.1.1

Installation

Terminal
npx expo install expo-live-photo

If you are installing this in an existing React Native app, make sure to install expo in your project.

Usage

Here's a simple example of expo-live-photo usage combined with expo-image-picker.

LivePhoto
import * as ImagePicker from 'expo-image-picker';
import { LivePhotoAsset, LivePhotoView, LivePhotoViewType } from 'expo-live-photo';
import { useRef, useState } from 'react';
import { View, StyleSheet, Text, Button } from 'react-native';

export default function LivePhotoScreen() {
  const viewRef = useRef<LivePhotoViewType>(null);
  const [livePhoto, setLivePhoto] = useState<LivePhotoAsset | null>(null);

  const pickImage = async () => {
    const result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ['livePhotos'],
    });

    if (!result.canceled && result.assets[0].pairedVideoAsset?.uri) {
      setLivePhoto({
        photoUri: result.assets[0].uri,
        pairedVideoUri: result.assets[0].pairedVideoAsset.uri,
      });
    } else {
      console.error('Failed to pick a live photo');
    }
  };

  if (!LivePhotoView.isAvailable()) {
    return (
      <View style={styles.container}>
        <Text>expo-live-photo is not available on this platform 😕</Text>
      </View>
    );
  }

  return (
    <View style={styles.container}>
      <LivePhotoView
        ref={viewRef}
        source={livePhoto}
        style={[styles.livePhotoView, { display: livePhoto ? 'flex' : 'none' }]}
        onLoadComplete={() => {
          console.log('Live photo loaded successfully!');
        }}
        onLoadError={error => {
          console.error('Failed to load the live photo: ', error.message);
        }}
      />
      <View style={livePhoto ? styles.pickImageCollapsed : styles.pickImageExpanded}>
        <Button title={livePhoto ? 'Change Image' : 'Pick an image'} onPress={pickImage} />
      </View>
      <Button title="Start Playback Hint" onPress={() => viewRef.current?.startPlayback('hint')} />
      <Button title="Start Playback" onPress={() => viewRef.current?.startPlayback('full')} />
      <Button title="Stop Playback" onPress={() => viewRef.current?.stopPlayback()} />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    paddingVertical: 20,
    paddingHorizontal: 40,
  },
  livePhotoView: {
    alignSelf: 'stretch',
    height: 300,
  },
  pickImageExpanded: {
    alignSelf: 'stretch',
    height: 300,
    justifyContent: 'center',
  },
  pickImageCollapsed: {
    marginVertical: 10,
  },
  button: {
    marginVertical: 10,
  },
});

API

import { LivePhotoView } from 'expo-live-photo';

Component

LivePhotoView

Type: React.Element<LivePhotoViewProps>

LivePhotoViewProps

contentFit

Optional • Type: ContentFit • Default: 'contain'

Determines how the image should be scaled to fit the container.

  • 'contain' - Scales the image so that its larger dimension fits the target size.
  • 'cover' - Scales the image so that it completely fills the target size.

isMuted

Optional • Type: boolean • Default: true

Determines whether the live photo should also play audio.

onLoadComplete

Optional • Type: () => void

Called when the live photo is loaded and ready to play.

onLoadError

Optional • Type: (error: LivePhotoLoadError) => void

Called when an error occurred while loading.

onLoadStart

Optional • Type: () => void

Called when the live photo starts loading.

onPlaybackStart

Optional • Type: () => void

Called when the playback starts.

onPlaybackStop

Optional • Type: () => void

Called when the playback stops.

onPreviewPhotoLoad

Optional • Type: () => void

Called when the live photo preview photo is loaded.

source

Optional • Literal type:

The live photo asset to display.

Acceptable values are: null | LivePhotoAsset

useDefaultGestureRecognizer

Optional • Type: boolean • Default: true

Determines whether the default iOS gesture recognizer should be used. When true the playback will start if the user presses and holds on the LivePhotoView.

Inherited Props

Component Methods

isAvailable()

Determines whether the current device is capable of displaying live photos.

Returns:
boolean

Types

ContentFit

Literal Type: string

Determines how the image should be scaled to fit the container.

  • 'contain' - Scales the image so that its larger dimension fits the target size.
  • 'cover' - Scales the image so that it completely fills the target size.

Acceptable values are: 'contain' | 'cover'

LivePhotoAsset

A live photo asset.

Note: Due to native limitations, the photo and video parts of the live photo must come from a valid live photo file and be unaltered. When taken, the photo is paired with the video via metadata. If the pairing is broken, joining them into a live photo is impossible.

PropertyTypeDescription
pairedVideoUristring

The URI of the video part of the live photo.

photoUristring

The URI of the photo part of the live photo.

LivePhotoLoadError

PropertyTypeDescription
messagestring

Reason for the load failure.

LivePhotoViewType

PropertyTypeDescription
startPlayback(playbackStyle: PlaybackStyle) => void

Start the playback of the video part of the live photo.

playbackStyle: PlaybackStyle

Determines which playback style to use. If not provided, the full video will be played.

stopPlayback() => void

Stop the playback of the video part of the live photo.

PlaybackStyle

Literal Type: string

Determines what style to use when playing the live photo.

  • 'hint' - A short part of the video will be played to indicate that a live photo is being displayed.
  • 'full' - The full video part will be played.

Acceptable values are: 'hint' | 'full'