Instrument video probe with raw-value metrics for bitrate/HDR validation
This commit is contained in:
@@ -252,6 +252,23 @@ export type Events = {
|
|||||||
'composer:image:edit': {
|
'composer:image:edit': {
|
||||||
platform: Platform['OS']
|
platform: Platform['OS']
|
||||||
}
|
}
|
||||||
|
'composer:video:probe': {
|
||||||
|
mimeType: string
|
||||||
|
codec: string
|
||||||
|
width: number
|
||||||
|
height: number
|
||||||
|
duration: number
|
||||||
|
bitrate: number
|
||||||
|
fileSize: number
|
||||||
|
hasAudio: boolean
|
||||||
|
frameRate: number
|
||||||
|
rotation: number
|
||||||
|
isHDR: boolean
|
||||||
|
wouldCompress: boolean
|
||||||
|
}
|
||||||
|
'composer:video:probeFailed': {
|
||||||
|
safeMessage: string
|
||||||
|
}
|
||||||
'composerPrompt:press': {}
|
'composerPrompt:press': {}
|
||||||
'composerPrompt:camera:press': {}
|
'composerPrompt:camera:press': {}
|
||||||
'composerPrompt:gallery:press': {}
|
'composerPrompt:gallery:press': {}
|
||||||
|
|||||||
@@ -6,7 +6,11 @@ import {
|
|||||||
VIDEO_MAX_SIZE,
|
VIDEO_MAX_SIZE,
|
||||||
} from '#/lib/constants'
|
} from '#/lib/constants'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {compress, probe} from '../../../../modules/expo-bluesky-video-compress'
|
import {
|
||||||
|
compress,
|
||||||
|
probe,
|
||||||
|
type VideoMetadata,
|
||||||
|
} from '../../../../modules/expo-bluesky-video-compress'
|
||||||
import {
|
import {
|
||||||
COMPRESSION_MAX_DIMENSION,
|
COMPRESSION_MAX_DIMENSION,
|
||||||
COMPRESSION_PASSTHROUGH_BITRATE,
|
COMPRESSION_PASSTHROUGH_BITRATE,
|
||||||
@@ -19,6 +23,8 @@ export async function compressVideo(
|
|||||||
opts?: {
|
opts?: {
|
||||||
signal?: AbortSignal
|
signal?: AbortSignal
|
||||||
onProgress?: (progress: number) => void
|
onProgress?: (progress: number) => void
|
||||||
|
onProbe?: (metadata: VideoMetadata, wouldCompress: boolean) => void
|
||||||
|
onProbeFailed?: (error: unknown) => void
|
||||||
},
|
},
|
||||||
): Promise<CompressedVideo> {
|
): Promise<CompressedVideo> {
|
||||||
if (file.mimeType === 'image/gif') {
|
if (file.mimeType === 'image/gif') {
|
||||||
@@ -36,6 +42,7 @@ export async function compressVideo(
|
|||||||
logger.debug('probe failed, falling through to passthrough', {
|
logger.debug('probe failed, falling through to passthrough', {
|
||||||
safeMessage: e,
|
safeMessage: e,
|
||||||
})
|
})
|
||||||
|
opts?.onProbeFailed?.(e)
|
||||||
return {
|
return {
|
||||||
uri: file.uri,
|
uri: file.uri,
|
||||||
size: file.fileSize ?? -1,
|
size: file.fileSize ?? -1,
|
||||||
@@ -43,7 +50,10 @@ export async function compressVideo(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shouldCompress(metadata, isAcceptableFormat)) {
|
const willCompress = shouldCompress(metadata, isAcceptableFormat)
|
||||||
|
opts?.onProbe?.(metadata, willCompress)
|
||||||
|
|
||||||
|
if (!willCompress) {
|
||||||
return {
|
return {
|
||||||
uri: file.uri,
|
uri: file.uri,
|
||||||
size: metadata.fileSize,
|
size: metadata.fileSize,
|
||||||
|
|||||||
@@ -412,9 +412,10 @@ export const ComposePost = ({
|
|||||||
currentDid,
|
currentDid,
|
||||||
abortController.signal,
|
abortController.signal,
|
||||||
i18n,
|
i18n,
|
||||||
|
ax.metric,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
[i18n, agent, currentDid, composerDispatch],
|
[i18n, agent, currentDid, composerDispatch, ax.metric],
|
||||||
)
|
)
|
||||||
|
|
||||||
const onInitVideo = useNonReactiveCallback(() => {
|
const onInitVideo = useNonReactiveCallback(() => {
|
||||||
@@ -559,6 +560,7 @@ export const ComposePost = ({
|
|||||||
currentDid,
|
currentDid,
|
||||||
abortController.signal,
|
abortController.signal,
|
||||||
i18n,
|
i18n,
|
||||||
|
ax.metric,
|
||||||
)
|
)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error('Failed to restore video from draft', {
|
logger.error('Failed to restore video from draft', {
|
||||||
@@ -567,7 +569,7 @@ export const ComposePost = ({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[i18n, agent, currentDid, composerDispatch],
|
[i18n, agent, currentDid, composerDispatch, ax.metric],
|
||||||
)
|
)
|
||||||
|
|
||||||
const handleSelectDraft = useCallback(
|
const handleSelectDraft = useCallback(
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import {uploadVideo} from '#/lib/media/video/upload'
|
|||||||
import {createVideoAgent} from '#/lib/media/video/util'
|
import {createVideoAgent} from '#/lib/media/video/util'
|
||||||
import {isNetworkError} from '#/lib/strings/errors'
|
import {isNetworkError} from '#/lib/strings/errors'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
|
import {type AnalyticsContextType} from '#/analytics'
|
||||||
|
|
||||||
type CaptionsTrack = {lang: string; file: File}
|
type CaptionsTrack = {lang: string; file: File}
|
||||||
|
|
||||||
@@ -265,6 +266,7 @@ export async function processVideo(
|
|||||||
did: string,
|
did: string,
|
||||||
signal: AbortSignal,
|
signal: AbortSignal,
|
||||||
i18n: I18n,
|
i18n: I18n,
|
||||||
|
metric: AnalyticsContextType['metric'],
|
||||||
) {
|
) {
|
||||||
let video: CompressedVideo | undefined
|
let video: CompressedVideo | undefined
|
||||||
try {
|
try {
|
||||||
@@ -273,6 +275,27 @@ export async function processVideo(
|
|||||||
dispatch({type: 'update_progress', progress: trunc2dp(num), signal})
|
dispatch({type: 'update_progress', progress: trunc2dp(num), signal})
|
||||||
},
|
},
|
||||||
signal,
|
signal,
|
||||||
|
onProbe: (metadata, wouldCompress) => {
|
||||||
|
metric('composer:video:probe', {
|
||||||
|
mimeType: metadata.mimeType,
|
||||||
|
codec: metadata.codec,
|
||||||
|
width: metadata.width,
|
||||||
|
height: metadata.height,
|
||||||
|
duration: metadata.duration,
|
||||||
|
bitrate: metadata.bitrate,
|
||||||
|
fileSize: metadata.fileSize,
|
||||||
|
hasAudio: metadata.hasAudio,
|
||||||
|
frameRate: metadata.frameRate,
|
||||||
|
rotation: metadata.rotation,
|
||||||
|
isHDR: metadata.isHDR,
|
||||||
|
wouldCompress,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onProbeFailed: e => {
|
||||||
|
metric('composer:video:probeFailed', {
|
||||||
|
safeMessage: e instanceof Error ? e.message : String(e),
|
||||||
|
})
|
||||||
|
},
|
||||||
})
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const message = getCompressErrorMessage(e, i18n)
|
const message = getCompressErrorMessage(e, i18n)
|
||||||
|
|||||||
Reference in New Issue
Block a user