CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-expo-media-library

Provides access to user's media library for React Native and Expo applications.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

assets.mddocs/

Asset Management

Core asset operations for creating, querying, retrieving detailed information, and deleting media assets with comprehensive metadata support including EXIF data, GPS location, and platform-specific features.

Capabilities

Query Assets

Fetches paginated assets from the media library with comprehensive filtering and sorting options.

/**
 * Fetches paginated assets matching specified criteria
 * @param assetsOptions - Options for filtering, sorting, and pagination (optional)
 * @returns Promise resolving to PagedInfo containing assets and pagination data
 */
function getAssetsAsync(assetsOptions: AssetsOptions = {}): Promise<PagedInfo<Asset>>;

interface AssetsOptions {
  /** Maximum number of assets to return per page (default: 20) */
  first?: number;
  /** Pagination cursor - asset or asset ID to start after */
  after?: AssetRef;
  /** Filter by specific album */
  album?: AlbumRef;
  /** Sort criteria - single value or array for multiple sort keys */
  sortBy?: SortByValue[] | SortByValue;
  /** Filter by media type(s) */
  mediaType?: MediaTypeValue[] | MediaTypeValue;
  /** Filter by media subtype(s) - iOS only */
  mediaSubtypes?: MediaSubtype[] | MediaSubtype;
  /** Filter assets created after this date */
  createdAfter?: Date | number;
  /** Filter assets created before this date */
  createdBefore?: Date | number;
  /** Resolve with full asset info on Android (slower but more complete) */
  resolveWithFullInfo?: boolean;
}

interface PagedInfo<T> {
  /** Array of assets for current page */
  assets: T[];
  /** Cursor for retrieving next page */
  endCursor: string;
  /** Whether more pages are available */
  hasNextPage: boolean;
  /** Estimated total count of matching assets */
  totalCount: number;
}

Usage Examples:

import * as MediaLibrary from "expo-media-library";

// Get recent photos
const photos = await MediaLibrary.getAssetsAsync({
  mediaType: MediaLibrary.MediaType.photo,
  first: 20,
  sortBy: [MediaLibrary.SortBy.creationTime, false], // Most recent first
});

// Get videos from specific album
const album = await MediaLibrary.getAlbumAsync('My Videos');
const videos = await MediaLibrary.getAssetsAsync({
  album: album,
  mediaType: MediaLibrary.MediaType.video,
  first: 10,
});

// Get assets with date range filtering
const lastWeek = new Date();
lastWeek.setDate(lastWeek.getDate() - 7);

const recentAssets = await MediaLibrary.getAssetsAsync({
  createdAfter: lastWeek,
  sortBy: MediaLibrary.SortBy.creationTime,
  first: 50,
});

// Pagination example
let allAssets = [];
let hasNext = true;
let cursor = undefined;

while (hasNext) {
  const result = await MediaLibrary.getAssetsAsync({
    first: 100,
    after: cursor,
    mediaType: MediaLibrary.MediaType.photo,
  });
  
  allAssets.push(...result.assets);
  hasNext = result.hasNextPage;
  cursor = result.endCursor;
}

Create Asset

Creates a new asset in the media library from an existing local file, commonly used to save camera photos.

/**
 * Creates asset from existing file, commonly used to save Camera photos
 * @param localUri - Local file path/URI with proper file extension
 * @param album - Album or album ID to add the asset to (optional)
 * @returns Promise resolving to the created Asset object
 */
function createAssetAsync(localUri: string, album?: AlbumRef): Promise<Asset>;

Usage Examples:

import * as MediaLibrary from "expo-media-library";
import { Camera } from "expo-camera";

// Save camera photo
const photo = await camera.takePictureAsync();
const asset = await MediaLibrary.createAssetAsync(photo.uri);

// Save to specific album
const album = await MediaLibrary.getAlbumAsync('My Photos');
const assetInAlbum = await MediaLibrary.createAssetAsync(photo.uri, album);

// Save downloaded image
const downloadedImage = 'file:///path/to/downloaded/image.jpg';
const savedAsset = await MediaLibrary.createAssetAsync(downloadedImage);

Save to Library

Saves a file to the media library without returning an asset object, useful for bulk operations.

/**
 * Saves file to media library without returning asset
 * @param localUri - Local file path/URI with proper file extension
 * @returns Promise resolving when save is complete
 */
function saveToLibraryAsync(localUri: string): Promise<void>;

Usage Examples:

import * as MediaLibrary from "expo-media-library";

// Simple save operation
await MediaLibrary.saveToLibraryAsync('file:///path/to/image.jpg');

// Bulk save multiple files
const filesToSave = [
  'file:///path/to/image1.jpg',
  'file:///path/to/image2.jpg',
  'file:///path/to/video.mp4',
];

for (const fileUri of filesToSave) {
  await MediaLibrary.saveToLibraryAsync(fileUri);
}

Get Asset Information

Retrieves detailed asset information including GPS location, local URI, EXIF metadata, and platform-specific features.

/**
 * Gets detailed asset information including GPS, URI, EXIF data
 * @param asset - Asset object or asset ID
 * @param options - Query options for network download behavior (optional)
 * @returns Promise resolving to AssetInfo with detailed metadata
 */
function getAssetInfoAsync(
  asset: AssetRef,
  options?: MediaLibraryAssetInfoQueryOptions
): Promise<AssetInfo>;

interface MediaLibraryAssetInfoQueryOptions {
  /** Whether to download asset from network if needed - iOS only */
  shouldDownloadFromNetwork?: boolean;
}

