use source file for web video compression

Avoids the fetch(blob:) round trip in compressVideo, which copies the
bytes and throws a bare TypeError when the URL is revoked or the read
fails. Also adds errorMessage to the compressFailed metric.
This commit is contained in:
vineyardbovines
2026-07-07 15:35:12 -04:00
parent ea3d6827c7
commit 44d381aee6
4 changed files with 17 additions and 2 deletions
+2
View File
@@ -1404,6 +1404,8 @@ export type Events = {
uploadId: string
engine: string
errorClass: string
/** Truncated to 256 chars */
errorMessage: string
elapsedMs: number
}
'video:upload:uploadStarted': {
+6 -2
View File
@@ -44,8 +44,12 @@ export async function compressVideo(
hasWebCodecs: hasWebCodecs(),
})
const response = await fetch(asset.uri)
const blob = await response.blob()
/*
* Prefer the original File over re-fetching the blob URL. A fetch round
* trip copies the bytes and fails with a bare TypeError if the URL was
* revoked or the read fails - the top web compressFailed error class.
*/
const blob = asset.file ?? (await (await fetch(asset.uri)).blob())
const isGif = blob.type === 'image/gif'
const hasCodecs = hasWebCodecs()
+6
View File
@@ -26,6 +26,11 @@ function errorClass(e: unknown): string {
return 'Unknown'
}
function errorMessage(e: unknown): string {
const message = e instanceof Error ? e.message : String(e)
return message.slice(0, 256)
}
export type VideoTelemetry = {
readonly uploadId: string
readonly engine: string
@@ -208,6 +213,7 @@ export function createVideoTelemetry({
uploadId,
engine,
errorClass: errorClass(e),
errorMessage: errorMessage(e),
elapsedMs: Date.now() - phaseStartedAt,
})
endTxn('error')
@@ -72,6 +72,7 @@ async function getMetadataWithWebCodecs(
return {
uri: blobUrl,
file,
mimeType: file.type,
width: videoTrack.displayWidth,
height: videoTrack.displayHeight,
@@ -92,6 +93,7 @@ async function getMetadataWithBrowserAPIs(
img.onload = () => {
resolve({
uri: blobUrl,
file,
mimeType: 'image/gif',
width: img.width,
height: img.height,
@@ -111,6 +113,7 @@ async function getMetadataWithBrowserAPIs(
video.onloadedmetadata = () => {
resolve({
uri: blobUrl,
file,
mimeType: file.type,
width: video.videoWidth,
height: video.videoHeight,