diff options
Diffstat (limited to 'src/lib/media/video/compress.web.ts')
-rw-r--r-- | src/lib/media/video/compress.web.ts | 41 |
1 files changed, 33 insertions, 8 deletions
diff --git a/src/lib/media/video/compress.web.ts b/src/lib/media/video/compress.web.ts index 11ccb5104..c08702534 100644 --- a/src/lib/media/video/compress.web.ts +++ b/src/lib/media/video/compress.web.ts @@ -1,12 +1,8 @@ import {VideoTooLargeError} from 'lib/media/video/errors' +import {CompressedVideo} from './types' const MAX_VIDEO_SIZE = 1024 * 1024 * 100 // 100MB -export type CompressedVideo = { - uri: string - size: number -} - // doesn't actually compress, but throws if >100MB export async function compressVideo( file: string, @@ -15,8 +11,9 @@ export async function compressVideo( onProgress?: (progress: number) => void }, ): Promise<CompressedVideo> { - const blob = await fetch(file).then(res => res.blob()) - const video = URL.createObjectURL(blob) + const {mimeType, base64} = parseDataUrl(file) + const blob = base64ToBlob(base64, mimeType) + const uri = URL.createObjectURL(blob) if (blob.size > MAX_VIDEO_SIZE) { throw new VideoTooLargeError() @@ -24,6 +21,34 @@ export async function compressVideo( return { 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}) } |