Skip to content

Commit

Permalink
chore: rename & update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
ForeverSc committed Jun 4, 2024
1 parent 8a13e84 commit b8d1cb9
Show file tree
Hide file tree
Showing 7 changed files with 279 additions and 100 deletions.
149 changes: 115 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,36 @@ WebCodecs only provide the ability to decode, but not to demux. mp4box.js is coo
- 🧩 Support for customized packaging, you can adjust the configuration, packaged in a specified format demuxer

## Install
### NPM
```bash
npm install web-demuxer
```

### CDN
```html
<script type="module">
import { WebDemuxer } from 'https://cdn.jsdelivr.net/npm/web-demuxer@latest/dist/web-demuxer.min.js';
</script>
```

## Usage
```typescript
import { WebDemuxer } from "web-demuxer"

const demuxer = new WebDemuxer({
// ⚠️ you need to put the dist/wasm-files file in the npm package into a static directory like public
// making sure that the js and wasm in wasm-files are in the same directory
wasmLoaderPath: "https://cdn.jsdelivr.net/npm/web-demuxer@latest/dist/wasm-files/ffmpeg.js",
wasmLoaderPath: "https://cdn.jsdelivr.net/npm/web-demuxer@latest/dist/wasm-files/ffmpeg.min.js",
})

// Take the example of seeking a video frame at a specified point in time
async function seek(time) {
async function seek(file, time) {
// 1. load video file
await demuxer.load(file);

// 2. demux video file and generate WebCodecs needed VideoDecoderConfig and EncodedVideoChunk
const videoDecoderConfig = await demuxer.getVideoDecoderConfig();
const videoChunk = await demuxer.seekEncodedVideoChunk(seekTime);
const videoChunk = await demuxer.seekEncodedVideoChunk(time);

// 3. use WebCodecs to decode frame
const decoder = new VideoDecoder({
Expand All @@ -55,55 +63,128 @@ async function seek(time) {
- [Seek Video Frame](https://foreversc.github.io/web-demuxer/#example-seek)[code](https://github.com/ForeverSc/web-demuxer/blob/main/index.html#L96)
- [Play Video](https://foreversc.github.io/web-demuxer/#example-play)[code](https://github.com/ForeverSc/web-demuxer/blob/main/index.html#L123)

Here is the translation of the provided TypeScript API documentation into English:

## API
### `WebDemuxer`
#### Constructor
```typescript
new WebDemuxer(options: WebDemuxerOptions)
```
Creates a new instance of `WebDemuxer`.

##### Parameters
- `options`: Required, configuration options
- `wasmLoaderPath`: Required, the address of the JS loader file corresponding to the wasm (corresponds to `dist/wasm-files/ffmpeg.js` or `dist/wasm-files/ffmpeg-mini.js` in the npm package)
> ⚠️ You need to ensure that the wasm and JS loader files are placed in the same accessible directory. The JS loader will request the wasm file in the same directory by default.
Parameters:
- `options`: Required, configuration options.
- `wasmLoaderPath`: Required, the path to the corresponding JavaScript loader file for wasm (corresponding to the `ffmpeg.js` or `ffmpeg-mini.js` in the `dist/wasm-files` directory of the npm package).
> ⚠️ You must ensure that the wasm and JavaScript loader files are placed in the same accessible directory, the JavaScript loader will default to requesting the wasm file in the same directory.
#### `load(file: File): Promise<boolean>`
Loads the file and waits for the wasm worker to load. You need to wait for the `load` method to succeed before calling subsequent methods.
```typescript
load(file: File): Promise<boolean>
```
Loads a file and waits for the wasm worker to finish loading. The subsequent methods can only be called after the `load` method has been successfully executed.

##### Parameters
- `file: File`: Required, the `File` object to be processed
Parameters:
- `file`: Required, the `File` object to be processed.

#### `getVideoDecoderConfig(): Promise<VideoDecoderConfig>`
Parses the video stream and obtains the `VideoDecoderConfig` of the file. The return value can be directly used as an input parameter for the `configure` method of `VideoDecoder`.
```typescript
getVideoDecoderConfig(): Promise<VideoDecoderConfig>
```
Parses the video stream to obtain the `VideoDecoderConfig` of the file, and the return value can be directly used as an argument for the `configure` method of `VideoDecoder`.

#### `getAudioDecoderConfig(): Promise<AudioDecoderConfig>`
Parses the audio stream and obtains the `AudioDecoderConfig` of the file. The return value can be directly used as an input parameter for the `configure` method of `AudioDecoder`.
```typescript
getAudioDecoderConfig(): Promise<AudioDecoderConfig>
```
Parses the audio stream to obtain the `AudioDecoderConfig` of the file, and the return value can be directly used as an argument for the `configure` method of `AudioDecoder`.

#### `seekEncodedVideoChunk(timestamp: number): Promise<EncodedVideoChunk>`
Obtains the video data at the specified timestamp (defaults to the keyframe). The return value can be directly used as an input parameter for the `decode` method of `VideoDecoder`.
```typescript
seekEncodedVideoChunk(time: number): Promise<EncodedVideoChunk>
```
Retrieves the video data at the specified time point (default keyframe), and the return value can be directly used as an argument for the `decode` method of `VideoDecoder`.

##### Parameters
- `timestamp: number`: Required, in seconds
Parameters:
- `time`: Required, in seconds.

#### `seekEncodedAudioChunk(timestamp: number): Promise<EncodedAudioChunk>`
Obtains the audio data at the specified timestamp. The return value can be directly used as an input parameter for the `decode` method of `AudioDecoder`.
```typescript
seekEncodedAudioChunk(time: number): Promise<EncodedAudioChunk>
```
Retrieves the audio data at the specified time point, and the return value can be directly used as an argument for the `decode` method of `AudioDecoder`.

##### Parameters
- `timestamp: number`: Required, in seconds
Parameters:
- `time`: Required, in seconds.

#### `readAVPacket(start: number, end: number, streamType?: AVMediaType, streamIndex?: number): ReadableStream<WebAVPacket>`
```typescript
readAVPacket(start?: number, end?: number, streamType?: AVMediaType, streamIndex?: number): ReadableStream<WebAVPacket>
```
Returns a `ReadableStream` for streaming packet data.

#### `getAVStream(streamType?: AVMediaType, streamIndex?: number): Promise<WebAVStream>`
Obtains data from the specified stream in the file.
Parameters:
- `start`: The start time for reading, in seconds, defaults to 0, reading packets from the beginning.
- `end`: The end time for reading, in seconds, defaults to 0, reading until the end of the file.
- `streamType`: The type of media stream, defaults to 0, which is the video stream.
- `streamIndex`: The index of the media stream, defaults to -1, which is to automatically select.

```typescript
getAVStream(streamType?: AVMediaType, streamIndex?: number): Promise<WebAVStream>
```
Gets information about a specified stream in the media file.

Parameters:
- `streamType`: The type of media stream, defaults to 0, which is the video stream.
- `streamIndex`: The index of the media stream, defaults to -1, which is to automatically select.

Simplified methods based on the semantics of `getAVStream`:
- `getVideoStream(streamIndex?: number): Promise<WebAVStream>`
- `getAudioStream(streamIndex?: number): Promise<WebAVStream>`

```typescript
getAVStreams(): Promise<WebAVStream[]>
```
Get all streams in the media file.

```typescript
getAVPacket(time: number, streamType?: AVMediaType, streamIndex?: number): Promise<WebAVPacket>
```
Gets the data at a specified time point in the media file.

Parameters:
- `time`: Required, in seconds.
- `streamType`: The type of media stream, defaults to 0, which is the video stream.
- `streamIndex`: The index of the media stream, defaults to -1, which is to automatically select.

Simplified methods based on the semantics of `getAVPacket`:
- `seekVideoPacket(time: number): Promise<WebAVPacket>`
- `seekAudioPacket(time: number): Promise<WebAVPacket>`
- `readVideoPacket(start?: number, end?: number): ReadableStream<WebAVPacket>`
- `readAudioPacket(start?: number, end?: number): ReadableStream<WebAVPacket>`

#### `getAVPacket(timestamp: number, streamType?: AVMediaType, streamIndex?: number): Promise<WebAVPacket>`
Obtains the data at the specified timestamp in the file.
```typescript
getAVPackets(time: number): Promise<WebAVPacket[]>
```
Simultaneously retrieves packet data on all streams at a certain time point and returns in the order of the stream array.

Parameters:
- `time`: Required, in seconds.

```typescript
destroy(): void
```
Destroys the instance and releases the worker.

### Convenience API
Semantic wrappers based on the basic API to simplify input parameters
TODO
Here is the translation of the provided text into English:

## Custom Demuxer
TODO
Currently, two versions of the demuxer are provided by default to support different formats:
- `dist/wasm-files/ffmpeg.js`: Full version (gzip: 941 kB), larger in size, supports mov, mp4, m4a, 3gp, 3g2, mj2, avi, flv, matroska, webm, m4v, mpeg, asf
- `dist/wasm-files/ffmpeg-mini.js`: Minimalist version (gzip: 115 kB), smaller in size, only supports mov, mp4, m4a, 3gp, 3g2, matroska, webm, m4v

You can also implement a demuxer for specific formats through custom configuration:

First, modify the `enable-demuxer` configuration in the `Makefile`
```makefile
DEMUX_ARGS = \
--enable-demuxer=mov,mp4,m4a,3gp,3g2,mj2,avi,flv,matroska,webm,m4v,mpeg,asf
```
Then execute `npm run dev:docker:arm64` (if on Windows, please execute `npm run dev:docker:x86_64`) to start the Docker environment.

Finally, execute `npm run build:wasm` to build the demuxer for the specified formats.

## License
MIT
132 changes: 105 additions & 27 deletions README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,36 @@ WebCodecs只提供了decode的能力,但没有提供demux的能力。有一些
- 🧩 支持自定义打包,可以调整配置,打包出指定格式的demuxer

## 安装
### NPM
```bash
npm install web-demuxer
```

### CDN
```html
<script type="module">
import { WebDemuxer } from 'https://cdn.jsdelivr.net/npm/web-demuxer@latest/dist/web-demuxer.min.js';
</script>
```

## 使用
```typescript
import { WebDemuxer } from "web-demuxer"

