Skip to content

Commit d6a0fe6

Browse files
authored
Merge pull request #35 from bilibili/feature/custom-wasm-option
Feature/custom wasm option
2 parents 93ae0ba + 5eb99e8 commit d6a0fe6

File tree

12 files changed

+403
-401
lines changed

12 files changed

+403
-401
lines changed

Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,10 @@ ffmpeg-lib-dev:
6363
emmake make
6464

6565
web-demuxer:
66-
$(WEB_DEMUXER_ARGS) -o ./src/lib/ffmpeg.js
66+
$(WEB_DEMUXER_ARGS) -o ./src/lib/web-demuxer.js
6767

6868
web-demuxer-mini:
69-
$(WEB_DEMUXER_ARGS) -o ./src/lib/ffmpeg-mini.js
69+
$(WEB_DEMUXER_ARGS) -o ./src/lib/web-demuxer-mini.js
7070

7171
web-demuxer-dev:
72-
$(WEB_DEMUXER_ARGS) $(WEB_DEMUXER_DEV_ARGS) -o ./src/lib/ffmpeg.js
72+
$(WEB_DEMUXER_ARGS) $(WEB_DEMUXER_DEV_ARGS) -o ./src/lib/web-demuxer.js

README.md

Lines changed: 56 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,12 @@ npm install web-demuxer
3333
import { WebDemuxer } from "web-demuxer"
3434

3535
const demuxer = new WebDemuxer({
36-
// ⚠️ you need to put the dist/wasm-files file in the npm package into a static directory like public
37-
// making sure that the js and wasm in wasm-files are in the same directory
38-
wasmLoaderPath: "https://cdn.jsdelivr.net/npm/web-demuxer@latest/dist/wasm-files/ffmpeg.min.js",
36+
// ⚠️ Optional parameter for custom WASM file location
37+
// When omitted, it defaults to looking for WASM files in the same directory as the script file.
38+
// We recommend placing the WASM file (web-demuxer.wasm from npm package's dist/wasm-files/)
39+
// in your project's static directory (e.g., public folder).
40+
// Alternatively, you can specify a CDN path like this:
41+
wasmFilePath: "https://cdn.jsdelivr.net/npm/web-demuxer@latest/dist/wasm-files/web-demuxer.wasm",
3942
})
4043

4144
// Take the example of seeking a video frame at a specified point in time
@@ -44,8 +47,8 @@ async function seek(file, time) {
4447
await demuxer.load(file);
4548

4649
// 2. demux video file and generate WebCodecs needed VideoDecoderConfig and EncodedVideoChunk
47-
const videoDecoderConfig = await demuxer.getVideoDecoderConfig();
48-
const videoChunk = await demuxer.seekEncodedVideoChunk(time);
50+
const videoDecoderConfig = await demuxer.getDecoderConfig('video');
51+
const videoEncodedChunk = await demuxer.seek('video', time);
4952

5053
// 3. use WebCodecs to decode frame
5154
const decoder = new VideoDecoder({
@@ -59,7 +62,7 @@ async function seek(file, time) {
5962
});
6063

6164
decoder.configure(videoDecoderConfig);
62-
decoder.decode(videoChunk);
65+
decoder.decode(videoEncodedChunk);
6366
decoder.flush();
6467
}
6568
```
@@ -70,14 +73,13 @@ async function seek(file, time) {
7073

7174
## API
7275
```typescript
73-
new WebDemuxer(options: WebDemuxerOptions)
76+
new WebDemuxer(options?: WebDemuxerOptions)
7477
```
7578
Creates a new instance of `WebDemuxer`.
7679

7780
Parameters:
78-
- `options`: Required, configuration options.
79-
- `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).
80-
> ⚠️ 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.
81+
- `options`: Optional, configuration options.
82+
- `wasmFilePath`: Optional, customize the WASM file path, it defaults to looking for WASM files in the same directory as the script file.
8183

