From a307c5c5bb320bc4cc08270de1379ac1c568c076 Mon Sep 17 00:00:00 2001 From: yz-yu Date: Sun, 16 Jan 2022 15:39:43 +0800 Subject: [PATCH] impl #796 observe media volume change (#798) --- docs/recipes/optimize-storage.md | 4 +++- docs/recipes/optimize-storage.zh_CN.md | 2 ++ packages/rrweb/src/record/observer.ts | 29 ++++++++++++++++---------- packages/rrweb/src/replay/index.ts | 6 ++++++ packages/rrweb/src/types.ts | 7 +++++++ 5 files changed, 36 insertions(+), 12 deletions(-) diff --git a/docs/recipes/optimize-storage.md b/docs/recipes/optimize-storage.md index 5ae91476..f93fe772 100644 --- a/docs/recipes/optimize-storage.md +++ b/docs/recipes/optimize-storage.md @@ -31,9 +31,11 @@ rrweb.record({ // do not record mouse movement mousemove: false // do not record mouse interaction - mouseInteraction: false, + mouseInteraction: false // set the interval of scrolling event scroll: 150 // do not emit twice in 150ms + // set the interval of media interaction event + media: 800 // set the timing of record input input: 'last' // When input mulitple characters, only record the final input } diff --git a/docs/recipes/optimize-storage.zh_CN.md b/docs/recipes/optimize-storage.zh_CN.md index 6d044346..f878ac81 100644 --- a/docs/recipes/optimize-storage.zh_CN.md +++ b/docs/recipes/optimize-storage.zh_CN.md @@ -34,6 +34,8 @@ rrweb.record({ mouseInteraction: false, // 设置滚动事件的触发频率 scroll: 150 // 每 150ms 最多触发一次 + // set the interval of media interaction event + media: 800 // 设置输入事件的录制时机 input: 'last' // 连续输入时,只录制最终值 } diff --git a/packages/rrweb/src/record/observer.ts b/packages/rrweb/src/record/observer.ts index 26cd1ef7..d59e57d4 100644 --- a/packages/rrweb/src/record/observer.ts +++ b/packages/rrweb/src/record/observer.ts @@ -684,22 +684,28 @@ function initMediaInteractionObserver( mediaInteractionCb: mediaInteractionCallback, blockClass: blockClass, mirror: Mirror, + sampling: SamplingStrategy, ): listenerHandler { - const handler = (type: MediaInteractions) => (event: Event) => { - const target = getEventTarget(event); - if (!target || isBlocked(target as Node, blockClass)) { - return; - } - mediaInteractionCb({ - type, - id: mirror.getId(target as INode), - currentTime: (target as HTMLMediaElement).currentTime, - }); - }; + const handler = (type: MediaInteractions) => + throttle((event: Event) => { + const target = getEventTarget(event); + if (!target || isBlocked(target as Node, blockClass)) { + return; + } + const { currentTime, volume, muted } = target as HTMLMediaElement; + mediaInteractionCb({ + type, + id: mirror.getId(target as INode), + currentTime, + volume, + muted, + }); + }, sampling.media || 500); const handlers = [ on('play', handler(MediaInteractions.Play)), on('pause', handler(MediaInteractions.Pause)), on('seeked', handler(MediaInteractions.Seeked)), + on('volumechange', handler(MediaInteractions.VolumeChange)), ]; return () => { handlers.forEach((h) => h()); @@ -987,6 +993,7 @@ export function initObservers( o.mediaInteractionCb, o.blockClass, o.mirror, + o.sampling, ); const styleSheetObserver = initStyleSheetObserver( diff --git a/packages/rrweb/src/replay/index.ts b/packages/rrweb/src/replay/index.ts index 8e4b56d2..7aa26e54 100644 --- a/packages/rrweb/src/replay/index.ts +++ b/packages/rrweb/src/replay/index.ts @@ -1019,6 +1019,12 @@ export class Replayer { if (d.currentTime) { mediaEl.currentTime = d.currentTime; } + if (d.volume) { + mediaEl.volume = d.volume; + } + if (d.muted) { + mediaEl.muted = d.muted; + } if (d.type === MediaInteractions.Pause) { mediaEl.pause(); } diff --git a/packages/rrweb/src/types.ts b/packages/rrweb/src/types.ts index 4f881ecb..da904dee 100644 --- a/packages/rrweb/src/types.ts +++ b/packages/rrweb/src/types.ts @@ -192,6 +192,10 @@ export type SamplingStrategy = Partial<{ * number is the throttle threshold of recording scroll */ scroll: number; + /** + * number is the throttle threshold of recording media interactions + */ + media: number; /** * 'all' will record all the input events * 'last' will only record the last input value while input a sequence of chars @@ -472,12 +476,15 @@ export const enum MediaInteractions { Play, Pause, Seeked, + VolumeChange, } export type mediaInteractionParam = { type: MediaInteractions; id: number; currentTime?: number; + volume?: number; + muted?: boolean; }; export type mediaInteractionCallback = (p: mediaInteractionParam) => void;