> For the complete documentation index, see [llms.txt](https://docs.decentraland.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.decentraland.org/creator/content-creator-zh/chang-jing-sdk7/mei-ti/video-playing.md).

# 视频播放

将视频流传输到场景中

在场景中显示视频有三种不同的方式：

* 将视频文件作为场景内容的一部分上传
* 从外部来源流式传输视频
* 通过 Decentraland cast 进行直播流式传输

{% hint style="info" %}
**💡 提示**：在 [Creator Hub 中的场景编辑器](/creator/content-creator-zh/chang-jing-bian-ji-qi/ru-men/about-editor.md)，你可以使用一个 **视频播放器** [智能物品](/creator/content-creator-zh/chang-jing-bian-ji-qi/jiao-hu-xing/smart-items.md) 来以无代码方式实现这一点。
{% endhint %}

在所有情况下，你都需要：

* 一个带有 [基础形状](/creator/content-creator-zh/chang-jing-sdk7/3d-nei-rong-ji-chu/shape-components.md) 的实体，例如平面、立方体，甚至圆锥体。
* 一个 [material](/creator/content-creator-zh/chang-jing-sdk7/3d-nei-rong-ji-chu/materials.md) 搭配一个 `VideoTexture` 将其分配给纹理
* 一个 `VideoPlayer` 组件来控制视频状态。

## 性能注意事项

请记住，流式传输视频会给玩家的机器带来相当大的负担。建议不要同时播放多个视频。

如果你的场景中同时播放了太多视频，其中一些会被引擎暂停。屏幕暂停的优先级会根据多种因素决定，包括与玩家的距离、大小，以及屏幕是否在玩家的视野范围内。可同时播放的视频最大数量取决于玩家的质量设置。

* 低：1
* 中：5
* 高：10

我们还建议在玩家靠近时或执行某个动作时再开始播放视频。如果在场景加载后很远的地方就开始播放视频，会在玩家访问邻近场景时不必要地影响性能。

还要避免以非常高的分辨率流式传输视频。不要使用高于 *HD*.

同样，最好在 Basic（无光照）材质上播放视频，以降低性能负载，下面的所有示例片段都是如此。

## 显示视频

以下说明适用于这三种视频显示方式：

1. 创建一个实体作为视频屏幕。给这个实体一个 `MeshRenderer` 组件，使其具有可见形状。
2. 创建一个 `VideoPlayer` 组件，可引用流媒体 URL 或视频文件路径。这里你还可以设置视频的 `playing` 状态及其音量。这个组件可以分配给视频屏幕实体，也可以分配给场景中的任何其他实体。
3. 创建一个 `VideoTexture` 对象，并在其 `videoPlayerEntity` 属性中分配拥有该 `VideoPlayer` 组件。
4. 创建一个 `材质`，将其分配给屏幕实体，并设置其 `纹理` 添加到 `VideoTexture` 你创建的。

此示例使用一个本地存储在 `/videos` 场景项目文件夹中的视频：

```ts
// #1
const screen = engine.addEntity()
MeshRenderer.setPlane(screen)
Transform.create(screen, { position: { x: 4, y: 1, z: 4 } })

// #2
VideoPlayer.create(screen, {
	src: 'videos/myVideo.mp4',
	playing: true,
})

// #3
const videoTexture = Material.Texture.Video({ videoPlayerEntity: screen })

// #4
Material.setBasicMaterial(screen, {
	texture: videoTexture,
})
```

要使用来自外部流媒体 URL 的视频，请将第 2 步修改为使 `src` 属性在 `VideoPlayer` 组件引用该流媒体 URL。

```ts
// #2
VideoPlayer.create(screen, {
	src: 'https://vz-7c61c1b5-d59.b-cdn.net/ccea595a-b910-4de6-b160-092819db021d/playlist.m3u8',
	playing: true,
})
```

参见 [使用 Decentraland cast 进行流式传输](#streaming-using-decentraland-cast) 了解如何使用这种第三种替代方法的详细信息。

## 关于外部推流

流的来源必须是一个 *https* URL（*http* 不支持 URL）。

你应该可以粘贴指向大多数主流视频流媒体网站视频的网址。请注意这些平台的服务条款。

若要从本地计算机上的视频文件进行推流，最简单的方法是将该视频上传到公开的 Google Drive 并粘贴链接。

另一种选择是使用像 [Vimeo](https://vimeo.com/) , [Livepeer Studio](https://livepeer.studio/) 或 [Serraform](https://serraform.gitbook.io/streaming-docs/guides/decentraland-playback) 这样的托管服务提供商，你向提供商支付费用，由其管理所有流媒体基础设施。

最强大的方法是搭建你自己的服务器，使用免费软件，但在像 [Digital Ocean](https://try.digitalocean.com/developerbrand/?_campaign=emea_brand_kw_en_cpc&_adgroup=digitalocean_exact_exact&_keyword=digitalocean&_device=c&_adposition=&_content=conversion&_medium=cpc&_source=bing\&msclkid=160bfc160a2a1bab9bbf9933594bd9c5\&utm_source=bing\&utm_medium=cpc\&utm_campaign=emea_brand_kw_en_cpc\&utm_term=digitalocean\&utm_content=DigitalOcean%20Exact_Exact) 或 [Cloudflare](https://www.cloudflare.com/products/cloudflare-stream/)上支付托管费用。你可以部署类似 [Node Media Server](https://github.com/illuspas/Node-Media-Server)的东西，它开箱即用即可提供你所需的大部分功能。

所有这些选项在不同场景下各有利弊。你应结合自己的需求、技术水平和预算，评估哪种最适合你。

## 设置 OBS 以成功推流

[OBS](https://obsproject.com/) 是一个流行且免费的流管理工具。

无论你使用的是场地方的流密钥，还是你自己的 RTMP 服务器，OBS 中的设置对于直播的成功都很重要。你应力求获得稳定、一致的连接。

### 简单的 OBS 设置

建议使用以下简单设置：

* 比特率 2500kbps（适用于所有 Decentraland 场地）
* 音频比特率 160kbps
* 视频编码器预设：硬件 NVENC
* 音频编码器 AAC
* 最高分辨率：720（更高会在 DCL 中引发问题）
* 帧率 30fps

{% hint style="warning" %}
**📔 注意**：确保在 OBS 中禁用多轨流媒体。你可以在 设置 > 直播 中找到该选项。
{% endhint %}

### 给新主播的建议

* 尽早进行音频检查，对于测试你与场地的设置至关重要。
* 像流密钥中一个数字写错这样的小错误，最容易搞砸直播。
* 不要超过 720 分辨率或 2500 kbps 的比特率。

## 实时流

你可以使用 [实时流](/creator/content-creator-zh/chang-jing-bian-ji-qi/shi-shi-yun-ying/live-streaming.md) 的功能，从摄像头进行直播或共享屏幕 [管理员工具](/creator/content-creator-zh/chang-jing-bian-ji-qi/shi-shi-yun-ying/scene-admin.md) 智能物件从 URL 播放音频流。

这种流式传输方式使用了与玩家之间实时通信相同的通讯架构。它易于设置，而且延迟远低于从外部来源流式传输。

1. 添加一个 [管理员工具](/creator/content-creator-zh/chang-jing-bian-ji-qi/shi-shi-yun-ying/scene-admin.md) 将智能物品添加到场景中，以及一个 [视频播放器](/creator/content-creator-zh/chang-jing-bian-ji-qi/jiao-hu-xing/video-screen.md) 智能物件从 URL 播放音频流。
2. 将你的场景发布到 World 或 Genesis City。
3. 以有权使用管理员工具的玩家身份进入场景。
4. 打开管理员控制台，选择 **视频** 选项卡，然后选择 **Live** 功能，然后点击 **获取流密钥** 按钮。
5. 复制 **服务器 URL** 和 *流密钥*添加到你的流媒体软件中（例如 OBS）。
6. 按 **激活** 按钮开始直播。

你也可以不向场景中添加 Video player 智能物品，而是使用 URL `livekit-video://current-stream` 作为视频源，在你的场景中播放该直播流。你仍然需要管理员工具来获取流密钥。

```ts
// #1
const screen = engine.addEntity()
MeshRenderer.setPlane(screen)
Transform.create(screen, { position: { x: 4, y: 1, z: 4 } })

// #2
VideoPlayer.create(screen, {
	src: `livekit-video://current-stream`,
	playing: true,
})

// #3
const videoTexture = Material.Texture.Video({ videoPlayerEntity: screen })

// #4
Material.setBasicMaterial(screen, {
	texture: videoTexture,
})
```

## 视频材质

大多数情况下，你会希望在无光照的 [Basic 材质](/creator/content-creator-zh/chang-jing-sdk7/3d-nei-rong-ji-chu/materials.md#unlit-materials)上播放视频，而不是在 PBR 材质上。这会得到更明亮、更清晰的图像，并且性能更好。

```ts
Material.setBasicMaterial(screen, {
	texture: videoTexture,
})
```

通常建议在 Basic 无光照材质上播放视频，因为这样性能更好。不过，如果你想将视频投射到 PBR 材质上，请记住，默认属性会让视频看起来相当不透明。你可以通过调整材质的其他属性来改善这一点。以下是一些让视频更醒目的推荐设置：

```ts
Material.setPbrMaterial(screen, {
	texture: videoTexture,
	roughness: 1.0,
	specularIntensity: 0,
	metallic: 0,
	emissiveTexture: videoTexture,
	emissiveIntensity: 0.6,
	emissiveColor: Color3.White(),
})
```

{% hint style="info" %}
**💡 提示**：由于视频是作为纹理添加到材质上的，你也可以尝试材质的其他属性，例如用颜色给它着色，或添加其他纹理层，比如制作脏屏效果。

参见 [材质](/creator/content-creator-zh/chang-jing-sdk7/3d-nei-rong-ji-chu/materials.md) 了解更多详情。
{% endhint %}

## 关于视频文件

支持以下文件格式：

* *.mp4*
* *.ogg*
* *.webm*

请记住，视频文件会增加场景的总大小，这会使玩家进入你的场景时下载场景所需的时间更长。视频大小也可能让你超过 [场景限制](/creator/content-creator-zh/chang-jing-sdk7/you-hua/scene-limitations.md)，因为你每个地块最多可使用 15 MB。我们建议尽可能压缩视频，以减少问题。

我们还建议在玩家靠近时或执行触发动作时才开始播放视频。如果你的场景在地平线远处加载后就开始播放视频，会在玩家访问邻近场景时不必要地影响性能。

## 开始、暂停和停止视频

要开始播放视频或将其暂停，请设置 `playing` 属性设为 *true* 或 *false*。如果 `playing` 设置为 false，视频会在最后显示的帧处暂停。

你可以通过向屏幕添加指针事件使其可切换，如下所示：

```ts
pointerEventsSystem.onPointerDown(
	{
		entity: screen,
		opts: { button: InputAction.IA_POINTER, hoverText: '播放/暂停' },
	},
	function () {
		const videoPlayer = VideoPlayer.getMutable(screen)
		videoPlayer.playing = !videoPlayer.playing
	}
)
```

要停止视频并将其回到第一帧，请设置 `位置` 属性为 0。在以下示例中，点击视频会停止它。

```ts
pointerEventsSystem.onPointerDown(
	{
		entity: screen,
		opts: { button: InputAction.IA_POINTER, hoverText: '停止' },
	},
	function () {
		const videoPlayer = VideoPlayer.getMutable(screen)
		videoPlayer.playing = false
		videoPlayer.position = 0
	}
)
```

## 配置视频播放器

以下可选属性可设置在 `VideoPlayer` 组件：

* `playing`：确定视频当前是否正在播放。如果为 false，视频会暂停。

{% hint style="warning" %}
**📔 注意**：同时可播放的视频数量有限，这取决于玩家的质量设置。如果场景播放的视频超过该数量，引擎会暂停优先级最低的视频。参见 [性能注意事项](#performance-considerations).
{% endhint %}

* `playbackRate`：更改视频播放速度。 *1* 。
* `volume`：允许你更改音频音量。 *1* 。
* `位置`：允许你设置视频的不同起始位置。它以视频原始开头之后的秒数表示。 *0* 默认值，因此它会从视频的实际开头开始。
* `loop`：布尔值，用于确定视频是否持续循环播放，或者播放一次后停止。 *false* 。

## 播放多个视频

为避免遇到性能问题，请保持同时播放的不同视频数量较低；引擎只允许有限数量的同时视频，这取决于玩家的质量设置（参见 [性能注意事项](#performance-considerations)）。不过，场景可以在多个不同屏幕上播放同一视频纹理的多个副本。这不受限制，因为它对性能的影响远小于播放不同的视频。要在多个实体上播放同一个视频，只需将同一个视频纹理对象实例分配给 `材质` 每个屏幕实体的组件。

```ts
// #1
const screen1 = engine.addEntity()
MeshRenderer.setPlane(screen1)
Transform.create(screen1, { position: { x: 4, y: 1, z: 4 } })

const screen2 = engine.addEntity()
MeshRenderer.setPlane(screen2)
Transform.create(screen2, { position: { x: 6, y: 1, z: 4 } })

// #2
VideoPlayer.create(screen1, {
	src: 'https://vz-7c61c1b5-d59.b-cdn.net/ccea595a-b910-4de6-b160-092819db021d/playlist.m3u8',
	playing: true,
})

// #3
const videoTexture = Material.Texture.Video({ videoPlayerEntity: screen1 })

// #4
Material.setBasicMaterial(screen1, {
	texture: videoTexture,
})

Material.setBasicMaterial(screen2, {
	texture: videoTexture,
})
```

请注意，在上面的示例中，只需创建一个 `VideoPlayer` 组件，它控制两个视频屏幕的状态。在这种情况下，该组件被分配给 `screen1` 实体，但它也可以分配给场景中的任何其他实体，不一定是某个屏幕。

## 视频事件

轻松处理视频中的状态变化，以响应视频开始播放、暂停等情况。例如，这可用于让动画与视频完美同步，确保它们与视频同时开始。

使用 `videoEventsSystem.registerVideoEventsEntity` 以定义一个函数，该函数会在分配给实体的视频状态每次变化时运行。每次状态变化时，你的函数都可以检查新状态并作出相应响应。

```ts
import {
	engine,
	Entity,
	VideoPlayer,
	videoEventsSystem,
	VideoState,
} from '@dcl/sdk/ecs'

// ... 使用 VideoPlayer 组件、Transform、MeshRenderer.setPlane() 等创建 videoPlayerEntity ...

videoEventsSystem.registerVideoEventsEntity(
	videoPlayerEntity,
	function (videoEvent) {
		console.log(
			'视频事件 - 状态：' +
				videoEvent.state +
				'\n当前偏移量：' +
				videoEvent.currentOffset +
				'\n视频长度：' +
				videoEvent.videoLength
		)

		switch (videoEvent.state) {
			case VideoState.VS_READY:
				console.log('视频事件 - 视频已就绪')
				break
			case VideoState.VS_NONE:
				console.log('视频事件 - 视频无状态')
				break
			case VideoState.VS_ERROR:
				console.log('视频事件 - 视频错误')
				break
			case VideoState.VS_SEEKING:
				console.log('视频事件 - 视频正在寻址')
				break
			case VideoState.VS_LOADING:
				console.log('视频事件 - 视频正在加载')
				break
			case VideoState.VS_BUFFERING:
				console.log('视频事件 - 视频正在缓冲')
				break
			case VideoState.VS_PLAYING:
				console.log('视频事件 - 视频开始播放')
				break
			case VideoState.VS_PAUSED:
				console.log('视频事件 - 视频已暂停')
				break
		}
	}
)
```

传递给函数作为输入的 videoEvent 对象包含以下属性：

* `currentOffset` (*数值*）：视频上 `位置` 属性的当前值。该值显示自视频原始起始点以来经过的秒数。 *-1* 如果视频尚未开始播放。
* `state`：新的视频状态，表示为以下值之一： `VideoState` 枚举。该枚举可包含以下可能值：
  * `VideoState.VS_READY`
  * `VideoState.VS_NONE`
  * `VideoState.VS_ERROR`
  * `VideoState.VS_SEEKING`
  * `VideoState.VS_LOADING`
  * `VideoState.VS_BUFFERING`
  * `VideoState.VS_PLAYING`
  * `VideoState.VS_PAUSED`
* `videoLength` (*数值* ）：整个视频的长度（秒）。 *-1* 如果长度未知。
* `时间戳` ( *数值*）：一个 *Lamport* 时间戳，每次视频状态变化时都会递增。
* `tickNumber` (*数值*）：事件发生的时间，以场景开始运行以来的计数 tick 表示。

如果你在一个已经有回调的实体上重新注册回调（例如，改变状态变化时发生的内容），新的回调会替换旧的回调，并且会保留最后一次报告的状态。这意味着，对于之前回调已经报告过的状态，新的回调不会再次被调用。

### 检查实体是否已注册

使用 `videoEventsSystem.hasVideoEventsEntity()` 以检查实体是否已经有注册的视频事件回调。

```ts
if (videoEventsSystem.hasVideoEventsEntity(videoPlayerEntity)) {
	console.log('此实体已经有一个视频事件监听器')
}
```

### 最新视频事件

使用以下方法查询视频的最后一次状态变化： `videoEventsSystem.getVideoState()`。这会返回最新的 `VideoEvent` 实体的值，或者 `undefined` 如果尚未报告任何事件则返回空。你可以在系统中调用它，以便在不注册回调的情况下每帧轮询视频状态。

```ts
function mySystem() {
	const latestVideoEvent = videoEventsSystem.getVideoState(videoPlayerEntity)
	if (!latestVideoEvent) return

	console.log(`状态：${latestVideoEvent.state}
    \n当前偏移量：${latestVideoEvent.currentOffset}
    \n视频长度：${latestVideoEvent.videoLength}`)
}
```

## 视频上的 Alpha 蒙版

要让视频屏幕呈现非矩形形状，一个巧妙的技巧是在平面上叠加一个 alpha 纹理。你可以把平面裁剪成任何你想要的形状。

使用下图将你的视频裁剪成圆形，并带有透明角。

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-4a71dbd3206e2ccafdba8990cb5099b48c9a97cf%2Fcircle_mask.png?alt=media\&token=c1e0f780-7fd0-4e06-a27f-00222068bf81)

```ts
const videoTexture = Material.Texture.Video({
	videoPlayerEntity: screen,
})
const alphaMask = Material.Texture.Common({
	src: 'assets/scene/circle_mask.png',
	wrapMode: TextureWrapMode.TWM_MIRROR,
})

Material.setBasicMaterial(screen, {
	texture: videoTexture,
	alphaTexture: alphaMask,
})
```

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-29eeafc704d19336cc3b0dc023c91e278b4bcd94%2Fcircular-video-screen.png?alt=media\&token=13d1560a-3d64-4a17-943c-25338f931f48)

{% hint style="warning" %}
**📔 注意**：在之前的版本中， `alphaTexture` 属性只存在于 PBR 材质中。当前它仅适用于 Basic 材质。
{% endhint %}

## 在 glTF 模型上播放视频

你可以在一个 *glTF* 模型的材质 [GltfNodeModifiers](/creator/content-creator-zh/chang-jing-sdk7/3d-nei-rong-ji-chu/materials.md#modify-gltf-materials) 组件遍历所有玩家。详见 [修改 glTF 材质](/creator/content-creator-zh/chang-jing-sdk7/3d-nei-rong-ji-chu/materials.md#modify-gltf-materials) 了解更多详情。

这使你可以在任何形状上播放视频，而不仅仅是平面。例如，你可以在弧形屏幕上播放视频，甚至可以在 NPC 的整个身体上播放视频。

```ts
const myEntity = engine.addEntity()

GltfContainer.create(myEntity, {
	src: 'models/myModel.glb',
})

Transform.create(myEntity, {
	position: Vector3.create(4, 0, 4),
})

VideoPlayer.create(myEntity, {
	src: 'https://vz-7c61c1b5-d59.b-cdn.net/ccea595a-b910-4de6-b160-092819db021d/playlist.m3u8',
	playing: true,
})

GltfNodeModifiers.create(myEntity, {
	modifiers: [
		{
			path: '',
			material: {
				material: {
					$case: 'pbr',
					pbr: {
						texture: Material.Texture.Video({
							videoPlayerEntity: myEntity,
						}),
					},
				},
			},
		},
	],
})
```

视频的映射将遵循模型所使用的原始 UV 映射。这意味着，如果模型有一个映射到模型特定部分的纹理，那么视频也会映射到同一部分。

你也可以使用 `GltfNodeModifiers` 组件，只在模型内部的特定网格上播放视频。例如，你可以在建筑物的某一面墙上播放它，即使该模型覆盖整个建筑。参见 [修改 glTF 材质](/creator/content-creator-zh/chang-jing-sdk7/3d-nei-rong-ji-chu/materials.md#modify-gltf-materials) 了解更多详情。

## 空间音频

默认情况下，来自 `VideoPlayer` 组件的视频是全局的，这意味着在整个场景中都能以一致的音量听到。如果玩家离开场景，他们将完全听不到该流媒体。

要使音频具有空间感，请设置 `spatial` 属性设为 *true*.

```ts
VideoPlayer.create(entity, {
	src: 'https://player.vimeo.com/progressive_redirect/playback/1145666916/rendition/540p/file.mp4%20%28540p%29.mp4?loc=external&signature=db1cd6946851313cb8f7be60d1f6c30af0902bcc46fdae0ba2a06e5fdf44c329',
	playing: true,
	spatial: true,
})
```

现在，视频将从拥有该 `VideoPlayer` 组件的实体位置传出，并且玩家越接近它，声音越大。

使用以下属性控制空间音频：

* `spatialMinDistance`：音频开始具有空间感的最小距离。如果玩家更近，音频将以全音量播放。 *0* 。
* `spatialMaxDistance`：音频可被听到的最大距离。如果玩家离得更远，音频音量将为 0。 *60* 默认

```ts
const videoPlayerEntity = engine.addEntity()

Transform.create(videoPlayerEntity, {
	position: Vector3.create(8, 2, 8),
})

VideoPlayer.create(videoPlayerEntity, {
	src: 'https://player.vimeo.com/progressive_redirect/playback/1145666916/rendition/540p/file.mp4%20%28540p%29.mp4?loc=external&signature=db1cd6946851313cb8f7be60d1f6c30af0902bcc46fdae0ba2a06e5fdf44c329',
	playing: true,
	spatial: true,
	spatialMinDistance: 5,
	spatialMaxDistance: 10,
})

MeshRenderer.setPlane(videoPlayerEntity)

Material.setBasicMaterial(videoPlayerEntity, {
	texture: Material.Texture.Video({ videoPlayerEntity: videoPlayerEntity }),
})
```

{% hint style="warning" %}
**📔 注意**：某些视频格式不支持空间音频。确保流编码为 *mp4*, *m4a*，或 *mov*.
{% endhint %}

## 音频分析

你可以从一个 `VideoPlayer` 实体的音轨中读取实时幅度和频率数据，以驱动与视频配乐同步的响应式视觉效果。参见 [音频分析](/creator/content-creator-zh/chang-jing-sdk7/mei-ti/audio-analysis.md).

{% hint style="info" %}
**💡 提示**：要查看在 GLTF 模型而非基础几何体上播放的视频，请参见 [`74,-8-gltfnodemodifier`](https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/74,-8-gltfnodemodifier) 测试场景，它使用 `GltfNodeModifiers` 视频纹理将 HLS 流驱动到特定 GLTF 节点上。
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.decentraland.org/creator/content-creator-zh/chang-jing-sdk7/mei-ti/video-playing.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
