fix dataurl roundtripping

This commit is contained in:
Samuel Newman
2026-03-12 11:16:41 +02:00
parent 997f0006a3
commit fa1a8f3d90
4 changed files with 78 additions and 111 deletions
+14 -35
View File
@@ -4,7 +4,7 @@ import {VIDEO_MAX_SIZE} from '#/lib/constants'
import {VideoTooLargeError} from '#/lib/media/video/errors'
import {type CompressedVideo} from './types'
// doesn't actually compress, converts to ArrayBuffer
// doesn't actually compress, just reads the File bytes
export async function compressVideo(
asset: ImagePickerAsset,
_opts?: {
@@ -12,45 +12,24 @@ export async function compressVideo(
onProgress?: (progress: number) => void
},
): Promise<CompressedVideo> {
const {mimeType, base64} = parseDataUrl(asset.uri)
const blob = base64ToBlob(base64, mimeType)
const uri = URL.createObjectURL(blob)
let bytes: ArrayBuffer
if (asset.file) {
bytes = await asset.file.arrayBuffer()
} else {
// fallback: fetch from blob/object URL
bytes = await fetch(asset.uri).then(res => res.arrayBuffer())
}
if (blob.size > VIDEO_MAX_SIZE) {
if (bytes.byteLength > VIDEO_MAX_SIZE) {
throw new VideoTooLargeError()
}
const mimeType = asset.mimeType ?? asset.file?.type ?? 'video/mp4'
return {
size: blob.size,
uri,
bytes: await blob.arrayBuffer(),
size: bytes.byteLength,
uri: asset.uri,
bytes,
mimeType,
}
}
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})
}