const demuxer = new WebDemuxer({
// ⚠️ 你需要将npm包中dist/wasm-files文件放到类似public的静态目录下
// 并确保wasm-files中的js和wasm文件在同一目录下
wasmLoaderPath: "https://cdn.jsdelivr.net/npm/web-demuxer@latest/dist/wasm-files/ffmpeg.js",
wasmLoaderPath: "https://cdn.jsdelivr.net/npm/web-demuxer@latest/dist/wasm-files/ffmpeg.min.js",
})

// 以获取指定时间点的视频帧为例
async function seek(time) {
async function seek(file, time) {
// 1. 加载视频文件
await demuxer.load(file);

// 2. 解封装视频文件并生成WebCodecs所需的VideoDecoderConfig和EncodedVideoChunk
const videoDecoderConfig = await demuxer.getVideoDecoderConfig();
const videoChunk = await demuxer.seekEncodedVideoChunk(seekTime);
const videoChunk = await demuxer.seekEncodedVideoChunk(time);

// 3. 通过WebCodecs去解码视频帧
const decoder = new VideoDecoder({
Expand All @@ -56,54 +64,124 @@ async function seek(time) {
- [Play Video](https://foreversc.github.io/web-demuxer/#example-play)[code](https://github.com/ForeverSc/web-demuxer/blob/main/index.html#L123)

## API
### `WebDemuxer`
#### 构造函数
```typescript
new WebDemuxer(options: WebDemuxerOptions)
```
创建一个新的`WebDemuxer`实例

##### 参数
参数:
- `options`: 必填, 配置选项
- `wasmLoaderPath`: 必填,wasm对应的js loader文件地址(对应npm包中`dist/wasm-files/ffmpeg.js``dist/wasm-files/ffmpeg-mini.js`
> ⚠️ 你需要确保将wasm 和js loader文件放在同一个可访问目录下,js loader会默认去请求同目录下的wasm文件
#### `load(file: File): Promise<boolean>`
```typescript
load(file: File): Promise<boolean>
```
加载文件并等待wasm worker加载完成。需要等待load方法执行成功后,才可以继续调用后续的方法

##### 参数
- `file: File`: 必填,需要处理的`File`对象
参数:
- `file`: 必填,需要处理的`File`对象

#### `getVideoDecoderConfig(): Promise<VideoDecoderConfig>`
解析视频流,获取文件的`VideoDecoderConfig`, 返回值可直接作为`VideoDecoder``configure`方法的入参
```typescript
getVideoDecoderConfig(): Promise<VideoDecoderConfig>
```
解析视频流,获取文件的`VideoDecoderConfig`, 返回值可直接作为`VideoDecoder``configure`方法的入参

#### `getAudioDecoderConfig(): Promise<AudioDecoderConfig>`

```typescript
getAudioDecoderConfig(): Promise<AudioDecoderConfig>
```
解析音频流,获取文件的`AudioDecoderConfig`, 返回值可直接作为`AudioDecoder``configure`方法的入参

#### `seekEncodedVideoChunk(timestamp: number): Promise<EncodedVideoChunk>`
```typescript
seekEncodedVideoChunk(time: number): Promise<EncodedVideoChunk>
```
根据传入时间点,获取指定时间点的视频数据(默认取关键帧),返回值可直接作为`VideoDecoder``decode`方法的入参

##### 参数
- `timestamp: number`: 必填,单位为s
参数:
- `time`: 必填,单位为s

#### `seekEncodedAudioChunk(timestamp: number): Promise<EncodedAudioChunk>`
```typescript
seekEncodedAudioChunk(time: number): Promise<EncodedAudioChunk>
```
根据传入时间点,获取指定时间点的音频数据,返回值可直接作为`AudioDecoder``decode`方法的入参

##### 参数
- `timestamp: number`: 必填,单位为s
参数:
- `time`: 必填,单位为s

#### `readAVPacket(start: number, end: number, streamType?: AVMediaType, streamIndex?: number): ReadableStream<WebAVPacket>`
```typescript
readAVPacket(start?: number, end?: number, streamType?: AVMediaType, streamIndex?: number): ReadableStream<WebAVPacket>
```
返回一个`ReadableStream`, 用于流式读取packet数据

#### `getAVStream(streamType?: AVMediaType, streamIndex?: number): Promise<WebAVStream>`
获取文件中指定stream的数据
参数:
- `start`: 读取开始时间点,单位为s,默认值为0,从头开始读取packet
- `end`: 读取结束时间点,单位为s, 默认值为0,读取到文件末尾
- `streamType`: 媒体流类型,默认值为0, 即视频流
- `streamIndex`: 媒体流索引,默认值为-1,即自动选择

```typescript
getAVStream(streamType?: AVMediaType, streamIndex?: number): Promise<WebAVStream>
```
获取媒体文件中指定stream的信息

#### `getAVPacket(timestamp: number, streamType?: AVMediaType, streamIndex?: number): Promise<WebAVPacket>`
获取文件中指定时间点的数据
参数:
- `streamType`: 媒体流类型,默认值为0, 即视频流
- `streamIndex`: 媒体流索引,默认值为-1,即自动选择

### 便利API
基于基础API的语义化封装,简化入参
TODO
基于`getAVStream`的语义简化方法:
- `getVideoStream(streamIndex?: number): Promise<WebAVStream>`
- `getAudioStream(streamIndex?: number): Promise<WebAVStream>`

```typescript
getAVStreams(): Promise<WebAVStream[]>
```
获取媒体文件中所有的stream

```typescript
getAVPacket(time: number, streamType?: AVMediaType, streamIndex?: number): Promise<WebAVPacket>
```
获取媒体文件中指定时间点的数据

参数:
- `time`: 必填,单位为s
- `streamType`: 媒体流类型,默认值为0, 即视频流
- `streamIndex`: 媒体流索引,默认值为-1,即自动选择

基于`getAVPacket`的语义简化方法:
- `seekVideoPacket(time: number): Promise<WebAVPacket>`
- `seekAudioPacket(time: number): Promise<WebAVPacket>`
- `readVideoPacket(start?: number, end?: number): ReadableStream<WebAVPacket>`
- `readAudioPacket(start?: number, end?: number): ReadableStream<WebAVPacket>`

```typescript
getAVPackets(time: number): Promise<WebAVPacket[]>
```
同时获取某个时间点,所有stream上的packet数据, 并按照stream数组顺序返回

参数:
- `time`: 必填,单位为s

```typescript
destroy(): void
```
销毁实例,释放worker

## 自定义Demuxer
TODO
目前默认提供两个版本的demuxer, 用于支持不同的格式:
- `dist/wasm-files/ffmpeg.js`: 完整版(gzip: 941 kB), 体积较大,支持mov,mp4,m4a,3gp,3g2,mj2,avi,flv,matroska,webm,m4v,mpegi,asf
- `dist/wasm-files/ffmpeg-mini.js`: 精简版本(gzip: 115 kB),体积小,仅支持mov,mp4,m4a,3gp,3g2,matroska,webm,m4v

你也可以通过自定义配置,实现指定格式的demxuer:

首先,修改`Makefile`中的`enable-demuxer`配置
```makefile
DEMUX_ARGS = \
--enable-demuxer=mov,mp4,m4a,3gp,3g2,mj2,avi,flv,matroska,webm,m4v,mpegi,asf
```
然后先执行`npm run dev:docker:arm64`(如果是windows, 请执行`npm run dev:docker:x86_64`),启动docker环境。

最后,执行`npm run build:wasm`,构建指定格式的demxuer

## License
MIT
Loading

0 comments on commit b8d1cb9

Please sign in to comment.