Skip to content

Commit

Permalink
puplished v0.0.2
Browse files Browse the repository at this point in the history
  • Loading branch information
k9p5 committed Jul 1, 2023
1 parent 1c05af8 commit 5b29a8d
Show file tree
Hide file tree
Showing 11 changed files with 162 additions and 44 deletions.
26 changes: 20 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Welcome to FFmpeg.js, an innovative library that offers a WebAssembly-powered interface for utilizing FFmpeg in the browser. 🌐💡

### [👥Join our Discord](https://discord.gg/EmUMFvMdhT)
### [👥Join our Discord](https://discord.gg/n3mpzfejAb)

----

Expand All @@ -25,7 +25,7 @@ Addressing the issues above, FFmpeg.js:

However, it's important to note that as of now, FFmpeg.js runs only in Chrome, Firefox, and Edge browsers. It doesn't support Safari or Node. 🚧🔍

## ⚙️ Setup
## 🚀 Setup

Setting up FFmpeg.js is a breeze!

Expand Down Expand Up @@ -117,14 +117,23 @@ Take a look at these tests for more examples:

- Webassembly is limited to 2GB
- Difficult to handle in unit tests, it's probably best if you mock the FFmpeg class and leave the testing to us (which is also good practice).
- The LGPLv2.1 build of FFmpeg without external libaries doesn't support any mainstream video delivery codecs such as h264/hevc/vp9. But it's very useful for audio processing, run the following commands for more information
- There is no hardware accileration available, making video encoding/decoding rather slow.

## ⚙️ Configurations

Currently there are two different FFmpeg configurations available with more on the way.

- `lgpl-base` (default): It is a compilation of FFmpeg without any external libraries, which is useful for audio & video muxing/demuxing and audio encoding/decoding. It is v2.1LGPL compliant and can therefore be used for commercial projects.
- `gpl-extended`: This is the [@ffmpeg/core](https://github.com/ffmpegwasm/ffmpeg.wasm-core) configuration, that has been built with `--enable-gpl` and `--enable-nonfree` and can therefore only be used for commercial projects if the entire codebase is publicly accessible. It supports popular delivery codecs such as `h264/h265/vp9` etc.

For more information about the supported codecs and muxers run the following commands:

```typescript
console.log(await ffmpeg.codecs());
console.log(await ffmpeg.formats());
```

**BUT WAIT THERE IS MORE!** FFmpeg js is compatible with the binaries of `@ffmpeg/core`, which supports all major codecs like those mentioned before. Here is how you can configure it:
This is how you can switch the configuration:

```typescript
import {
Expand All @@ -134,10 +143,15 @@ import {

// FFmpegConfigurationGPLExtended will add the type extensions
const ffmpeg = new FFmpeg<FFmpegConfigurationGPLExtended>({
lib: 'gpl-extended',
config: 'gpl-extended',
});
```
Thats it!
> More FFmpeg LGPLv2.1 builds with external libraries such as VP9 and LAME will be added soon!

We believe that FFmpeg.js will significantly streamline your interaction with FFmpeg in the browser, providing a more effective and efficient coding experience. Happy coding! 🚀🌟

### DISCLAIMER

*The information contained in this text is provided for informational purposes only. It is not intended as a comprehensive guide to the GPL and LGPL license usages nor does it offer legal advice. Laws and regulations surrounding software licenses can be complex and may change over time. The author and provider of this information cannot be held responsible for any errors, omissions, or any outcomes related to your use of this information.*

*While every effort has been made to ensure the information presented here is accurate as of the date of publication, no guarantee is given as to its currency or applicability to your specific situation. You should not rely upon this information as a substitute for consultation with a legal professional or other competent advisors. Always consult with a qualified professional familiar with your particular circumstances before making decisions that could have legal implications.*
24 changes: 7 additions & 17 deletions examples/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@
"vite": "^4.3.9"
},
"dependencies": {
"@diffusion-studio/ffmpeg-js": "file:.."
"@diffusion-studio/ffmpeg-js": "^0.0.2"
}
}
3 changes: 1 addition & 2 deletions examples/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ import typescriptLogo from './typescript.svg';
import viteLogo from '/vite.svg';
import { FFmpeg } from '@diffusion-studio/ffmpeg-js';

const logger = () => null;
const ffmpeg = new FFmpeg({ logger, lib: "lgpl-base" });
const ffmpeg = new FFmpeg({ log: false });

