[Videos] avoid using fetch for blob handling where possible (#5041)
* avoid using fetch where possible * whoopsie wrong branch * more import fixeszio/stable
parent
c70ec1ce1a
commit
8647c8e9f5
|
@ -1,9 +1,6 @@
|
||||||
import {getVideoMetaData, Video} from 'react-native-compressor'
|
import {getVideoMetaData, Video} from 'react-native-compressor'
|
||||||
|
|
||||||
export type CompressedVideo = {
|
import {CompressedVideo} from './types'
|
||||||
uri: string
|
|
||||||
size: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function compressVideo(
|
export async function compressVideo(
|
||||||
file: string,
|
file: string,
|
||||||
|
|
|
@ -1,12 +1,8 @@
|
||||||
import {VideoTooLargeError} from 'lib/media/video/errors'
|
import {VideoTooLargeError} from 'lib/media/video/errors'
|
||||||
|
import {CompressedVideo} from './types'
|
||||||
|
|
||||||
const MAX_VIDEO_SIZE = 1024 * 1024 * 100 // 100MB
|
const MAX_VIDEO_SIZE = 1024 * 1024 * 100 // 100MB
|
||||||
|
|
||||||
export type CompressedVideo = {
|
|
||||||
uri: string
|
|
||||||
size: number
|
|
||||||
}
|
|
||||||
|
|
||||||
// doesn't actually compress, but throws if >100MB
|
// doesn't actually compress, but throws if >100MB
|
||||||
export async function compressVideo(
|
export async function compressVideo(
|
||||||
file: string,
|
file: string,
|
||||||
|
@ -15,8 +11,9 @@ export async function compressVideo(
|
||||||
onProgress?: (progress: number) => void
|
onProgress?: (progress: number) => void
|
||||||
},
|
},
|
||||||
): Promise<CompressedVideo> {
|
): Promise<CompressedVideo> {
|
||||||
const blob = await fetch(file).then(res => res.blob())
|
const {mimeType, base64} = parseDataUrl(file)
|
||||||
const video = URL.createObjectURL(blob)
|
const blob = base64ToBlob(base64, mimeType)
|
||||||
|
const uri = URL.createObjectURL(blob)
|
||||||
|
|
||||||
if (blob.size > MAX_VIDEO_SIZE) {
|
if (blob.size > MAX_VIDEO_SIZE) {
|
||||||
throw new VideoTooLargeError()
|
throw new VideoTooLargeError()
|
||||||
|
@ -24,6 +21,34 @@ export async function compressVideo(
|
||||||
|
|
||||||
return {
|
return {
|
||||||
size: blob.size,
|
size: blob.size,
|
||||||
uri: video,
|
uri,
|
||||||
|
bytes: await blob.arrayBuffer(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseDataUrl(dataUrl: string) {
|
||||||
|
const [mimeType, base64] = dataUrl.slice('data:'.length).split(';base64,')
|
||||||
|
if (!mimeType || !base64) {
|
||||||
|
throw new Error('Invalid data URL')
|
||||||
|
}
|
||||||
|
return {mimeType, base64}
|
||||||
|
}
|
||||||
|
|
||||||
|
function base64ToBlob(base64: string, mimeType: string) {
|
||||||
|
const byteCharacters = atob(base64)
|
||||||
|
const byteArrays = []
|
||||||
|
|
||||||
|
for (let offset = 0; offset < byteCharacters.length; offset += 512) {
|
||||||
|
const slice = byteCharacters.slice(offset, offset + 512)
|
||||||
|
const byteNumbers = new Array(slice.length)
|
||||||
|
|
||||||
|
for (let i = 0; i < slice.length; i++) {
|
||||||
|
byteNumbers[i] = slice.charCodeAt(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
const byteArray = new Uint8Array(byteNumbers)
|
||||||
|
byteArrays.push(byteArray)
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Blob(byteArrays, {type: mimeType})
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
export type CompressedVideo = {
|
||||||
|
uri: string
|
||||||
|
size: number
|
||||||
|
// web only, can fall back to uri if missing
|
||||||
|
bytes?: ArrayBuffer
|
||||||
|
}
|
|
@ -2,7 +2,8 @@ import {ImagePickerAsset} from 'expo-image-picker'
|
||||||
import {useMutation} from '@tanstack/react-query'
|
import {useMutation} from '@tanstack/react-query'
|
||||||
|
|
||||||
import {cancelable} from '#/lib/async/cancelable'
|
import {cancelable} from '#/lib/async/cancelable'
|
||||||
import {CompressedVideo, compressVideo} from 'lib/media/video/compress'
|
import {CompressedVideo} from '#/lib/media/video/types'
|
||||||
|
import {compressVideo} from 'lib/media/video/compress'
|
||||||
|
|
||||||
export function useCompressVideoMutation({
|
export function useCompressVideoMutation({
|
||||||
onProgress,
|
onProgress,
|
||||||
|
|
|
@ -4,7 +4,7 @@ import {useMutation} from '@tanstack/react-query'
|
||||||
import {nanoid} from 'nanoid/non-secure'
|
import {nanoid} from 'nanoid/non-secure'
|
||||||
|
|
||||||
import {cancelable} from '#/lib/async/cancelable'
|
import {cancelable} from '#/lib/async/cancelable'
|
||||||
import {CompressedVideo} from '#/lib/media/video/compress'
|
import {CompressedVideo} from '#/lib/media/video/types'
|
||||||
import {createVideoEndpointUrl} from '#/state/queries/video/util'
|
import {createVideoEndpointUrl} from '#/state/queries/video/util'
|
||||||
import {useAgent, useSession} from '#/state/session'
|
import {useAgent, useSession} from '#/state/session'
|
||||||
import {getServiceAuthAudFromUrl} from 'lib/strings/url-helpers'
|
import {getServiceAuthAudFromUrl} from 'lib/strings/url-helpers'
|
||||||
|
|
|
@ -3,7 +3,7 @@ import {useMutation} from '@tanstack/react-query'
|
||||||
import {nanoid} from 'nanoid/non-secure'
|
import {nanoid} from 'nanoid/non-secure'
|
||||||
|
|
||||||
import {cancelable} from '#/lib/async/cancelable'
|
import {cancelable} from '#/lib/async/cancelable'
|
||||||
import {CompressedVideo} from '#/lib/media/video/compress'
|
import {CompressedVideo} from '#/lib/media/video/types'
|
||||||
import {createVideoEndpointUrl} from '#/state/queries/video/util'
|
import {createVideoEndpointUrl} from '#/state/queries/video/util'
|
||||||
import {useAgent, useSession} from '#/state/session'
|
import {useAgent, useSession} from '#/state/session'
|
||||||
import {getServiceAuthAudFromUrl} from 'lib/strings/url-helpers'
|
import {getServiceAuthAudFromUrl} from 'lib/strings/url-helpers'
|
||||||
|
|
|
@ -6,8 +6,8 @@ import {useLingui} from '@lingui/react'
|
||||||
import {QueryClient, useQuery, useQueryClient} from '@tanstack/react-query'
|
import {QueryClient, useQuery, useQueryClient} from '@tanstack/react-query'
|
||||||
|
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {CompressedVideo} from 'lib/media/video/compress'
|
|
||||||
import {VideoTooLargeError} from 'lib/media/video/errors'
|
import {VideoTooLargeError} from 'lib/media/video/errors'
|
||||||
|
import {CompressedVideo} from 'lib/media/video/types'
|
||||||
import {useCompressVideoMutation} from 'state/queries/video/compress-video'
|
import {useCompressVideoMutation} from 'state/queries/video/compress-video'
|
||||||
import {useVideoAgent} from 'state/queries/video/util'
|
import {useVideoAgent} from 'state/queries/video/util'
|
||||||
import {useUploadVideoMutation} from 'state/queries/video/video-upload'
|
import {useUploadVideoMutation} from 'state/queries/video/video-upload'
|
||||||
|
|
|
@ -4,7 +4,7 @@ import {View} from 'react-native'
|
||||||
import {ImagePickerAsset} from 'expo-image-picker'
|
import {ImagePickerAsset} from 'expo-image-picker'
|
||||||
import {useVideoPlayer, VideoView} from 'expo-video'
|
import {useVideoPlayer, VideoView} from 'expo-video'
|
||||||
|
|
||||||
import {CompressedVideo} from '#/lib/media/video/compress'
|
import {CompressedVideo} from '#/lib/media/video/types'
|
||||||
import {ExternalEmbedRemoveBtn} from 'view/com/composer/ExternalEmbedRemoveBtn'
|
import {ExternalEmbedRemoveBtn} from 'view/com/composer/ExternalEmbedRemoveBtn'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React, {useEffect, useRef} from 'react'
|
||||||
import {View} from 'react-native'
|
import {View} from 'react-native'
|
||||||
import {ImagePickerAsset} from 'expo-image-picker'
|
import {ImagePickerAsset} from 'expo-image-picker'
|
||||||
|
|
||||||
import {CompressedVideo} from '#/lib/media/video/compress'
|
import {CompressedVideo} from '#/lib/media/video/types'
|
||||||
import {ExternalEmbedRemoveBtn} from 'view/com/composer/ExternalEmbedRemoveBtn'
|
import {ExternalEmbedRemoveBtn} from 'view/com/composer/ExternalEmbedRemoveBtn'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue