diff --git a/packages/rrdom/src/diff.ts b/packages/rrdom/src/diff.ts index 8456dd3398..2e770527c2 100644 --- a/packages/rrdom/src/diff.ts +++ b/packages/rrdom/src/diff.ts @@ -133,6 +133,8 @@ export function diff( oldMediaElement.volume = newMediaRRElement.volume; if (newMediaRRElement.currentTime !== undefined) oldMediaElement.currentTime = newMediaRRElement.currentTime; + if (newMediaRRElement.playbackRate !== undefined) + oldMediaElement.playbackRate = newMediaRRElement.playbackRate; break; } case 'CANVAS': diff --git a/packages/rrdom/src/document.ts b/packages/rrdom/src/document.ts index 01074af388..f8ee5b8686 100644 --- a/packages/rrdom/src/document.ts +++ b/packages/rrdom/src/document.ts @@ -580,6 +580,7 @@ export function BaseRRMediaElementImpl< public volume?: number; public paused?: boolean; public muted?: boolean; + public playbackRate?: number; // eslint-disable-next-line @typescript-eslint/no-unused-vars attachShadow(_init: ShadowRootInit): IRRElement { throw new Error( diff --git a/packages/rrdom/test/diff.test.ts b/packages/rrdom/test/diff.test.ts index 989c9ae083..699b0aee1a 100644 --- a/packages/rrdom/test/diff.test.ts +++ b/packages/rrdom/test/diff.test.ts @@ -217,6 +217,7 @@ describe('diff algorithm for rrdom', () => { expect(element.currentTime).toEqual(0); expect(element.muted).toEqual(false); expect(element.paused).toEqual(true); + expect(element.playbackRate).toEqual(1); const rrDocument = new RRDocument(); const rrMedia = rrDocument.createElement(tagName) as RRMediaElement; @@ -224,12 +225,14 @@ describe('diff algorithm for rrdom', () => { rrMedia.currentTime = 100; rrMedia.muted = true; rrMedia.paused = false; + rrMedia.playbackRate = 0.5; diff(element, rrMedia, replayer); expect(element.volume).toEqual(0.5); expect(element.currentTime).toEqual(100); expect(element.muted).toEqual(true); expect(element.paused).toEqual(false); + expect(element.playbackRate).toEqual(0.5); rrMedia.paused = true; diff(element, rrMedia, replayer); diff --git a/packages/rrdom/test/document.test.ts b/packages/rrdom/test/document.test.ts index 32e43a9d57..c9ee13c3a0 100644 --- a/packages/rrdom/test/document.test.ts +++ b/packages/rrdom/test/document.test.ts @@ -894,6 +894,7 @@ describe('Basic RRDocument implementation', () => { expect(node.volume).toBeUndefined(); expect(node.paused).toBeUndefined(); expect(node.muted).toBeUndefined(); + expect(node.playbackRate).toBeUndefined(); expect(node.play).toBeDefined(); expect(node.pause).toBeDefined(); expect(node.toString()).toEqual('VIDEO '); diff --git a/packages/rrweb/src/record/observer.ts b/packages/rrweb/src/record/observer.ts index b11f2e2405..53bb35f14e 100644 --- a/packages/rrweb/src/record/observer.ts +++ b/packages/rrweb/src/record/observer.ts @@ -703,13 +703,19 @@ function initMediaInteractionObserver({ ) { return; } - const { currentTime, volume, muted } = target as HTMLMediaElement; + const { + currentTime, + volume, + muted, + playbackRate, + } = target as HTMLMediaElement; mediaInteractionCb({ type, id: mirror.getId(target as Node), currentTime, volume, muted, + playbackRate, }); }, sampling.media || 500); const handlers = [ @@ -717,6 +723,7 @@ function initMediaInteractionObserver({ on('pause', handler(MediaInteractions.Pause)), on('seeked', handler(MediaInteractions.Seeked)), on('volumechange', handler(MediaInteractions.VolumeChange)), + on('ratechange', handler(MediaInteractions.RateChange)), ]; return () => { handlers.forEach((h) => h()); diff --git a/packages/rrweb/src/replay/index.ts b/packages/rrweb/src/replay/index.ts index 141c3dba9a..234360ff6c 100644 --- a/packages/rrweb/src/replay/index.ts +++ b/packages/rrweb/src/replay/index.ts @@ -1188,6 +1188,9 @@ export class Replayer { // unexpeted behavior void mediaEl.play(); } + if (d.type === MediaInteractions.RateChange) { + mediaEl.playbackRate = d.playbackRate; + } } catch (error) { if (this.config.showWarning) { console.warn( diff --git a/packages/rrweb/src/types.ts b/packages/rrweb/src/types.ts index 0873cdc089..ab9ea8337e 100644 --- a/packages/rrweb/src/types.ts +++ b/packages/rrweb/src/types.ts @@ -611,6 +611,7 @@ export const enum MediaInteractions { Pause, Seeked, VolumeChange, + RateChange, } export type mediaInteractionParam = { @@ -619,6 +620,7 @@ export type mediaInteractionParam = { currentTime?: number; volume?: number; muted?: boolean; + playbackRate?: number; }; export type mediaInteractionCallback = (p: mediaInteractionParam) => void;