document.querySelector<HTMLDivElement>('#app')!.innerHTML = `
<div>
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@diffusion-studio/ffmpeg-js",
"private": false,
"version": "0.0.1",
"version": "0.0.2",
"description": "FFmpeg.js - Use FFmpeg in the browser powered by WebAssembly",
"type": "module",
"files": [
Expand Down Expand Up @@ -54,7 +54,7 @@
"homepage": "https://github.com/diffusion-studio/ffmpeg-js#readme",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"build": "rm -r -f ./dist && tsc && vite build",
"preview": "vite preview",
"test": "npx playwright test --project=chromium",
"prettier": "npx prettier --write ./src"
Expand Down
9 changes: 4 additions & 5 deletions playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export default defineConfig({
command: 'npm run dev',
url: 'http://localhost:5173/',
},

testDir: './src/tests',
/* Run tests in files in parallel */
fullyParallel: false,
Expand Down Expand Up @@ -47,9 +46,9 @@ export default defineConfig({
use: { ...devices['Desktop Firefox'] },
},

{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},
// {
// name: 'webkit',
// use: { ...devices['Desktop Safari'] },
// },
],
});
File renamed without changes.
21 changes: 15 additions & 6 deletions src/ffmpeg.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { IFFmpegConfiguration } from './interfaces';
import { FFmpegBase } from './ffmpeg-base';
import * as types from './types';
import libs from './lib-config';
import configs from './ffmpeg-config';
import { noop } from './utils';

export class FFmpeg<
Config extends IFFmpegConfiguration<
Expand All @@ -14,11 +15,19 @@ export class FFmpeg<
private _output?: types.OutputOptions<Config>;
private _middleware: string[] = [];

public constructor(settings: types.FFmpegSettings = { lib: 'lgpl-base' }) {
super({
logger: settings.logger ?? console.log,
source: settings.source ?? libs[settings.lib],
});
public constructor(settings: types.FFmpegSettings = {}) {
let logger = console.log;
let source = configs[settings?.config ?? "lgpl-base"];

if (settings?.log == false) {
logger = noop;
}

if (settings?.source) {
source = settings.source;
}

super({ logger, source });
}

/**
Expand Down
96 changes: 96 additions & 0 deletions src/tests/base.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { test, expect, Page } from '@playwright/test';

// Annotate entire file as serial.
test.describe.configure({ mode: 'serial' });

let page: Page;

test.describe('FFmpegBase functionalities', async () => {
/**
* Get index page and wait until ffmpeg is ready
*/
test.beforeAll(async ({ browser }) => {
page = await browser.newPage();
await page.goto('http://localhost:5173/');

const ready = await page.evaluate(async () => {
if (!ffmpeg.isReady) {
await new Promise<void>((resolve) => {
ffmpeg.whenReady(resolve);
});
}

return ffmpeg.isReady;
});
expect(ready).toBe(true);
});

test('test intercepting logs', async () => {
const messages = await page.evaluate(async () => {
const _messages: string[] = [];
ffmpeg.onMessage(((msg) => {
_messages.push(msg);
}));
await ffmpeg.exec(["-help"]);
return _messages;
});
expect(messages.length).toBeGreaterThan(0);
expect(messages.at(0)).toBeTruthy();
expect(messages.at(0)?.length).toBeGreaterThan(0);
});

test('test removing onMessage callback', async () => {
const messages = await page.evaluate(async () => {
const _messages0: string[] = [];
const _messages1: string[] = [];

const cb0 = (msg: string) => _messages0.push(msg)
const cb1 = (msg: string) => _messages1.push(msg)

ffmpeg.onMessage(cb0);
ffmpeg.onMessage(cb1);

await ffmpeg.exec(["-help"]);

ffmpeg.removeOnMessage(cb1);

return [_messages0, _messages1];
});

expect(messages[0].length).toBeGreaterThan(0);
expect(messages[1].length).toBeGreaterThan(0);
// callback function 1 should have recieved
// half as many messages than callback funtion 0
expect(messages[1].length).toBeGreaterThan(messages[0].length / 2);
});


test('test clearing memory works', async () => {
const result = await page.evaluate(async () => {
const inputName = 'input.ogg';
const outputName = 'output.wav';
await ffmpeg.writeFile(inputName, 'http://localhost:5173/samples/audio.ogg');
await ffmpeg.exec(['-i', inputName, outputName]);
const render = ffmpeg.readFile(outputName).length;

ffmpeg.clearMemory();
// try to read memory again should fail
let input = null;
let output = null;

// input and output should stay null
try {
input = ffmpeg.readFile(inputName);
} catch (e) { }
try {
output = ffmpeg.readFile(outputName);
} catch (e) { }

return { render, input, output }
});

expect(result.render).toBeGreaterThan(0);
expect(result.output).toBe(null);
expect(result.input).toBe(null);
});
});
12 changes: 12 additions & 0 deletions src/tests/export.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,18 @@ test.describe('FFmpeg basic exporting', async () => {
expect(length).toBeGreaterThan(0);
});

test('test converting mp4 into gif', async () => {
const length = await page.evaluate(async () => {
const result = await ffmpeg
.input({ source: 'http://localhost:5173/samples/video.mp4' })
.ouput({ format: 'gif' })
.export();

return result?.length;
});
expect(length).toBeGreaterThan(0);
});

test('test adding wav audio track to mp4', async () => {
const length = await page.evaluate(async () => {
const result = await ffmpeg
Expand Down
9 changes: 4 additions & 5 deletions src/types/common.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import libs from '../lib-config';
import configs from '../ffmpeg-config';

/**
* Defines a callback function that
Expand Down Expand Up @@ -63,12 +63,11 @@ export type FFmpegSettings = {
* **COMPLY WITH**, checkout https://ffmpeg.org/legal.html
* for more.
*/
lib: keyof typeof libs;
config?: keyof typeof configs;
/**
* Overwrite the logging function.
* The default is console log
* Choose whether ffmpeg should log each output
*/
logger?(msg?: any, ...params: any[]): void;
log?: boolean;
};

/**
Expand Down

0 comments on commit 5b29a8d

Please sign in to comment.