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:
@@ -1404,6 +1404,8 @@ export type Events = {
|
|||||||
uploadId: string
|
uploadId: string
|
||||||
engine: string
|
engine: string
|
||||||
errorClass: string
|
errorClass: string
|
||||||
|
/** Truncated to 256 chars */
|
||||||
|
errorMessage: string
|
||||||
elapsedMs: number
|
elapsedMs: number
|
||||||
}
|
}
|
||||||
'video:upload:uploadStarted': {
|
'video:upload:uploadStarted': {
|
||||||
|
|||||||
@@ -44,8 +44,12 @@ export async function compressVideo(
|
|||||||
hasWebCodecs: hasWebCodecs(),
|
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 isGif = blob.type === 'image/gif'
|
||||||
const hasCodecs = hasWebCodecs()
|
const hasCodecs = hasWebCodecs()
|
||||||
|
|||||||
@@ -26,6 +26,11 @@ function errorClass(e: unknown): string {
|
|||||||
return 'Unknown'
|
return 'Unknown'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function errorMessage(e: unknown): string {
|
||||||
|
const message = e instanceof Error ? e.message : String(e)
|
||||||
|
return message.slice(0, 256)
|
||||||
|
}
|
||||||
|
|
||||||
export type VideoTelemetry = {
|
export type VideoTelemetry = {
|
||||||
readonly uploadId: string
|
readonly uploadId: string
|
||||||
readonly engine: string
|
readonly engine: string
|
||||||
@@ -208,6 +213,7 @@ export function createVideoTelemetry({
|
|||||||
uploadId,
|
uploadId,
|
||||||
engine,
|
engine,
|
||||||
errorClass: errorClass(e),
|
errorClass: errorClass(e),
|
||||||
|
errorMessage: errorMessage(e),
|
||||||
elapsedMs: Date.now() - phaseStartedAt,
|
elapsedMs: Date.now() - phaseStartedAt,
|
||||||
})
|
})
|
||||||
endTxn('error')
|
endTxn('error')
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ async function getMetadataWithWebCodecs(
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
uri: blobUrl,
|
uri: blobUrl,
|
||||||
|
file,
|
||||||
mimeType: file.type,
|
mimeType: file.type,
|
||||||
width: videoTrack.displayWidth,
|
width: videoTrack.displayWidth,
|
||||||
height: videoTrack.displayHeight,
|
height: videoTrack.displayHeight,
|
||||||
@@ -92,6 +93,7 @@ async function getMetadataWithBrowserAPIs(
|
|||||||
img.onload = () => {
|
img.onload = () => {
|
||||||
resolve({
|
resolve({
|
||||||
uri: blobUrl,
|
uri: blobUrl,
|
||||||
|
file,
|
||||||
mimeType: 'image/gif',
|
mimeType: 'image/gif',
|
||||||
width: img.width,
|
width: img.width,
|
||||||
height: img.height,
|
height: img.height,
|
||||||
@@ -111,6 +113,7 @@ async function getMetadataWithBrowserAPIs(
|
|||||||
video.onloadedmetadata = () => {
|
video.onloadedmetadata = () => {
|
||||||
resolve({
|
resolve({
|
||||||
uri: blobUrl,
|
uri: blobUrl,
|
||||||
|
file,
|
||||||
mimeType: file.type,
|
mimeType: file.type,
|
||||||
width: video.videoWidth,
|
width: video.videoWidth,
|
||||||
height: video.videoHeight,
|
height: video.videoHeight,
|
||||||
|
|||||||
Reference in New Issue
Block a user