interface AssetInfo extends Asset {
  /** Local URI for accessing the asset file */
  localUri?: string;
  /** GPS location where asset was captured */
  location?: Location;
  /** EXIF metadata object */
  exif?: object;
  /** Whether asset is marked as favorite - iOS only */
  isFavorite?: boolean;
  /** Whether asset is stored in cloud - iOS only */
  isNetworkAsset?: boolean;
  /** Image orientation value - iOS only */
  orientation?: number;
  /** Paired video asset for Live Photos - iOS only */
  pairedVideoAsset?: Asset | null;
}

Usage Examples:

import * as MediaLibrary from "expo-media-library";

// Get basic asset info
const assets = await MediaLibrary.getAssetsAsync({ first: 1 });
const assetInfo = await MediaLibrary.getAssetInfoAsync(assets.assets[0]);

console.log('Local URI:', assetInfo.localUri);
console.log('Location:', assetInfo.location);
console.log('EXIF data:', assetInfo.exif);

// Get info with network download (iOS)
const networkAssetInfo = await MediaLibrary.getAssetInfoAsync(
  assetId,
  { shouldDownloadFromNetwork: true }
);

// Access specific EXIF data
if (assetInfo.exif) {
  console.log('Camera make:', assetInfo.exif.Make);
  console.log('Camera model:', assetInfo.exif.Model);
  console.log('ISO:', assetInfo.exif.ISOSpeedRatings);
}

// Check for Live Photo (iOS)
if (assetInfo.pairedVideoAsset) {
  console.log('This is a Live Photo with video:', assetInfo.pairedVideoAsset.uri);
}

Delete Assets

Deletes one or more assets from the media library permanently.

/**
 * Deletes assets from the media library
 * @param assets - Single asset or array of assets/asset IDs to delete
 * @returns Promise resolving to boolean indicating success
 */
function deleteAssetsAsync(assets: AssetRef[] | AssetRef): Promise<boolean>;

Usage Examples:

import * as MediaLibrary from "expo-media-library";

// Delete single asset
const asset = await MediaLibrary.getAssetsAsync({ first: 1 });
const success = await MediaLibrary.deleteAssetsAsync(asset.assets[0]);

// Delete multiple assets
const assets = await MediaLibrary.getAssetsAsync({ first: 5 });
const deleteSuccess = await MediaLibrary.deleteAssetsAsync(assets.assets);

// Delete by asset IDs
const assetIds = ['asset-id-1', 'asset-id-2', 'asset-id-3'];
const deletedIds = await MediaLibrary.deleteAssetsAsync(assetIds);

// Conditional deletion
const oldAssets = await MediaLibrary.getAssetsAsync({
  createdBefore: new Date('2020-01-01'),
  first: 100,
});

if (oldAssets.assets.length > 0) {
  const deleted = await MediaLibrary.deleteAssetsAsync(oldAssets.assets);
  console.log(`Deleted ${deleted ? oldAssets.assets.length : 0} old assets`);
}

Types

interface Asset {
  /** Unique identifier for the asset */
  id: string;
  /** Asset filename */
  filename: string;
  /** Asset URI (ph:// on iOS, file:// on Android) */
  uri: string;
  /** Media type of the asset */
  mediaType: MediaTypeValue;
  /** Media subtypes array - iOS only */
  mediaSubtypes?: MediaSubtype[];
  /** Asset width in pixels */
  width: number;
  /** Asset height in pixels */
  height: number;
  /** Creation timestamp in milliseconds */
  creationTime: number;
  /** Last modification timestamp in milliseconds */
  modificationTime: number;
  /** Duration in seconds (0 for photos) */
  duration: number;
  /** Album ID containing this asset - Android only */
  albumId?: string;
}

interface Location {
  /** Latitude coordinate */
  latitude: number;
  /** Longitude coordinate */
  longitude: number;
  /** Altitude in meters (optional) */
  altitude?: number;
  /** Accuracy in meters (optional) */
  accuracy?: number;
}

type MediaTypeValue = 'audio' | 'photo' | 'video' | 'unknown' | 'pairedVideo';

/**
 * Media subtypes available on iOS
 * @platform ios
 */
type MediaSubtype = 
  | 'depthEffect'      // Portrait mode photos
  | 'hdr'              // HDR photos
  | 'highFrameRate'    // High frame rate videos
  | 'livePhoto'        // Live Photos
  | 'panorama'         // Panorama photos
  | 'screenshot'       // Screenshots
  | 'stream'           // Streamed videos
  | 'timelapse'        // Time-lapse videos
  | 'spatialMedia'     // Spatial media (Vision Pro)
  | 'videoCinematic';  // Cinematic mode videos

type SortByValue = [SortByKey, boolean] | SortByKey;

type SortByKey = 
  | 'default'
  | 'mediaType'
  | 'width'
  | 'height'
  | 'creationTime'
  | 'modificationTime'
  | 'duration';

type AssetRef = Asset | string;

Platform-Specific Features

iOS

  • Live Photos: Access paired video assets through pairedVideoAsset
  • Media Subtypes: Rich filtering by photo/video types like HDR, panorama, Live Photo
  • Favorites: Access favorite status through isFavorite
  • Network Assets: Handle iCloud photos with isNetworkAsset and download options
  • Orientation: Access image orientation metadata

Android

  • Scoped Storage: Full support for Android R+ scoped storage requirements
  • Album IDs: Direct access to album associations through albumId
  • Full Resolution: Access to full resolution assets without iOS limitations
  • Media Location: Optional ACCESS_MEDIA_LOCATION permission for GPS data

Web

  • Limited Support: Basic asset listing and file access through browser APIs
  • No Native Features: EXIF, GPS, and advanced metadata not available

docs

albums.md

assets.md

events.md

index.md

permissions.md

tile.json