Skip to content

feat: Add V3 background segmentation video frame processor#3223

Merged
dinmin-amzn merged 1 commit into
mainfrom
background-segmentation-v3
Jun 23, 2026
Merged

feat: Add V3 background segmentation video frame processor#3223
dinmin-amzn merged 1 commit into
mainfrom
background-segmentation-v3

Conversation

@harshhv-dev

@harshhv-dev harshhv-dev commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Issue #:
Implement a new CDN-based background segmentation processor that supports blur (low/medium/high), image replacement, and color replacement effects with two model types (selfie_general and selfie_multiclass).

Description of changes:
Core:

  • BackgroundSegmentationVideoFrameProcessor with CDN asset loading
  • BackgroundSegmentationAssetLoader with request deduplication
  • BackgroundSegmentationCompatibilityChecker (WebGL2, WASM, Workers)
  • BackgroundSegmentationMetrics observer for StatsCollector integration
  • Dynamic filter switching via setConfig/setModelType without recreation

Observability:

  • Video processor metrics (frame rate, per-processor latency) via StatsCollector
  • Event publishing for filter lifecycle (backgroundFilterStarted, backgroundFilterConfigSelected, backgroundFilterFailed)
  • Extended VideoFXEventAttributes with V3-specific fields

Demo:

  • Replace legacy MediaPipe/TensorFlow-based filters with V3 segmentation
  • Add blur strength options (low/medium/high) for both model types
  • Fix iOS crash on rapid filter switching (concurrency guard)
  • Fix filter re-application after offline/online transition
  • Remove @tensorflow-models/body-segmentation dependency

Integration tests:

  • Replace V2 VideoFx integration tests with V3 background segmentation tests
  • Add reusable VideoTestSteps: addVideoFxBackgroundColorReplacementSteps, addVideoFxBackgroundBlurSteps, addVideoFxBackgroundImageReplacementSteps
  • Each utility method supports model parameter (general/multiclass) for both model variants
  • Color replacement verified via blue pixel percentage check (40-100% threshold)
  • Blur verified via pixel sum diff check (minSignificantDiff: 1000)
  • Image replacement verified via pixel sum diff check (minSignificantDiff: 10000)
  • Add fake video stream (output.y4m) with person on white background for deterministic pixel checks
  • Update MeetingPage with background segmentation filter element selectors and enableBackgroundSegmentationFilterButtons methods

Testing:

  • V3 functionalities were successfully tested with working demo app.

Can these tested using a demo application? Please provide reproducible step-by-step instructions.
Yes, these changes can be tested using demo application. Here are the steps:

  1. Start the demo:
     cd demos/browser
     npm run start
  1. Open http://localhost:8080 in your browser
  2. Enter a meeting title, your name, and click Continue
  3. Join the meeting with audio/video enabled
  4. Open the Video Filter dropdown and select any "BackgroundSegmentation" option:
    - BackgroundSegmentation - (Blue) — replaces background with solid blue using general model variant
    - BackgroundSegmentation - (Blur Low) / (Blur Medium) / (Blur High) - replaces background with blur effect using general model variant
    - BackgroundSegmentation - (Replacement) — replaces background with encoded image using general model variant
    - BackgroundSegmentation - (Multiclass-Blue) — replaces background with solid blue using multiclass model variant
    - BackgroundSegmentation - (Multiclass-Blur Low/Medium/High) — replaces background with blur effect using multiclass model variant
    - BackgroundSegmentation - (Multiclass-Replacement) — replaces background with encoded image using multiclass model variant
  5. Verify the filter applies to the local video tile
  6. Switch between background segmentation filters — should transition smoothly without delay
  7. Select "None" to disable the filter

Checklist:

  1. Have you successfully run npm run build:release locally? Yes

  2. Do you add, modify, or delete public API definitions? If yes, has that been reviewed and approved?

  3. Do you change the wire protocol, e.g. the request method? If yes, has that been reviewed and approved?

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@harshhv-dev
harshhv-dev requested a review from a team as a code owner June 5, 2026 00:57
@harshhv-dev
harshhv-dev marked this pull request as draft June 5, 2026 01:02
@harshhv-dev
harshhv-dev force-pushed the background-segmentation-v3 branch 13 times, most recently from 72f5adb to fd06b99 Compare June 12, 2026 00:13
@harshhv-dev
harshhv-dev marked this pull request as ready for review June 12, 2026 00:17
@harshhv-dev

Copy link
Copy Markdown
Contributor Author

Note: Multiclass-model based integration tests in VideoProcessingTest are currently disabled to avoid flaky WebGL/GPU resource exhaustion issue causing script timeouts in headless Chrome CI during Github workflow run for VideoProcessingTest. One of the examples for successful test run can be found here

