import {getVideoMetaData, Video} from 'react-native-compressor' import {type ImagePickerAsset} from 'expo-image-picker' import {SUPPORTED_MIME_TYPES, type SupportedMimeTypes} from '#/lib/constants' import {type CompressedVideo} from './types' import {extToMime} from './util' const MIN_SIZE_FOR_COMPRESSION = 25 // 25mb export async function compressVideo( file: ImagePickerAsset, opts?: { signal?: AbortSignal onProgress?: (progress: number) => void }, ): Promise { const {onProgress, signal} = opts || {} const isAcceptableFormat = SUPPORTED_MIME_TYPES.includes( file.mimeType as SupportedMimeTypes, ) if (file.mimeType === 'image/gif') { // let's hope they're small enough that they don't need compression! // this compression library doesn't support gifs // worst case - server rejects them. I think that's fine -sfn return {uri: file.uri, size: file.fileSize ?? -1, mimeType: 'image/gif'} } const minimumFileSizeForCompress = isAcceptableFormat ? MIN_SIZE_FOR_COMPRESSION : 0 const compressed = await Video.compress( file.uri, { compressionMethod: 'manual', bitrate: 3_000_000, // 3mbps maxSize: 1920, // WARNING: this ONE SPECIFIC ARG is in MB -sfn minimumFileSizeForCompress, getCancellationId: id => { if (signal) { signal.addEventListener('abort', () => { Video.cancelCompression(id) }) } }, }, onProgress, ) const info = await getVideoMetaData(compressed) return {uri: compressed, size: info.size, mimeType: extToMime(info.extension)} }