# @api\.video/media-stream-composer 中文文档

规范地址：https://npmcn.com/package/%40api.video/media-stream-composer/

版本：0\.2\.6
npm 元数据更新时间：2025-05-22T12:50:36.509Z
中文译文更新时间：2026-11-08T07:31:14.213Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40api.video/media-stream-composer
原文对照：https://npmcn.com/package/%40api.video/media-stream-composer/?lang=original
项目主页：https://github.com/apivideo/api.video-typescript-media-stream-composer#readme
源码仓库：https://github.com/apivideo/api.video-typescript-media-stream-composer

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：764 kB，16 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- Node.js 要求：\>=15\.0\.0
- 运行依赖：3 个
- 首次发布：2022-05-31T13:04:49.537Z
- 最新版本发布：2024-10-15T10:10:25.996Z
- 近 30 天下载量：1868（2026-10-06 至 2026-11-04，npm 官方下载统计）
- 已发布版本数：19（近 12 个月 0 个）

## 中文简介

api.video 媒体流作曲

## 安装

```sh
npm install @api.video/media-stream-composer
```

也可以使用：`pnpm add @api.video/media-stream-composer`、`yarn add @api.video/media-stream-composer`、`bun add @api.video/media-stream-composer`

## README

[![badge](https://img.shields.io/twitter/follow/api_video?style=social)](https://twitter.com/intent/follow?screen_name=api_video)   [![badge](https://img.shields.io/github/stars/apivideo/api.video-typescript-media-stream-composer?style=social)](https://github.com/apivideo/api.video-typescript-media-stream-composer)   [![badge](https://img.shields.io/discourse/topics?server=https%3A%2F%2Fcommunity.api.video)](https://community.api.video/) ![](https://github.com/apivideo/.github/blob/main/assets/apivideo_banner.png)

# api.video 媒体作曲

![npm](https://img.shields.io/npm/v/@api.video/media-stream-composer) ![ts](https://badgen.net/badge/-/TypeScript/blue?icon=typescript&label)

[视频](https://api.video/) 是产品制造者的视频基础设施。 闪电快视频 API 用于在您的应用程序中集成,缩放,并管理点播后低空直播功能.

## 目录

-   [目录](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-table-of-contents)
-   [项目说明](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-project-description)
-   [开始](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-getting-started)
    -   [安装](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-installation)
        -   [安装方法 1: 需要js](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-installation-method-1-requirejs)
        -   [安装方法 第 2: ES6 模块](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-installation-method-2-es6-modules)
        -   [在 Javascript 计划中简单包含](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-simple-include-in-a-javascript-project)
-   [文档](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-documentation)
    -   [证据](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-instantiation)
        -   [选项](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-options)
    -   [方法](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-methods)
        -   [`addStream(mediaStream: MediaStream | HTMLImageElement, options: StreamOptions): string`](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-addstreammediastream-mediastream--htmlimageelement-options-streamoptions-string)
            -   [选项](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-options-1)
        -   [`updateStream(streamId: string, options: StreamOptions): void`](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-updatestreamstreamid-string-options-streamoptions-void)
        -   [`removeStream(id: string): void`](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-removestreamid-string-void)
        -   [`getStreams(): StreamDetails[]`](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-getstreams-streamdetails)
        -   [`getStream(id: string): StreamDetails`](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-getstreamid-string-streamdetails)
        -   [`addAudioSource(mediaStream: MediaStream): string`](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-addaudiosourcemediastream-mediastream-string)
        -   [`removeAudioSource(id: string): void`](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-removeaudiosourceid-string-void)
        -   [`getAudioSources(): AudioSourceDetails[]`](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-getaudiosources-audiosourcedetails)
        -   [`getAudioSource(audioSourceId: string): AudioSourceDetails`](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-getaudiosourceaudiosourceid-string-audiosourcedetails)
        -   [`moveUp(streamId: string): void`](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-moveupstreamid-string-void)
        -   [`moveDown(streamId: string): void`](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-movedownstreamid-string-void)
        -   [`startRecording(options: RecordingOptions): void`](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-startrecordingoptions-recordingoptions-void)
            -   [选项](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-options-2)
                -   [使用授权的上传符( 建议):](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-using-a-delegated-upload-token-recommended)
                -   [使用访问符( 损坏 ) :](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-using-an-access-token-discouraged)
                -   [共同选项](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-common-options)
        -   [`stopRecording(): Promise<VideoUploadResponse>`](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-stoprecording-promisevideouploadresponse)
        -   [`getCanvas(): HTMLCanvasElement | undefined`](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-getcanvas-htmlcanvaselement--undefined)
        -   [`appendCanvasTo(containerQuerySelector: string): void`](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-appendcanvastocontainerqueryselector-string-void)
        -   [`setMouseTool(tool: "draw" | "move-resize"): void`](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-setmousetooltool-draw--move-resize-void)
        -   [`setDrawingSettings(settings: Partial<DrawingSettings>): void`](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-setdrawingsettingssettings-partialdrawingsettings-void)
        -   [`clearDrawing(): void`](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-cleardrawing-void)
        -   [`addEventListener(event: string, listener: Function)`](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-addeventlistenerevent-string-listener-function)
        -   [`destroy()`](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-destroy)
-   [完整实例](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-full-examples)
    -   ["卢姆式"](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-loom-like)

## 项目说明

此库允许您从多个媒体流的构成中轻松记录视频并上传到 api. video 。 每个溪流的位置和大小可以灵活而轻松地设定.

例如,这只允许用几行代码来创建由下列内容组成的视频: "全屏抓取左半部,窗口#1抓取右半部,视频左下方以圆形相机".

一个小型的 Next.js 应用程序的代码可以显示库提供的不同特性 [实例/记录.a.video](https://github.com/apivideo/api.video-typescript-media-stream-composer/tree/main/examples/record.a.video) 文件夹。 如果你想尝试现场直播,请到这里: [https://record.a.video (英语)](https://record.a.video/)。 。 。 .

## 开始

### 安装

#### 安装方法 1: 需要js

如果您使用需要js, 您可以将库添加为您的项目依赖性

```sh
$ npm install --save @api.video/media-stream-composer
```

然后可以在脚本中使用库 :

```javascript
var { MediaStreamComposer } = require('@api.video/media-stream-composer');

var composer = new MediaStreamComposer({
    resolution: {
        width: 1280,
        height: 720
    }
}); 
```

#### 安装方法 第 2: ES6 模块

您可以将库添加为您的项目依赖性

```sh
$ npm install --save @api.video/media-stream-composer
```

然后可以在脚本中使用库 :

```javascript
import { MediaStreamComposer } from '@api.video/media-stream-composer'

const composer = new MediaStreamComposer({
    resolution: {
        width: 1280,
        height: 720
    }
});
```

#### 在 Javascript 计划中简单包含

将库包含在您的 HTML 文件里 :

```html
<head>
    ...
    <script src="https://unpkg.com/@api.video/media-stream-composer" defer></script>
</head>
```

然后,你可以即时使用作曲家 `new MediaStreamComposer()`数字 :

```html
...
<script type="text/javascript"> 
    const composer = new MediaStreamComposer({
        resolution: {
            width: 1280,
            height: 720
        }
    });
</script>
```

## 文档

### 证据

#### 选项

媒体流作曲家被即时化 `options` 对象。 目前,它只包含一个选项: `resolution`如果提供,此选项必须包含 `width` (单位:千美元) `height` 属性。 此分辨率将用于创建画布元素来绘制流. 上传后还将用于设定视频的解析.

如果 `resolution` 选项,将使用此分辨率创建画布:1280x720.

### 方法

#### `addStream(mediaStream: MediaStream | HTMLImageElement, options: StreamOptions): string`

添加Stream () 方法为组分添加了流. 溪流可以是 `MediaStream` (例如:网络相机、屏幕或窗口捕获) `HTMLImageElement` (例如,一个标志).

它需要一个 `MediaStream | HTMLImageElement` 还有一个 `StreamOptions` 参数.

**关于图像来源的说明**

当将图像加载到构件上时,图像的出处必须与网页的出处相同,以便正确显示图像. 这意味着图像必须从同一个域来服务,或者图像的托管服务器必须包含相应的 CORS(Cross-Origin Resource sharing)信头来允许图像从不同的来源被显示在画布上. 详情如下: [https://developer.mozilla.org/en-US/docs/Web/HTML/CORS 已启用 图像](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image) 。 。 。 .

##### 选项

| 选项名称 | 类型 | 默认值 | 说明 |
| --: | --- | --- | --- |
| 名称 | 字符串 | 未定义 | 流的可选名称 |
| 职位 | `contain` | `cover` | `fixed` | `contain` | `contain`: 溪流将包含在画布中, `cover`河会被帆布覆盖, `fixed`: 流会固定在画布中 |
| 页:1 | 编号 | 未定义 | 溪流的x个位置(以像素表示,只有位置= `fixed`(中文(简体) ) |
| 尔 | 编号 | 未定义 | y 流的位置( 以像素表示, 仅在位置 = `fixed`(中文(简体) ) |
| 宽度 | 编号 | 未定义 | 流的宽度( 以像素表示, 只有位置 = `fixed`(中文(简体) ) |
| 高度 | 编号 | 未定义 | 溪流高度(以像素计,只有在位置= `fixed`(中文(简体) ) |
| 可拖动 | 布尔 | 虚假 | 是否可以通过拖曳来移动溪流( 见 Bellow) [鼠标交互](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-mouse-interactions)(中文(简体) ) |
| 可调整 | 布尔 | 虚假 | 溪流是否可以通过拖曳其边框来调整大小( 见 Bellow) [鼠标交互](https://npmcn.com/package/%40api.video/media-stream-composer/#readme-mouse-interactions)(中文(简体) ) |
| 口罩 | `none` | `circle` | `none` | 溪流是否应该被圆所掩盖 |
| 哑 | 布尔 | 虚假 | 溪流是否应当变音 |
| 隐藏 | 布尔 | 虚假 | 溪流是否应当隐藏 |
| 透明度 | 编号 | 100个 | 溪流不透明度(从0到100) |
| 点击 | (流线:字符串,事件: `{ x: number; y: number; }`(虚空) | 未定义 | 点击流时调用回调函数 |

**示例(屏幕抓取)**

```javascript

navigator.mediaDevices.getDisplayMedia({ video: true, audio: false }).then((stream) => {
    const streamId = composer.addStream(stream, {
        position: "fixed",
        x: 100,
        y: 100,
        width: 300,
        draggable: true,
        resizable: true,
        mask: "circle",
        opacity: 90,
        onClick: (streamId, event) => {
            console.log(streamId, event.x, event.y);
        }
    });

    // ...
});
```

**示例(图像)**

```javascript

const image = new Image();
image.crossOrigin = 'anonymous';
image.src = "./my-logo.jpg"; 

const streamId = composer.addStream(image, {
    position: "fixed",
    x: 100,
    y: 100,
    width: 300,
    draggable: true,
    resizable: true,
    mask: "none"
});
```

#### `updateStream(streamId: string, options: StreamOptions): void`

更新现有流的选项。 它需要溪流的ID(通过添加Stream()方法返回的)和一个 `StreamOptions` 参数(与添加Stream()方法相同).

**示例**

```javascript
composer.updateStream(streamId, {
    hidden: true,
});
```

#### `removeStream(id: string): void`

从构成中删除一条流 。 id与由添加Stream()方法返回的同.

**示例**

```javascript
composer.removeStream(streamId);
```

#### `getStreams(): StreamDetails[]`

返回含有构成中所有流的详细内容的一系列对象.

**示例**

```javascript
const streams = composer.getStreams();
/*
    streams: [{
        "id": "0",
        "options": {
            "position": "fixed",
            "height": 192,
            "x": 0,
            "y": 0,
            "resizable": true,
            "draggable": true,
            "mask": "circle",
            "name": "#0 webcam"
        },
        "displaySettings": {
            "radius": 96,
            "displayResolution": {
                "width": 192,
                "height": 192
            },
            "position": {
                "x": 0,
                "y": 0
            },
            "streamResolution": {
                "width": 640,
                "height": 480
            },
            "index": 1
        },
        "stream": {}
    }]
*/

```

#### `getStream(id: string): StreamDetails`

获取溪流的细节. 取出溪来之道. id与由添加Stream()方法返回的同.

**示例**

```javascript
const stream = composer.getStream(streamId);
```

#### `addAudioSource(mediaStream: MediaStream): string`

添加AudioSource()方法将流作为音频源添加到构成中. 它需要一个 `MediaStream` 参数。 展出不会被溪流所影响. 只有音频会混合. |

**示例**

```javascript

navigator.mediaDevices.getDisplayMedia({ audio: { deviceId: selectedAudioSource }).then((stream) => {
    const audioSourceId = composer.addAudioSource(stream);
});

```

#### `removeAudioSource(id: string): void`

从构成中删除音频源 。 id与由添加Audio Source()方法返回的同.

**示例**

```javascript
composer.removeAudioSource(audioSourceId);
```

#### `getAudioSources(): AudioSourceDetails[]`

返回含有构成中所有流的详细内容的一系列对象.

**示例**

```javascript
const audioSources = composer.getAudioSources();
/*
    audioSources: [{
        "id": "audio_0",
        "stream": {}
    }]
*/

```

#### `getAudioSource(audioSourceId: string): AudioSourceDetails`

获取音频来源的细节. 它需要音频源的ID。 id与由添加Audio Source()方法返回的同.

**示例**

```javascript
const stream = composer.getAudioSource(audioSourceId);
```

#### `moveUp(streamId: string): void`

向上移动组分中的一串流( 即向上移动) 。 id与由添加Stream()方法返回的同.

**示例**

```javascript
composer.moveUp(streamId);
```

#### `moveDown(streamId: string): void`

将组分中的一串流向下移动( 即将其向下移动) 。 id与由添加Stream()方法返回的同.

**示例**

```javascript
composer.moveDown(streamId);
```

#### `startRecording(options: RecordingOptions): void`

开始记录构成并上传到您的 api. video 账户 。 它需要一个 `RecordingOptions` 参数.

##### 选项

提供选项取决于您要对 api. video API 进行认证的方式: 要么使用授权的上传令牌( recommanded), 要么使用通常的访问令牌 .

###### 使用授权的上传符( 建议):

在从客户端上传时,使用授权上传符进行认证是最佳选项. 更多关于授权上传信条 [授权上传](https://api.video/blog/tutorials/delegated-uploads/)。 。 。 .

| 选项名称 | 强制性 | 类型 | 说明 |
| --: | --- | --- | --- |
| 上传脚本 | **对** | 字符串 | 您的上传标志 |
| 视频 | 没有 | 字符串 | 现有视频的编号 |
| _常见选项(见铃声)_ |  |  |  |

###### 使用访问符( 损坏 ) :

**3⁄4 ̄ ̧漯B**: 注意暴露您的访问符客户端会导致巨大的安全问题. 只有你知道自己在做什么,才使用这种方法:).

| 选项名称 | 强制性 | 类型 | 说明 |
| --: | --- | --- | --- |
| 访问脚本 | **对** | 字符串 | 您的访问符 |
| 视频 | **对** | 字符串 | 现有视频的编号 |
| _常见选项(见铃声)_ |  |  |  |

###### 共同选项

| 选项名称 | 强制性 | 类型 | 说明 |
| --: | --- | --- | --- |
| 视频Name | 没有 | 字符串 | 您录制的视频名称( 覆盖默认的“ 文件” 名称) |
| 爱比荷斯 | 没有 | 字符串 | api.video 主机(默认:ws.api.video) |
| 重试 | 没有 | 编号 | aPI 调用失败时重试的次数( 默认: 5) |
| 时间 | 无( 默认: 5000) | 编号 | 要记录到每个 Blob 的毫秒数 . |

**示例**

```javascript
composer.startRecording({
    uploadToken: "YOUR_DELEGATED_TOKEN",
    retries: 10,
});
```

#### `stopRecording(): Promise<VideoUploadResponse>`

Stop Recording () 方法停止了对成分的录制. 它不需要参数。 它返回一个承诺 解决新创建的视频.

**示例**

```javascript
composer.stopRecording().then(e => console.log(`player url: ${e.assets.player}`));
```

#### `getCanvas(): HTMLCanvasElement | undefined`

返回用于绘制构成的画布。 它不需要参数.

**示例**

```javascript
const canvas = composer.getCanvas();
```

#### `appendCanvasTo(containerQuerySelector: string): void`

将绘制成分的画布添加到 HTML 容器中。 它需要一个包含容器的查询选择器的字符串.

如果你想在网页上显示构成,那就很有用.

此外,它也是强制性的,你要使用基于鼠标的特性,比如拖放,再大小和绘图.

**示例**

```html
<div id="container"></div>
<script>
    // ....
    composer.appendCanvasTo("#container");
</script>

```

#### `setMouseTool(tool: "draw" | "move-resize"): void`

定义用户使用鼠标与画布交互时要执行的动作类型 。 它需要一个包含工具名称的字符串.

工具 :

-   `move-resize`: 移动并调整溪流大小
-   `draw`: 在流上绘制(可以使用 `setDrawingSettings()` 方法)

**示例**

```javascript
composer.setMouseTool("draw");

```

#### `setDrawingSettings(settings: Partial<DrawingSettings>): void`

设置绘图设置 `draw` 工具。 它需要一个 `DrawingSettings` 包含下列属性的参数:

-   `color`: 绘图的颜色
-   `lineWidth`: 绘图的宽度
-   `autoEraseDelay`: 绘图被去除之前的延迟( 以秒为0 表示不延迟)

**示例**

```javascript
composer.setDrawingSettings({
    color: "#FF0000",
    lineWidth: 5,
    autoEraseDelay: 3,
});
```

#### `clearDrawing(): void`

清除画布上的所有图纸. 它不需要参数.

**示例**

```javascript
composer.clearDrawing();
```

#### `addEventListener(event: string, listener: Function)`

为媒体记录器定义事件收听器 。 现有活动如下:

-   `"error"`: 当发生错误时
-   `"recordingStopped"`: 当录音停止时

**示例**

```javascript
    composer.addEventListener("error", (event) => {
       console.log(event.data);
    });
```

#### `destroy()`

摧毁所有流并释放所有正在使用的资源.

## 完整实例

### "卢姆式"

这些样本展示了如何利用作曲家在一角用网络相机流来创建屏幕广播.

它具有以下特点:

-   屏幕播放流在背景中被添加,其大小会自动调整到成分大小(`contain` 维度)
-   网络相机流被添加到屏幕播放流前, 在左下角, 它被显示在一个圆形上 - 流是可拖动和可调整的
-   使用收音机按钮可以在“拖动”和“移动/缩小”工具之间切换

```html
<html>
    <head>
        <script src="https://unpkg.com/@api.video/media-stream-composer"></script>
        <style>
            body {
                font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif;
            }
            #container {
                display: flex;
                flex-direction: column;
                align-items: center;
            }

            #video {
                border: 1px solid gray;
            }

            #container div {
                margin: 10px 0;
            }
        </style>
    </head>

    <body>
        <div id="container">
            <div id="canvas-container"> </div>
            <div>
                <button id="start">start recording</button>
                <button id="stop" disabled>stop recording</button>
            </div>
            <div>
                <label for="tool-select">Tool:</label>
                <select id="tool-select">
                    <option value="draw">draw</option>
                    <option selected value="move-resize">move/resize</option>
                </select>
            </div>
            <div>
                <p>Video link: <span id="video-link"><i>will be displayed when the recording is finished</i></span></p>
            </div>
        </div>

        <script>
            const canvasContainer = document.getElementById('canvas-container');
            const toolSelect = document.getElementById("tool-select");
            const startButton = document.getElementById("start");
            const stopButton = document.getElementById("stop");
            const videoLink = document.getElementById("video-link");
            const width = 1366;
            const height = 768;

            canvasContainer.style.width = `${width}px`;
            canvasContainer.style.height = `${height}px`;



            (async () => {
                const screencast = await navigator.mediaDevices.getDisplayMedia();
                const webcam = await navigator.mediaDevices.getUserMedia({
                    audio: true,
                    video: true
                });

                // create the media stream composer instance
                const mediaStreamComposer = new MediaStreamComposer({
                    resolution: {
                        width,
                        height
                    }
                });

                // add the screencast stream
                mediaStreamComposer.addStream(screencast, {
                    position: "contain",
                    mute: true,
                });

                // add the webcam stream in the lower left corner, with a circle mask
                mediaStreamComposer.addStream(webcam, {
                    position: "fixed",
                    mute: false,
                    y: height - 200,
                    left: 0,
                    height: 200,
                    mask: "circle",
                    draggable: true,
                    resizable: true,
                });

                // display the canvas (preview purpose)
                mediaStreamComposer.appendCanvasTo("#canvas-container");

                // when the start button is clicked, start the recording
                startButton.onclick = () => {
                    mediaStreamComposer.startRecording({
                        uploadToken: "YOUR_UPLOAD_TOKEN",
                    });
                    startButton.disabled = true;
                    stopButton.disabled = false;
                }

                // when the stop button is clicked, stop the recording and display the video link
                stopButton.onclick = () => {
                    mediaStreamComposer.stopRecording().then(a => videoLink.innerHTML = a.assets.player);
                    stopButton.disabled = true;
                    startButton.disabled = false;
                }


                mediaStreamComposer.setDrawingSettings({
                    color: "#FF0000",
                    lineWidth: 5,
                    autoEraseDelay: 3,
                });

                toolSelect.onchange = (a) => mediaStreamComposer.setMouseTool(a.target.value);
            })();
        </script>
    </body>

</html>
```

## 常见问题

### @api\.video/media-stream-composer 是什么？

api\.video 媒体流作曲

### 如何安装 @api\.video/media-stream-composer？

在项目目录运行 npm install @api\.video/media-stream-composer，或使用 pnpm add / yarn add / bun add。

### @api\.video/media-stream-composer 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @api\.video/media-stream-composer 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @api\.video/media-stream-composer 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=15\.0\.0。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @api\.video/media-stream-composer 可以商用吗？

@api\.video/media-stream-composer 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @api\.video/media-stream-composer 的下载量有多少？

根据 npm 官方下载统计，@api\.video/media-stream-composer 在 2026/10/06 – 2026/11/04 这 30 天内被下载 1,868 次，日均约 62 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @api\.video/media-stream-composer 还在维护吗？

最新版本 0\.2\.6 发布于 2024/10/15（2 年前）；至今共发布 19 个版本，其中过去 12 个月发布了 0 个；首次发布于 2022/05/31。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

