diff --git a/src/analytics/metrics/types.ts b/src/analytics/metrics/types.ts index 3cb707733f..b988595bb2 100644 --- a/src/analytics/metrics/types.ts +++ b/src/analytics/metrics/types.ts @@ -1404,6 +1404,8 @@ export type Events = { uploadId: string engine: string errorClass: string + /** Truncated to 256 chars */ + errorMessage: string elapsedMs: number } 'video:upload:uploadStarted': { diff --git a/src/lib/media/video/compress.web.ts b/src/lib/media/video/compress.web.ts index 46fff5b058..aba5f1ec0a 100644 --- a/src/lib/media/video/compress.web.ts +++ b/src/lib/media/video/compress.web.ts @@ -36,8 +36,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() diff --git a/src/lib/media/video/telemetry.ts b/src/lib/media/video/telemetry.ts index 34eb431420..67ff77c58e 100644 --- a/src/lib/media/video/telemetry.ts +++ b/src/lib/media/video/telemetry.ts @@ -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') diff --git a/src/view/com/composer/videos/metadata.web.ts b/src/view/com/composer/videos/metadata.web.ts index 920dcdb6af..ed87d157c9 100644 --- a/src/view/com/composer/videos/metadata.web.ts +++ b/src/view/com/composer/videos/metadata.web.ts @@ -73,6 +73,7 @@ async function getMetadataWithWebCodecs( return { uri: blobUrl, + file, mimeType: file.type, width: videoTrack.displayWidth, height: videoTrack.displayHeight, @@ -93,6 +94,7 @@ async function getMetadataWithBrowserAPIs( img.onload = () => { resolve({ uri: blobUrl, + file, mimeType: 'image/gif', width: img.width, height: img.height, @@ -112,6 +114,7 @@ async function getMetadataWithBrowserAPIs( video.onloadedmetadata = () => { resolve({ uri: blobUrl, + file, mimeType: file.type, width: video.videoWidth, height: video.videoHeight,