

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 为 Amazon Chime SDK 将背景筛选器集成至客户端应用程序
<a name="background-filters"></a>

本部分介绍如何使用背景模糊 2.0 和背景替换 2.0 以编程方式筛选视频背景。要将背景筛选器添加至视频流，创建包含 `VideoFxConfig` 对象的 `VideoFxProcessor`。然后将该处理器插入到 `VideoTransformDevice`。

后台过滤器处理器使用 TensorFlow 精简版机器学习模型 JavaScript Web Workers，并 WebAssembly 对视频流中每帧的背景应用过滤器。这些资产是在您创建 `VideoFxProcessor` 时的运行过程中下载。

[上的浏览器演示应用程序 GitHub](https://github.com/aws/amazon-chime-sdk-js/tree/main/demos/browser)使用了新的背景模糊和替换滤镜。若要试用，使用 `npm run start` 启动演示，加入会议，然后点击摄像头启用视频。打开**应用筛选器**菜单 (![\[Button with a circle and a downward arrow.\]](http://docs.aws.amazon.com/zh_cn/chime-sdk/latest/dg/images/blur-apply-filter-initial.png))，然后选择**背景模糊 2.0**或**背景替换 2.0**选项。

**Topics**
+ [关于使用适用于 Amazon Chime SDK 的背景筛选器](about-bg-filters.md)
+ [在 Amazon Chime 软件开发工具包客户端库中使用内容安全策略 JavaScript](content-security.md)
+ [为 Amazon Chime SDK 将背景筛选器添加到您的应用程序](add-filters.md)
+ [Amazon Chime SDK 的背景筛选器示例](example-bg-filter.md)

# 关于使用适用于 Amazon Chime SDK 的背景筛选器
<a name="about-bg-filters"></a>

背景筛选器可以是 CPU 密集型，也可以是 GPU 密集型。某些移动设备和低规格笔记本电脑或台式机可能无法同时运行筛选器和多个视频流。

## Amazon Chime SDK 的 SIMD 支持
<a name="simd-support"></a>

在支持单指令、多数据 (SIMD) 的环境中，背景筛选器的效率更高。启用 SIMD 后，在给定的复杂度级别下，筛选器占用的 CPU 资源会更少。运行不支持 SIMD 的浏览器的低功耗设备可能无法运行背景筛选器。

## Amazon Chime 软件开发工具包的网络GL2 支持
<a name="webgl2-support"></a>

该`VideoFxProcessor`对象需要支持 Web GL2 的浏览器才能访问客户端设备上的 GPU。

## Amazon Chime SDK 的内容分发和带宽
<a name="delivery-caching-bandwidth"></a>

Amazon 内容分发网络会在运行时加载背景过滤 machine-learning-model文件。这可提供低延迟的全局分发，而无需提供一整套文件作为应用程序的一部分。但是，加载模型文件可能会增加应用程序某些部分的延迟。为了帮助减轻这种影响，浏览器会无限期缓存模型文件。该缓存使后续加载速度大大加快。作为最佳实践，请检查受支持的浏览器，然后在用户可能没有注意到任何延迟时创建背景筛选器资源。例如，您可以在用户在大厅等候或使用设备选择器时下载模型文件。

您的应用程序必须连接以下应用：
+ Amazon Chime SDK 媒体服务。
+ 亚马逊 CloudFront 通过 HTTPS（端口 443）。

所有请求都发送到 `sdkassets.chime.aws` 的子域。无法访问内容分发网络或[内容安全策略](content-security.md)中未包含正确域名的应用程序将不能通过支持检查且无法使用筛选器。

有关的 IP 地址范围 CloudFront的更多信息，请参阅 *Amazon CloudFront 开发者指南*中的[ CloudFront 边缘服务器的位置和 IP 地址范围](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/LocationsOfEdgeServers.html)。

## Amazon Chime SDK 的浏览器兼容性
<a name="filters-browser-compat"></a>

下表列出了支持背景筛选器的浏览器和版本。


| 浏览器 | 支持的最低版本 | 
| --- | --- | 
| Firefox | 76\$1 | 
| 基于 Chromium 的浏览器和环境，包括 Edge 和 Electron | 78\$1 | 
| Android Chrome | 110\$1 | 
| macOS 上的 Safari | 16.3\$1 | 
| iOS（iPhone、iPad）上的 Safari | 16.x | 
| iOS 上的 Chrome | 110.0.0.x.x | 
| iOS 上的 Firefox (iPhone iPad) | 16.x | 

`VideoFxProcessor` 对象的 3.14 版本支持安卓系统。要获得 3.14 之前版本的 Android 设备支持，请使用 `BackgroundBlurVideoFrameProcessor` 和 `BackgroundReplacementVideoFrameProcessor` 对象。有关使用它们的更多信息，请参阅上的[https://aws.github.io/amazon-chime-sdk-js/modules/backgroundfilter_video_processor.html](https://aws.github.io/amazon-chime-sdk-js/modules/backgroundfilter_video_processor.html)页面 GitHub。

# 在 Amazon Chime 软件开发工具包客户端库中使用内容安全策略 JavaScript
<a name="content-security"></a>

现代 Web 应用程序使用内容安全策略保护用户免受某些类别的攻击。使用 `VideoFxProcessor` 的应用程序必须包含本节描述的策略指令。这些指令允许 Amazon Chime SDK 在运行时访问其所需的资源。

**Topics**
+ [所需的内容安全策略指令](#required-csp)
+ [内容安全策略示例](#example-csp)
+ [内容安全策略错误](#csp-errors)
+ [跨源开启器内容安全政策](#cross-origin-policy)

## 所需的内容安全策略指令
<a name="required-csp"></a>

您必须使用以下内容安全策略指令。
+ 对于 `script-src:`，添加 `blob: https://*.sdkassets.chime.aws` 以加载视频处理代码，并添加 `wasm-unsafe-eval` 以允许运行该代码。
+ 对于 `script-src-elem:`，添加 `blob:` `https://*.sdkassets.chime.aws` 以从来源加载视频处理代码。
+ 用于`worker-src:``blob: https://*.sdkassets.chime.aws`添加 JavaScript 跨源加载工作人员。

如果您忽略这些条目中的任何一个，或者您使用 HTTP 标头和 `http-equiv` 元标签指定策略，但意外通过交叉排除其中任何一个条目，则背景筛选器将无法初始化。该筛选器似乎不受支持，或者创建了一个无操作视频帧处理器。您将在浏览器控制台中看到错误，例如：

```
Refused to connect to
'https://static.sdkassets.chime.aws/bgblur/workers/worker.js…'
because it violates the document's content security policy.
```

### 必需的脚本策略指令
<a name="required-script"></a>

要正常运行，该`VideoFxProcessor`类必须在运行时从 Amazon 内容分发网络加载 JavaScript 类。这些类使用 Web GL2 实现视频的后期处理。要允许应用程序获取和运行这些类别，必须包含以下指令：
+ `script-src 'self' blob: https://*.sdkassets.chime.aws`
+ `script-src-elem 'self' blob: https://*.sdkassets.chime.aws`

**注意**  
要在 Safari 和 Firefox 上获得全面支持，必须使用 `script-src` 和 `script-src-elem` 指令。

### 工作线程策略指令
<a name="required-worker"></a>

将 JavaScript 类作为 blob `VideoFxProcessor` 加载以运行 Web 工作线程。该线程使用机器学习模型处理视频。要授予应用程序获取和使用此工作线程的访问权限，请包含以下指令：

`worker-src 'self' blob: https://*.sdkassets.chime.aws`

### WebAssembly 政策
<a name="required-web-assembly"></a>

从亚马逊拥有的同一个内容交付网络`VideoFxProcessor`加载一个 WebAssembly (WASM) 模块。在 Chrome 95 及更高版本中，编译后的 WASM 模块无法跨越多个模块边界。要允许获取和实例化这些模块，请在 `script-src` 指令中包含 `'wasm-unsafe-eval'`。

有关内容安全政策文档的更多信息 WebAssembly，请参阅上的[WebAssembly 内容安全政策](https://github.com/WebAssembly/content-security-policy/blob/main/proposals/CSP.md) GitHub。

### （可选）背景图片策略指令
<a name="optional-directives"></a>

要将动态加载的背景图像与背景替换筛选器一起使用，`VideoFxProcessor` 必须能够访问该图像。为此，请在托管图像的域中加入 `connect-src` 指令。

## 内容安全策略示例
<a name="example-csp"></a>

以下示例策略允许使用 `VideoFxProcessor`。`connect-src` 定义并不特定于 `VideoFxProcessor`。相反，它们与 Amazon Chime SDK 会议中的音频和视频有关。

```
<head>
    <meta http-equiv="Content-Security-Policy" 
        content="base-uri 'self';    
        connect-src       'self' https://*.chime.aws wss://*.chime.aws https://*.amazonaws.com wss://*.chime.aws https://*.ingest.chime.aws;
        script-src        'self' blob: 'wasm-unsafe-eval' https://*.sdkassets.chime.aws; 
        script-src-elem   'self' blob: https://*.sdkassets.chime.aws;
        worker-src        'self' blob: https://*.sdkassets.chime.aws;">
</head>
```

## 内容安全策略错误
<a name="csp-errors"></a>

如果省略任何必需指令，则 `VideoFxProcessor` 不会实例化且将不受支持。在这种情况下，浏览器控制台中会出现以下（或类似）错误：

```
Refused to connect to
'https://static.sdkassets.chime.aws/ml_media_fx/otherassets/worker.js'
because it violates the document's content security policy.
```

## 跨源开启器内容安全政策
<a name="cross-origin-policy"></a>

为了限制内存使用量，该模块倾向于使用 `SharedArrayBuffer` 进行处理。但是，这需要您仔细配置 Web 安全。在为应用程序 HTML 提供服务时，必须设置以下标头：

```
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
```

服务器必须设置这些，因为它们没有等效元标签。如果您不设置这些标头，则背景筛选器可能会占用稍多的 RAM。

背景筛选器可以是 CPU 密集型，也可以是 GPU 密集型。某些移动设备和低规格笔记本电脑或台式机可能无法同时运行筛选器和多个视频流。

# 为 Amazon Chime SDK 将背景筛选器添加到您的应用程序
<a name="add-filters"></a>

添加背景筛选器的过程要遵循以下主要步骤：
+ 检查是否有支持的浏览器。
+ 使用您要使用的配置创建 `VideoFxConfig` 对象。
+ 使用配置对象创建 `VideoFxProcessor` 对象。
+ 将 `VideoFxProcessor` 对象包含在 `VideoTransformDevice`。
+ 使用 `VideoTransformDevice` 启动视频输入。

**注意**  
要完成这些步骤，您必须先执行以下操作：  
创建 `Logger`。
选择 `MediaDeviceInfo` 类视频设备。
成功加入 `MeetingSession`。

以下部分介绍如何完成流程的每个步骤。

**Topics**
+ [为 Amazon Chime SDK 在提供筛选器之前先检查是否受支持](support-check.md)
+ [为 Amazon Chime SDK 创建 VideoFxConfig 对象](create-videofxconfig.md)
+ [为 Amazon Chime SDK 创建 VideoFxProcessor 对象](create-videofxprocessor.md)
+ [为 Amazon Chime SDK 配置 VideoFxProcessor 对象](configure-videofxprocessor.md)
+ [为 Amazon Chime SDK 创建 VideoTransformDevice 对象](create-video-transform.md)
+ [为 Amazon Chime SDK 开始视频输入](start-video-input.md)
+ [为 Amazon Chime SDK 微调资源利用率](tuning.md)

# 为 Amazon Chime SDK 在提供筛选器之前先检查是否受支持
<a name="support-check"></a>

Amazon Chime SDK 提供了一种异步静态方法，用于检查受支持的浏览器并尝试下载所需资产。但是，它不检查设备性能。作为最佳实践，在提供筛选器之前，始终确保用户的浏览器和设备可以支持筛选器。

```
import {
    VideoFxProcessor
} from 'amazon-chime-sdk-js';

if (!await VideoFxProcessor.isSupported(logger)) {     
    // logger is optional for isSupported
}
```

# 为 Amazon Chime SDK 创建 VideoFxConfig 对象
<a name="create-videofxconfig"></a>

您可以在同一个对象中为 `backgroundBlur` 和 `backgroundReplacement` 定义配置。但是，不能同时为两个筛选器将 `isEnabled` 设置为 `true`。这是一个无效配置。

`VideoFxConfig` 类本身不进行验证。验证将在下一步骤中进行。

以下示例显示有效的 `VideoFxConfig`。

```
const videoFxConfig: VideoFxConfig = {
    backgroundBlur: {
        isEnabled: false,
        strength: 'medium'
    },
    backgroundReplacement: {
        isEnabled: false,
        backgroundImageURL: 'space.jpg',
        defaultColor: undefined,
    }
}
```

下表列出了您可以在 `VideoFxConfig` 对象中指定的 `VideoFxProcessor` 属性。

**背景模糊筛选器属性**


| 属性 | Type | 说明 | 
| --- | --- | --- | 
| `isEnabled` | `boolean` |  当为 `true` 时，筛选器会模糊背景。 | 
| `strength` | `string` | 确定模糊程度。有效值：`low` \$1 `medium` \$1 `high`。 | 

**背景替换筛选器属性**


| 属性 | Type | 说明 | 
| --- | --- | --- | 
| `isEnabled` | `boolean` |  当为 `true` 时，筛选器会替换背景。 | 
| `backgroundImageURL` | `string` | 背景图片的 URL。筛选器根据当前屏幕的尺寸动态调整图像大小。您可以使用诸如 `https://...` 等字符串或诸如 `data:image/jpeg;base64` 等 URL。 | 
| `defaultColor` | `string` | 十六进制颜色字符串，例如 `000000` 或 `FFFFFF`，或 `black` 或 `white` 等字符串。如果未指定图像 URL，则处理器会使用 `defaultColor` 作为背景。如果未指定 `defaultColor`，则处理器默认为黑色。 | 

# 为 Amazon Chime SDK 创建 VideoFxProcessor 对象
<a name="create-videofxprocessor"></a>

创建`VideoFxProcessor`对象时， AWS 服务器会下载运行时资源，或者浏览器缓存加载资源。如果网络或 CSP 配置阻止访问资产，则 `VideoFx.create` 操作会引发异常。结果 VideoFxProcessor 被配置为无操作处理器，这不会影响视频流。

```
let videoFxProcessor: VideoFxProcessor | undefined = undefined;
try {
  videoFxProcessor = await VideoFxProcessor.create(logger, videoFxConfig);
} catch (error) {
  logger.warn(error.toString());
}
```

`VideoFxProcessor.create` 还会尝试从 `backgroundReplacement.backgroundImageURL` 中加载图像。如果图像加载失败，处理器会抛出异常。处理器还会出于其他原因抛出异常，例如配置无效、浏览器不受支持或硬件性能不足。

# 为 Amazon Chime SDK 配置 VideoFxProcessor 对象
<a name="configure-videofxprocessor"></a>

下表列出可以配置的 `VideoFxProcessor` 属性。表下方的示例显示典型的运行时系统配置。

**背景模糊**  
背景模糊具有以下属性：


| 属性 | Type | 说明 | 
| --- | --- | --- | 
| `isEnabled` | `boolean` | 当为 `true` 时，筛选器会模糊背景。 | 
| `strength` | `string` | 确定模糊程度。有效值：`low` \$1`medium` \$1`high`. | 

**背景替换**  
背景替换使用以下参数：


| 属性 | Type | 说明 | 
| --- | --- | --- | 
| `isEnabled` | `boolean` | 当为 `true` 时，筛选器会替换背景。 | 
| `backgroundImageURL` | `string` | 背景图片的 URL。筛选器根据当前屏幕的尺寸动态调整图像大小。您可以使用诸如 `https://...` 等字符串或诸如 `data:image/jpeg;base64` 等 URL。 | 
| `defaultColor` | `string` | 十六进制颜色字符串，例如 `000000` 或 `FFFFFF`，或 `black` 或 `white` 等字符串。如果未指定图像 URL，则处理器会使用 `defaultColor` 作为背景。如果未指定 `defaultColor`，则处理器默认为黑色。 | 

**运行时更改配置**  
您可以使用 `videoFxProcessor.setEffectConfig` 参数在运行时更改 `VideoFxProcessor` 配置。以下示例显示如何启用背景替换和禁用背景模糊。

**注意**  
一次只能指定一种类型的背景替换。指定 `backgroundImageURL` 或 `defaultColor` 的值，但不能同时指定两者。

```
videoFxConfig.backgroundBlur.isEnabled = false;
videoFxConfig.backgroundReplacement.isEnabled = true;
try {
  await videoFxProcessor.setEffectConfig(videoFxConfig);
} catch(error) {
  logger.error(error.toString())
}
```

如果 `setEffectConfig` 抛出异常，则之前的配置仍然有效。`setEffectConfig` 会在与导致 `VideoFxProcessor.create` 抛出异常的类似条件下抛出异常。

以下示例显示如何在视频运行时更改背景图像。

```
videoFxConfig.backgroundReplacement.backgroundImageURL = "https://my-domain.com/my-other-image.jpg";
try {
  await videoFxProcessor.setEffectConfig(videoFxConfig);
} catch(error) {
  logger.error(error.toString())
}
```

# 为 Amazon Chime SDK 创建 VideoTransformDevice 对象
<a name="create-video-transform"></a>

以下示例显示如何创建包含 `VideoFxProcessor` 的 `VideoTransformDevice` 对象。

```
// assuming that logger and videoInputDevice have already been set    
const videoTransformDevice = new DefaultVideoTransformDevice(
  logger,
  videoInputDevice,
  [videoFxProcessor]
);
```

# 为 Amazon Chime SDK 开始视频输入
<a name="start-video-input"></a>

以下示例演示如何使用 `VideoTransformDevice` 对象开始视频输入。

```
// assuming that meetingSession has already been created
await meetingSession.audioVideo.startVideoInput(videoTransformDevice);
meetingSession.audioVideo.start();
meetingSession.audioVideo.startLocalVideoTile();
```

# 为 Amazon Chime SDK 微调资源利用率
<a name="tuning"></a>

创建 `VideoFxProcessor` 时，您可以提供可选 `processingBudgetPerFrame` 参数并控制筛选器占用 CPU 和 GPU 量。

```
let videoFxProcessor: VideoFxProcessor | undefined = undefined;
const processingBudgetPerFrame = 50;
try {
  videoFxProcessor = await VideoFxProcessor.create(logger, videoFxConfig, processingBudgetPerFrame);
} catch (error) {
  logger.warn(error.toString());
}
```

`VideoFxProcessor` 需要时间处理帧。时间长短取决于设备、浏览器以及浏览器或设备上正在运行的其他程序。处理器使用*预算*的概念确定处理和渲染每帧所用的时间。

处理时间以毫秒为单位。举个如何使用预算的示例，1 秒有 1000 毫秒。将每秒 15 帧的视频捕获作为目标，总预算为 1000 毫秒/15fps = 66 毫秒。通过在 `processingBudgetPerFrame` 参数中提供值 `50`，您可以将预算设置为其中的 50% 或 33ms，如上例所示。

然后 `VideoFxProcessor` 尝试在指定的预算范围内处理帧。如果处理超出预算，处理器会降低视觉质量使其保持在预算范围内。处理器继续将视觉质量降低到最低限度后，它会停止降低。这种处理持续时间是持续测量的，因此，如果有更多资源可用，例如关闭另一个应用程序并释放 CPU，处理器会再次提高视觉质量，直到达到预算或者达到最高的视觉质量。

如果您未向 `processingBudgetPerFrame` 提供值，则 `VideoFxProcessor` 默认为 `50`。

# Amazon Chime SDK 的背景筛选器示例
<a name="example-bg-filter"></a>

以下示例显示如何实施筛选器

```
import {
    VideoFxConfig,
    VideoFxTypeConversion,
    VideoTransformDevice,
    DefaultVideoTransformDevice,
    Logger,
    VideoFxProcessor,
    MeetingSession
} from 'amazon-chime-sdk-js';

let videoTransformDevice: VideoTransformDevice | undefined = undefined;
let videoFxProcessor: VideoFxProcessor | undefined = undefined;

const videoFxConfig: VideoFxConfig = {
    backgroundBlur: {
        isEnabled: false,
        strength: "medium"
    },
    backgroundReplacement: {
        isEnabled: false,
        backgroundImageURL: 'space.jpg',
        defaultColor: undefined,
    }
}

export const addEffectsToMeeting = async (videoInputDevice: MediaDeviceInfo, meetingSession: MeetingSession, logger: Logger): Promise<void> => {
    try {
        videoFxProcessor = await VideoFxProcessor.create(logger, videoFxConfig);
    } catch (error) {
        logger.error(error.toString());
        return;
    }

    videoTransformDevice = new DefaultVideoTransformDevice(
        logger,
        videoInputDevice,
        [videoFxProcessor]
    );

    await meetingSession.audioVideo.startVideoInput(videoTransformDevice);
}

export const enableReplacement = async (logger: Logger) => {
    videoFxConfig.backgroundBlur.isEnabled = false;
    videoFxConfig.backgroundReplacement.isEnabled = true;
    await updateVideoFxConfig(videoFxConfig, logger);
}

export const enableBlur = async (logger: Logger) => {
    videoFxConfig.backgroundReplacement.isEnabled = false;
    videoFxConfig.backgroundBlur.isEnabled = true;
    await updateVideoFxConfig(videoFxConfig, logger);
}

export const pauseEffects = async (logger: Logger) => {
    videoFxConfig.backgroundReplacement.isEnabled = false;
    videoFxConfig.backgroundBlur.isEnabled = false;
    await updateVideoFxConfig(videoFxConfig, logger);

}

export const setReplacementImage = async (newImageUrl: string, logger: Logger) => {
    videoFxConfig.backgroundReplacement.backgroundImageURL = newImageUrl;
    videoFxConfig.backgroundReplacement.defaultColor = undefined;
    await updateVideoFxConfig(videoFxConfig, logger);
}

export const setReplacementDefaultColor = async (newHexColor: string, logger: Logger) => {
    videoFxConfig.backgroundReplacement.defaultColor = newHexColor;
    videoFxConfig.backgroundReplacement.backgroundImageURL = undefined;
    await updateVideoFxConfig(videoFxConfig, logger);
}

export const setBlurStrength = async (newStrength: number, logger: Logger) => {
    videoFxConfig.backgroundBlur.strength = VideoFxTypeConversion.useBackgroundBlurStrengthType(newStrength);
    await updateVideoFxConfig(videoFxConfig, logger);

}

export const updateVideoFxConfig = async (config: VideoFxConfig, logger: Logger) => {
    try {
        await videoFxProcessor.setEffectConfig(videoFxConfig);
    } catch (error) {
        logger.error(error.toString())
    }
}

export const turnOffEffects = () => {
    const innerDevice = await videoTransformDevice?.intrinsicDevice();
    await videoTransformDevice?.stop();
    videoTransformDevice = undefined;
    videoFxProcessor = undefined;
    await meetingSession.audioVideo.startVideoInput(innerDevice);
}
```