forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {getVideoMetaData, Video} from 'react-native-compressor'
2import {type ImagePickerAsset} from 'expo-image-picker'
3
4import {SUPPORTED_MIME_TYPES, type SupportedMimeTypes} from '#/lib/constants'
5import {type CompressedVideo} from './types'
6import {extToMime} from './util'
7
8const MIN_SIZE_FOR_COMPRESSION = 25 // 25mb
9
10export async function compressVideo(
11 file: ImagePickerAsset,
12 opts?: {
13 signal?: AbortSignal
14 onProgress?: (progress: number) => void
15 },
16): Promise<CompressedVideo> {
17 const {onProgress, signal} = opts || {}
18
19 const isAcceptableFormat = SUPPORTED_MIME_TYPES.includes(
20 file.mimeType as SupportedMimeTypes,
21 )
22
23 if (file.mimeType === 'image/gif') {
24 // let's hope they're small enough that they don't need compression!
25 // this compression library doesn't support gifs
26 // worst case - server rejects them. I think that's fine -sfn
27 return {uri: file.uri, size: file.fileSize ?? -1, mimeType: 'image/gif'}
28 }
29
30 const minimumFileSizeForCompress = isAcceptableFormat
31 ? MIN_SIZE_FOR_COMPRESSION
32 : 0
33
34 const compressed = await Video.compress(
35 file.uri,
36 {
37 compressionMethod: 'manual',
38 bitrate: 3_000_000, // 3mbps
39 maxSize: 1920,
40 // WARNING: this ONE SPECIFIC ARG is in MB -sfn
41 minimumFileSizeForCompress,
42 getCancellationId: id => {
43 if (signal) {
44 signal.addEventListener('abort', () => {
45 Video.cancelCompression(id)
46 })
47 }
48 },
49 },
50 onProgress,
51 )
52
53 const info = await getVideoMetaData(compressed)
54
55 return {uri: compressed, size: info.size, mimeType: extToMime(info.extension)}
56}