diff --git a/frontend/app/player/mobile/managers/SnapshotManager.ts b/frontend/app/player/mobile/managers/SnapshotManager.ts index ad69addba..c0090633f 100644 --- a/frontend/app/player/mobile/managers/SnapshotManager.ts +++ b/frontend/app/player/mobile/managers/SnapshotManager.ts @@ -12,7 +12,7 @@ export default class SnapshotManager extends ListWalker { private snapshots: Snapshots = {} public mapToSnapshots(files: TarFile[]) { - const filenameRegexp = /(\d+)_1_(\d+)\.(jpeg|webp)$/; + const filenameRegexp = /(\d+)_1_(\d+)\.(jpeg|png|avif|webp)$/; const firstPair = files[0].name.match(filenameRegexp) const sessionStart = firstPair ? parseInt(firstPair[1], 10) : 0 files.forEach(file => { diff --git a/frontend/app/player/web/managers/CanvasManager.ts b/frontend/app/player/web/managers/CanvasManager.ts index ea2610ebe..07eb6ac8b 100644 --- a/frontend/app/player/web/managers/CanvasManager.ts +++ b/frontend/app/player/web/managers/CanvasManager.ts @@ -86,7 +86,7 @@ export default class CanvasManager extends ListWalker { public mapToSnapshots(files: TarFile[]) { const tempArr: Timestamp[] = []; - const filenameRegexp = /(\d+)_(\d+)_(\d+)\.(jpeg|webp)$/; + const filenameRegexp = /(\d+)_(\d+)_(\d+)\.(jpeg|png|avif|webp)$/; const firstPair = files[0].name.match(filenameRegexp); if (!firstPair) { console.error('Invalid file name format', files[0].name); diff --git a/tracker/tracker/CHANGELOG.md b/tracker/tracker/CHANGELOG.md index 769ef43ea..728314b2c 100644 --- a/tracker/tracker/CHANGELOG.md +++ b/tracker/tracker/CHANGELOG.md @@ -1,3 +1,7 @@ +# 13.0.2 + +- more file extensions for canvas + # 13.0.1 - moved canvas snapshots to webp, additional option to utilize useAnimationFrame method (for webgl) diff --git a/tracker/tracker/package.json b/tracker/tracker/package.json index 79797e080..c2ad9cf4f 100644 --- a/tracker/tracker/package.json +++ b/tracker/tracker/package.json @@ -1,7 +1,7 @@ { "name": "@openreplay/tracker", "description": "The OpenReplay tracker main package", - "version": "13.0.1-4", + "version": "13.0.2", "keywords": [ "logging", "replay" diff --git a/tracker/tracker/src/main/app/canvas.ts b/tracker/tracker/src/main/app/canvas.ts index 0f6c12460..01da58f8d 100644 --- a/tracker/tracker/src/main/app/canvas.ts +++ b/tracker/tracker/src/main/app/canvas.ts @@ -15,17 +15,20 @@ interface Options { isDebug?: boolean fixedScaling?: boolean useAnimationFrame?: boolean + fileExt?: 'webp' | 'png' | 'jpeg' | 'avif' } class CanvasRecorder { private snapshots: Record = {} private readonly intervals: NodeJS.Timeout[] = [] private readonly interval: number + private readonly fileExt: 'webp' | 'png' | 'jpeg' | 'avif' constructor( private readonly app: App, private readonly options: Options, ) { + this.fileExt = options.fileExt ?? 'webp' this.interval = 1000 / options.fps } @@ -98,6 +101,7 @@ class CanvasRecorder { this.options.quality, this.snapshots[id].dummy, this.options.fixedScaling, + this.fileExt, (blob) => { if (!blob) return this.snapshots[id].images.push({ id: this.app.timestamp(), data: blob }) @@ -137,9 +141,9 @@ class CanvasRecorder { images.forEach((snapshot) => { const blob = snapshot.data if (!blob) return - formData.append('snapshot', blob, `${createdAt}_${canvasId}_${snapshot.id}.webp`) + formData.append('snapshot', blob, `${createdAt}_${canvasId}_${snapshot.id}.${this.fileExt}`) if (this.options.isDebug) { - saveImageData(blob, `${createdAt}_${canvasId}_${snapshot.id}.webp`) + saveImageData(blob, `${createdAt}_${canvasId}_${snapshot.id}.${this.fileExt}`) } }) @@ -175,9 +179,10 @@ function captureSnapshot( quality: 'low' | 'medium' | 'high' = 'medium', dummy: HTMLCanvasElement, fixedScaling = false, + fileExt: 'webp' | 'png' | 'jpeg' | 'avif', onBlob: (blob: Blob | null) => void, ) { - const imageFormat = 'image/webp' + const imageFormat = `image/${fileExt}` if (fixedScaling) { const canvasScaleRatio = window.devicePixelRatio || 1 dummy.width = canvas.width / canvasScaleRatio diff --git a/tracker/tracker/src/main/app/index.ts b/tracker/tracker/src/main/app/index.ts index 388876de8..4880ac472 100644 --- a/tracker/tracker/src/main/app/index.ts +++ b/tracker/tracker/src/main/app/index.ts @@ -117,19 +117,36 @@ type AppOptions = { __is_snippet: boolean __debug_report_edp: string | null __debug__?: ILogLevel + /** @deprecated see canvas prop */ __save_canvas_locally?: boolean + /** @deprecated see canvas prop */ fixedCanvasScaling?: boolean localStorage: Storage | null sessionStorage: Storage | null forceSingleTab?: boolean + /** Sometimes helps to prevent session breaking due to dict reset */ disableStringDict?: boolean assistSocketHost?: string + /** @deprecated see canvas prop */ disableCanvas?: boolean canvas: { disableCanvas?: boolean + /** + * If you expect HI-DPI users mostly, this will render canvas + * in 1:1 pixel ratio + * */ fixedCanvasScaling?: boolean __save_canvas_locally?: boolean + /** + * Use with care since it hijacks one frame each time it captures + * snapshot for every canvas + * */ useAnimationFrame?: boolean + /** + * Use webp unless it produces too big images + * @default webp + * */ + fileExt?: 'webp' | 'png' | 'jpeg' | 'avif' } /** @deprecated */