8284
```typescript
8385
load(source: File | string): Promise<void>
@@ -88,90 +90,33 @@ Parameters:
8890
- `source`: Required, support the `File` object or file URL to be processed.
8991

9092
```typescript
91-
getVideoDecoderConfig(): Promise<VideoDecoderConfig>
93+
getDecoderConfig<T extends MediaType>(type: T): Promise<MediaTypeToConfig[T]>
9294
```
93-
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`.
94-
95-
```typescript
96-
getAudioDecoderConfig(): Promise<AudioDecoderConfig>
97-
```
98-
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`.
99-
100-
```typescript
101-
seekEncodedVideoChunk(time: number, seekFlag?: AVSeekFlag): Promise<EncodedVideoChunk>
102-
```
103-
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`.
104-
105-
Parameters:
106-
- `time`: Required, in seconds.
107-
- `seekFlag`: The seek flag, defaults to 1 (seek backward). See `AVSeekFlag` for more details.
108-
109-
```typescript
110-
seekEncodedAudioChunk(time: number, seekFlag?: AVSeekFlag): Promise<EncodedAudioChunk>
111-
```
112-
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`.
113-
114-
Parameters:
115-
- `time`: Required, in seconds.
116-
- `seekFlag`: The seek flag, defaults to 1 (seek backward). See `AVSeekFlag` for more details.
117-
118-
```typescript
119-
readAVPacket(start?: number, end?: number, streamType?: AVMediaType, streamIndex?: number, seekFlag?: AVSeekFlag): ReadableStream<WebAVPacket>
120-
```
121-
Returns a `ReadableStream` for streaming packet data.
95+
Get decoder configuration for WebCodecs based on media type ('video' or 'audio'). Returns `VideoDecoderConfig` or `AudioDecoderConfig` that can be used directly with WebCodecs.
12296
12397
Parameters:
124-
- `start`: The start time for reading, in seconds, defaults to 0, reading packets from the beginning.
125-
- `end`: The end time for reading, in seconds, defaults to 0, reading until the end of the file.
126-
- `streamType`: The type of media stream, defaults to 0, which is the video stream. 1 is audio stream. See `AVMediaType` for more details.
127-
- `streamIndex`: The index of the media stream, defaults to -1, which is to automatically select.
128-
- `seekFlag`: The seek flag, defaults to 1 (seek backward). See `AVSeekFlag` for more details.
129-
130-
Simplified methods based on the semantics of `readAVPacket`:
131-
- `readVideoPacket(start?: number, end?: number, seekFlag?: AVSeekFlag): ReadableStream<WebAVPacket>`
132-
- `readAudioPacket(start?: number, end?: number, seekFlag?: AVSeekFlag): ReadableStream<WebAVPacket>`
98+
- `type`: Required, media type ('video' or 'audio')
13399
134100
```typescript
135-
getAVStream(streamType?: AVMediaType, streamIndex?: number): Promise<WebAVStream>
101+
seek<T extends MediaType>(type: T, time: number, seekFlag?: AVSeekFlag): Promise<MediaTypeToChunk[T]>
136102
```
137-
Gets information about a specified stream in the media file.
103+
Seek and return encoded chunk for WebCodecs. Returns `EncodedVideoChunk` or `EncodedAudioChunk` based on media type.
138104
139105
Parameters:
140-
- `streamType`: The type of media stream, defaults to 0, which is the video stream. 1 is audio stream. See `AVMediaType` for more details.
141-
- `streamIndex`: The index of the media stream, defaults to -1, which is to automatically select.
142-
143-
Simplified methods based on the semantics of `getAVStream`:
144-
- `getVideoStream(streamIndex?: number): Promise<WebAVStream>`
145-
- `getAudioStream(streamIndex?: number): Promise<WebAVStream>`
106+
- `type`: Required, media type ('video' or 'audio')
107+
- `time`: Required, unit is s
108+
- `seekFlag`: Seek flag, default value is 1 (backward seek). See `AVSeekFlag` for details.
146109
147110
```typescript
148-
getAVStreams(): Promise<WebAVStream[]>
111+
read<T extends MediaType>(type: T, start?: number, end?: number, seekFlag?: AVSeekFlag): ReadableStream<MediaTypeToChunk[T]>
149112
```
150-
Get all streams in the media file.
151-
152-
```typescript
153-
getAVPacket(time: number, streamType?: AVMediaType, streamIndex?: number, seekFlag?: AVSeekFlag): Promise<WebAVPacket>
154-
```
155-
Gets the data at a specified time point in the media file.
113+
Read encoded chunks as a stream for WebCodecs. Returns `ReadableStream` of `EncodedVideoChunk` or `EncodedAudioChunk`.
156114
157115
Parameters:
158-
- `time`: Required, in seconds.
159-
- `streamType`: The type of media stream, defaults to 0, which is the video stream. 1 is audio stream. See `AVMediaType` for more details.
160-
- `streamIndex`: The index of the media stream, defaults to -1, which is to automatically select.
161-
- `seekFlag`: The seek flag, defaults to 1 (seek backward). See `AVSeekFlag` for more details.
162-
163-
Simplified methods based on the semantics of `getAVPacket`:
164-
- `seekVideoPacket(time: number, seekFlag?: AVSeekFlag): Promise<WebAVPacket>`
165-
- `seekAudioPacket(time: number, seekFlag?: AVSeekFlag): Promise<WebAVPacket>`
166-
167-
```typescript
168-
getAVPackets(time: number, seekFlag?: AVSeekFlag): Promise<WebAVPacket[]>
169-
```
170-
Simultaneously retrieves packet data on all streams at a certain time point and returns in the order of the stream array.
171-
172-
Parameters:
173-
- `time`: Required, in seconds.
174-
- `seekFlag`: The seek flag, defaults to 1 (seek backward). See `AVSeekFlag` for more details.
116+
- `type`: Required, media type ('video' or 'audio')
117+
- `start`: Optional, start time in seconds (default: 0)
118+
- `end`: Optional, end time in seconds (default: 0, read till end)
119+
- `seekFlag`: Optional, seek flag (default: AVSEEK_FLAG_BACKWARD)
175120
176121
```typescript
177122
getMediaInfo(): Promise<WebMediaInfo> // 2.0 New
@@ -260,34 +205,43 @@ Get the media information of a file, the output is referenced from `ffprobe`
260205
```
261206
262207
```typescript
263-
setLogLevel(level: AVLogLevel) // 2.0 New
208+
getMediaStream(type: MediaType, streamIndex?: number): Promise<WebAVStream>
264209
```
210+
Get information about a media stream (video or audio) in the media file.
211+
265212
Parameters:
266-
- `level`: Required, output log level, see `AVLogLevel` for details.
213+
- `type`: Required, the type of media stream ('video' or 'audio')
214+
- `streamIndex`: Optional, the index of the media stream
267215
268216
```typescript
269-
destroy(): void
217+
seekMediaPacket(type: MediaType, time: number, seekFlag?: AVSeekFlag): Promise<WebAVPacket>
270218
```
271-
Destroys the instance and releases the worker.
272-
273-
## Custom Demuxer
274-
Currently, two versions of the demuxer are provided by default to support different formats:
275-
- `dist/wasm-files/ffmpeg.js`: Full version (gzip: 996 kB), larger in size, supports mov, mp4, m4a, 3gp, 3g2, mj2, avi, flv, matroska, webm, m4v, mpeg, asf, mpegts
276-
- `dist/wasm-files/ffmpeg-mini.js`: Minimalist version (gzip: 456 kB), smaller in size, only supports mov, mp4, m4a, 3gp, 3g2, matroska, webm, m4v
277-
> If you want to use a smaller size version, you can use version 1.0 of web-demuxer, the lite version is only 115KB
278-
> Version 1.0 is written in C, focuses on WebCodecs, and is small in size, while version 2.0 uses C++ Embind, which provides richer media information output, is easier to maintain, and is large in size
219+
Retrieves the media data at the specified time point.
279220
280-
You can also implement a demuxer for specific formats through custom configuration:
221+
Parameters:
222+
- `type`: Required, the type of media ('video' or 'audio')
223+
- `time`: Required, in seconds
224+
- `seekFlag`: Optional, seek flag, defaults to 1 (backward seek). See `AVSeekFlag` for details.
281225
282-
First, modify the `enable-demuxer` configuration in the `Makefile`
283-
```makefile
284-
DEMUX_ARGS = \
285-
--enable-demuxer=mov,mp4,m4a,3gp,3g2,mj2,avi,flv,matroska,webm,m4v,mpeg,asf
226+
```typescript
227+
readMediaPacket(type: MediaType, start?: number, end?: number, seekFlag?: AVSeekFlag): ReadableStream<WebAVPacket>
286228
```
287-
Then execute `npm run dev:docker:arm64` (if on Windows, please execute `npm run dev:docker:x86_64`) to start the Docker environment.
229+
Returns a `ReadableStream` for streaming media packet data.
288230
289-
Finally, execute `npm run build:wasm` to build the demuxer for the specified formats.
231+
Parameters:
232+
- `type`: Required, the type of media ('video' or 'audio')
233+
- `start`: Optional, start time in seconds (default: 0)
234+
- `end`: Optional, end time in seconds (default: 0, read till end)
235+
- `seekFlag`: Optional, seek flag (default: AVSEEK_FLAG_BACKWARD)
290236
291-
## License
292-
This project is primarily licensed under the MIT License, covering most of the codebase.
293-
The `lib/` directory includes code derived from FFmpeg, which is licensed under the LGPL License.
237+
238+
```typescript
239+
setLogLevel(level: AVLogLevel) // 2.0 New
240+
```
241+
Parameters:
242+
- `level`: Required, output log level, see `AVLogLevel` for details.
243+
244+
```typescript
245+
destroy(): void
246+
```
247+
Destroys the instance and releases the worker.

0 commit comments

Comments
 (0)