static async create(
logger: Logger,
config: BackgroundSegmentationVideoFrameProcessorConfig,
modelType: ModelType = ModelType.SELFIE_GENERAL,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we were defaulting to multi-class?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default matches the CDN processor's default. We decided to default to SELFIE_GENERAL because the multiclass model (18MB) auto-downgrades to general on CPU-only and low-performance devices as part of QA bugs fix for some device-specific issues.
cc: @dinmin-amzn

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think it's reasonable, but how drastric is the auto downgrade? as a followup how can we get more default users on multiclass?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The auto-downgrade is seamless — the CDN processor detects device capability at init and silently loads general (8MB) instead of multiclass (18MB). The user sees no error or interruption; they just get the lighter model. Visual quality difference is subtle for most scenarios (both models handle blur/replacement well), with multiclass providing better segmentation accuracy per our benchmark data. Once we have confidence for devices-specific issues, we can flip the default easily back to Multiclass model as it is a one-liner change.

Comment thread src/backgroundsegmentation/BackgroundSegmentationVideoFrameProcessor.ts Outdated
Comment thread src/statscollector/StatsCollector.ts
Comment thread src/statscollector/StatsCollector.ts Outdated
Comment thread demos/browser/app/meetingV2/meetingV2.ts
@harshhv-dev
harshhv-dev force-pushed the background-segmentation-v3 branch from fd06b99 to 82707c4 Compare June 12, 2026 19:00
hensmi-amazon
hensmi-amazon previously approved these changes Jun 12, 2026
Comment on lines +1378 to +1406
describe('videoProcessorMetricsDidReceive', () => {
it('stores video processor metrics', () => {
statsCollector = new StatsCollector(audioVideoController, logger, interval);
const metrics = {
frameRate: 15,
processors: [{ averageProcessLatency: 10.5, processorName: 'TestProcessor' }],
};
statsCollector.videoProcessorMetricsDidReceive(metrics);
});
});

describe('backgroundSegmentationMetricsDidReceive', () => {
it('stores background segmentation metrics', () => {
statsCollector = new StatsCollector(audioVideoController, logger, interval);
statsCollector.backgroundSegmentationMetricsDidReceive({
metricName: 'test',
timestamp: Date.now(),
});
});

it('drops oldest when max exceeded', () => {
statsCollector = new StatsCollector(audioVideoController, logger, interval);
for (let i = 0; i < 55; i++) {
statsCollector.backgroundSegmentationMetricsDidReceive({
metricName: `m-${i}`,
timestamp: Date.now(),
});
}
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do these tests verify the correct result?

Comment on lines +589 to +601
it('passes metrics collector to internal metrics', async () => {
sandbox.stub(BackgroundSegmentationCompatibilityChecker, 'checkCompatibility').returns({
isCompatible: false,
missingFeatures: ['webgl2'],
});

const processor = await BackgroundSegmentationVideoFrameProcessor.create(logger, {
type: ProcessorEffect.BLUR,
});

const collector = { backgroundSegmentationMetricsDidReceive: sandbox.stub() };
processor.setMetricsCollector(collector);
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is validation done in this test?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad, I need to add some assertions here.

dinmin-amzn
dinmin-amzn previously approved these changes Jun 23, 2026
  Implement a new CDN-based background segmentation processor that supports
  blur (low/medium/high), image replacement, and color replacement effects
  with two model types (selfie_general and selfie_multiclass).

  Core:
  - BackgroundSegmentationVideoFrameProcessor with CDN asset loading
  - BackgroundSegmentationAssetLoader with request deduplication
  - BackgroundSegmentationCompatibilityChecker (WebGL2, WASM, Workers)
  - BackgroundSegmentationMetrics observer for StatsCollector integration
  - Dynamic filter switching via setConfig/setModelType without recreation

  Observability:
  - Video processor metrics (frame rate, per-processor latency) via StatsCollector
  - Event publishing for filter lifecycle (backgroundFilterStarted, backgroundFilterConfigSelected, backgroundFilterFailed)
  - Extended VideoFXEventAttributes with V3-specific fields

  Demo:
  - Replace legacy MediaPipe/TensorFlow-based filters with V3 segmentation
  - Add blur strength options (low/medium/high) for both model types
  - Fix iOS crash on rapid filter switching (concurrency guard)
  - Fix filter re-application after offline/online transition
  - Remove @tensorflow-models/body-segmentation dependency

  Testing:
  - Add unit tests for BackgroundSegmentation (processor, asset loader, compatibility checker, metrics)
  - Update VideoProcessingTest to use V3 background segmentation filters (replaces V2 VideoFx tests)
  - Add VideoTestSteps utility methods for blur, image replacement, and color replacement with model parameter
  - Add fake video stream (output.y4m) for consistent pixel-based filter verification
  - Add blue pixel percentage check and pixel diff verification for filter validation
@dinmin-amzn
dinmin-amzn merged commit 334d78f into main Jun 23, 2026
7 checks passed
@dinmin-amzn
dinmin-amzn deleted the background-segmentation-v3 branch June 23, 2026 23:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants