Compare commits

...
10 Commits
23 changed files with 77 additions and 78 deletions
+1 -1
View File
@@ -10,6 +10,6 @@ indent_size = 2
indent_style = space indent_style = space
indent_size = 4 indent_size = 4
[*.yaml] [*.yml]
indent_style = space indent_style = space
indent_size = 2 indent_size = 2
@@ -2,6 +2,7 @@ name: Lint
on: on:
push: push:
pull_request:
jobs: jobs:
lint: lint:
+6 -3
View File
@@ -11,9 +11,7 @@ jobs:
release: release:
name: Release name: Release
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions: write-all
contents: read
id-token: write
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -41,6 +39,11 @@ jobs:
- name: Run build - name: Run build
run: npm run build run: npm run build
- name: Upload build artifacts
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release upload ${{ github.event.release.tag_name }} dist/bundles/mediabunny.cjs dist/bundles/mediabunny.min.cjs dist/bundles/mediabunny.mjs dist/bundles/mediabunny.min.mjs dist/mediabunny.d.ts
- name: Create Publish to npm - name: Create Publish to npm
run: npm publish --provenance run: npm publish --provenance
env: env:
-1
View File
@@ -1,5 +1,4 @@
/node_modules /node_modules
/build
/dist /dist
/dist-docs /dist-docs
.DS_Store .DS_Store
+4 -4
View File
@@ -5,7 +5,7 @@
[![](https://img.shields.io/npm/dm/mediabunny)](https://www.npmjs.com/package/mediabunny) [![](https://img.shields.io/npm/dm/mediabunny)](https://www.npmjs.com/package/mediabunny)
<div align="center"> <div align="center">
<img src="./docs/public/mediabunny-logo.svg" height="180"> <img src="./docs/public/mediabunny-logo.svg" width="180" height="180">
</div> </div>
Mediabunny is a JavaScript library for reading, writing, and converting media files (like MP4, WebM, MP3), directly in the browser. It aims to be a complete toolkit for high-performance media operations on the web. It's written from scratch in pure TypeScript, has zero dependencies, is very performant, and is extremely tree-shakable, meaning you only include what you use. You can think of it a bit like [FFmpeg](https://ffmpeg.org/), but built from the ground up for the web. Mediabunny is a JavaScript library for reading, writing, and converting media files (like MP4, WebM, MP3), directly in the browser. It aims to be a complete toolkit for high-performance media operations on the web. It's written from scratch in pure TypeScript, has zero dependencies, is very performant, and is extremely tree-shakable, meaning you only include what you use. You can think of it a bit like [FFmpeg](https://ffmpeg.org/), but built from the ground up for the web.
@@ -16,11 +16,11 @@ Mediabunny is a JavaScript library for reading, writing, and converting media fi
<div align="center"> <div align="center">
<a href="https://www.gling.ai/" target="_blank"> <a href="https://www.gling.ai/" target="_blank">
<img src="./docs/public/sponsors/gling.svg" height="60" alt="Gling AI"> <img src="./docs/public/sponsors/gling.svg" width="60" height="60" alt="Gling AI">
</a> </a>
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;
<a href="https://diffusion.studio/" target="_blank"> <a href="https://diffusion.studio/" target="_blank">
<img src="./docs/public/sponsors/diffusionstudio.png" height="60" alt="Diffusion Studio"> <img src="./docs/public/sponsors/diffusionstudio.png" width="60" height="60" alt="Diffusion Studio">
</a> </a>
</div> </div>
@@ -152,7 +152,7 @@ For development, clone this repository and install it using a modern version of
```bash ```bash
npm install # Install dependencies npm install # Install dependencies
npm run watch # Development build with watch mode npm run watch # Build bundles on watch mode
npm run build # Production build with type definitions npm run build # Production build with type definitions
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
"mainEntryPointFilePath": "build/index.d.ts", "mainEntryPointFilePath": "dist/modules/index.d.ts",
"bundledPackages": [], "bundledPackages": [],
"compiler": {}, "compiler": {},
"apiReport": { "apiReport": {
+4 -4
View File
@@ -37,20 +37,20 @@ const esmConfig = {
const ctxUmd = await esbuild.context({ const ctxUmd = await esbuild.context({
...umdConfig, ...umdConfig,
outfile: 'dist/mediabunny.js', outfile: 'dist/bundles/mediabunny.cjs',
}); });
const ctxEsm = await esbuild.context({ const ctxEsm = await esbuild.context({
...esmConfig, ...esmConfig,
outfile: 'dist/mediabunny.mjs', outfile: 'dist/bundles/mediabunny.mjs',
}); });
const ctxUmdMinified = await esbuild.context({ const ctxUmdMinified = await esbuild.context({
...umdConfig, ...umdConfig,
outfile: 'dist/mediabunny.min.js', outfile: 'dist/bundles/mediabunny.min.cjs',
minify: true, minify: true,
}); });
const ctxEsmMinified = await esbuild.context({ const ctxEsmMinified = await esbuild.context({
...esmConfig, ...esmConfig,
outfile: 'dist/mediabunny.min.mjs', outfile: 'dist/bundles/mediabunny.min.mjs',
minify: true, minify: true,
}); });
+1 -1
View File
@@ -1,6 +1,6 @@
<!DOCTYPE html> <!DOCTYPE html>
<script src="../dist/mediabunny.js"></script> <script src="../dist/bundles/mediabunny.cjs"></script>
<script type="module"> <script type="module">
const fileInput = document.createElement('input'); const fileInput = document.createElement('input');
+1 -1
View File
@@ -1,6 +1,6 @@
<!DOCTYPE html> <!DOCTYPE html>
<script src="../dist/mediabunny.js"></script> <script src="../dist/bundles/mediabunny.cjs"></script>
<script type="module"> <script type="module">
const fileInput = document.createElement('input'); const fileInput = document.createElement('input');
+1 -1
View File
@@ -1,6 +1,6 @@
<button>Go</button> <button>Go</button>
<script src="../dist/mediabunny.js"></script> <script src="../dist/bundles/mediabunny.cjs"></script>
<script type="module"> <script type="module">
function download(blob, filename) { function download(blob, filename) {
+1 -1
View File
@@ -1,6 +1,6 @@
<!DOCTYPE html> <!DOCTYPE html>
<script src="../dist/mediabunny.js"></script> <script src="../dist/bundles/mediabunny.cjs"></script>
<script type="module"> <script type="module">
function download(blob, filename) { function download(blob, filename) {
+1 -1
View File
@@ -15,7 +15,7 @@
</div> </div>
</div> </div>
<script src="../dist/mediabunny.js"></script> <script src="../dist/bundles/mediabunny.cjs"></script>
<script type="module"> <script type="module">
const fileInput = document.querySelector('input[type="file"]'); const fileInput = document.querySelector('input[type="file"]');
+1
View File
@@ -75,6 +75,7 @@ export default withMermaid({
{ icon: 'github', link: 'https://github.com/Vanilagy/mediabunny' }, { icon: 'github', link: 'https://github.com/Vanilagy/mediabunny' },
{ icon: 'discord', link: 'https://discord.gg/hmpkyYuS4U' }, { icon: 'discord', link: 'https://discord.gg/hmpkyYuS4U' },
{ icon: 'x', link: 'https://x.com/vanilagy' }, { icon: 'x', link: 'https://x.com/vanilagy' },
{ icon: 'bluesky', link: 'https://bsky.app/profile/vanilagy.bsky.social' },
], ],
search: { search: {
+4 -2
View File
@@ -27,7 +27,9 @@ ESM is preferred because it gives you tree shaking.
You can also just include the library using a script tag in your HTML: You can also just include the library using a script tag in your HTML:
```html ```html
<script src="path/to/mediabunny.js"></script> <script src="mediabunny.cjs"></script>
``` ```
You can download the built distribution file from the [releases page](https://github.com/Vanilagy/mediabunny/releases). This will add a `Mediabunny` object to the global scope.
You can download a built distribution file from the [releases page](https://github.com/Vanilagy/mediabunny/releases). Use the `*.cjs` builds for normal script tag inclusion, or the `*.mjs` builds for script tags with `type="module"` or direct imports via ESM. Including the `mediabunny.d.ts` declaration file in your TypeScript project will declare a global `Mediabunny` namespace.
+1 -1
View File
@@ -237,7 +237,7 @@ await conversion.execute();
</div> </div>
</div> </div>
<div class="flex flex-col-reverse lg:flex-row gap-4 lg:gap-20 lg:items-center"> <div class="flex flex-col-reverse lg:flex-row gap-4 lg:gap-20 items-center">
<div class="relative flex-1 min-w-0"> <div class="relative flex-1 min-w-0">
<div class="absolute size-70 rounded-full bg-[#ff45ac]/0 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 blur-[200px]" /> <div class="absolute size-70 rounded-full bg-[#ff45ac]/0 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 blur-[200px]" />
<img class="relative" src="./assets/inspiring-io.svg"> <img class="relative" src="./assets/inspiring-io.svg">
+1 -1
View File
@@ -253,7 +253,7 @@ const runAudioIterator = async () => {
} }
// To play back audio, we loop over all audio chunks (typically very short) of the file and play them at the correct // To play back audio, we loop over all audio chunks (typically very short) of the file and play them at the correct
// timestamp. The result is a continuous, uninteruppted audio signal. // timestamp. The result is a continuous, uninterrupted audio signal.
for await (const { buffer, timestamp } of audioBufferIterator!) { for await (const { buffer, timestamp } of audioBufferIterator!) {
const node = audioContext!.createBufferSource(); const node = audioContext!.createBufferSource();
node.buffer = buffer; node.buffer = buffer;
+24 -38
View File
@@ -1,12 +1,12 @@
{ {
"name": "mediabunny", "name": "mediabunny",
"version": "1.0.2", "version": "1.0.5",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "mediabunny", "name": "mediabunny",
"version": "1.0.2", "version": "1.0.5",
"license": "MPL-2.0", "license": "MPL-2.0",
"dependencies": { "dependencies": {
"@types/dom-mediacapture-transform": "^0.1.11", "@types/dom-mediacapture-transform": "^0.1.11",
@@ -319,9 +319,9 @@
} }
}, },
"node_modules/@babel/helper-string-parser": { "node_modules/@babel/helper-string-parser": {
"version": "7.25.9", "version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
"integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -329,9 +329,9 @@
} }
}, },
"node_modules/@babel/helper-validator-identifier": { "node_modules/@babel/helper-validator-identifier": {
"version": "7.25.9", "version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
"integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -339,13 +339,13 @@
} }
}, },
"node_modules/@babel/parser": { "node_modules/@babel/parser": {
"version": "7.27.0", "version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz",
"integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/types": "^7.27.0" "@babel/types": "^7.28.0"
}, },
"bin": { "bin": {
"parser": "bin/babel-parser.js" "parser": "bin/babel-parser.js"
@@ -355,14 +355,14 @@
} }
}, },
"node_modules/@babel/types": { "node_modules/@babel/types": {
"version": "7.27.0", "version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz",
"integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-string-parser": "^7.25.9", "@babel/helper-string-parser": "^7.27.1",
"@babel/helper-validator-identifier": "^7.25.9" "@babel/helper-validator-identifier": "^7.27.1"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@@ -1238,18 +1238,14 @@
} }
}, },
"node_modules/@jridgewell/gen-mapping": { "node_modules/@jridgewell/gen-mapping": {
"version": "0.3.8", "version": "0.3.12",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz",
"integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.5.0",
"@jridgewell/sourcemap-codec": "^1.4.10",
"@jridgewell/trace-mapping": "^0.3.24" "@jridgewell/trace-mapping": "^0.3.24"
},
"engines": {
"node": ">=6.0.0"
} }
}, },
"node_modules/@jridgewell/resolve-uri": { "node_modules/@jridgewell/resolve-uri": {
@@ -1262,16 +1258,6 @@
"node": ">=6.0.0" "node": ">=6.0.0"
} }
}, },
"node_modules/@jridgewell/set-array": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/sourcemap-codec": { "node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.0", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
@@ -1280,9 +1266,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@jridgewell/trace-mapping": { "node_modules/@jridgewell/trace-mapping": {
"version": "0.3.25", "version": "0.3.29",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz",
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
+14 -10
View File
@@ -1,25 +1,27 @@
{ {
"name": "mediabunny", "name": "mediabunny",
"author": "Vanilagy", "author": "Vanilagy",
"version": "1.0.2", "version": "1.0.5",
"description": "Pure TypeScript media toolkit for reading, writing, and converting media files, directly in the browser.", "description": "Pure TypeScript media toolkit for reading, writing, and converting media files, directly in the browser.",
"type": "module", "type": "module",
"main": "./dist/mediabunny.js", "main": "./dist/bundles/mediabunny.cjs",
"module": "./dist/mediabunny.mjs", "module": "./dist/modules/index.js",
"types": "./dist/mediabunny.d.ts", "types": "./dist/modules/index.d.ts",
"exports": { "exports": {
"types": "./dist/mediabunny.d.ts", "types": "./dist/modules/index.d.ts",
"import": "./dist/mediabunny.mjs", "import": "./dist/modules/index.js",
"require": "./dist/mediabunny.js" "require": "./dist/bundles/mediabunny.cjs"
}, },
"files": [ "files": [
"README.md", "README.md",
"package.json", "package.json",
"LICENSE", "LICENSE",
"dist" "dist",
"src"
], ],
"sideEffects": false,
"scripts": { "scripts": {
"build": "tsx scripts/ensure-license-headers.ts && node build.mjs && tsc -p src && api-extractor run && npm run check-docblocks && tsx scripts/append-namespace.ts", "build": "rm -rf dist && tsx scripts/ensure-license-headers.ts && tsc -p src && npm run fix-build-import-paths && node build.mjs && api-extractor run && npm run check-docblocks && npm run append-namespace",
"watch": "node build.mjs --watch", "watch": "node build.mjs --watch",
"lint": "eslint .", "lint": "eslint .",
"check": "tsc -p src --noEmit && tsc -p scripts --noEmit && tsc -p tsconfig.vite.json --noEmit && rm tsconfig.vite.tsbuildinfo", "check": "tsc -p src --noEmit && tsc -p scripts --noEmit && tsc -p tsconfig.vite.json --noEmit && rm tsconfig.vite.tsbuildinfo",
@@ -28,7 +30,9 @@
"docs:build": "vitepress build docs && npm run examples:build", "docs:build": "vitepress build docs && npm run examples:build",
"docs:preview": "vitepress preview docs", "docs:preview": "vitepress preview docs",
"dev": "vite", "dev": "vite",
"examples:build": "vite build" "examples:build": "vite build",
"fix-build-import-paths": "find dist -name \"*.js\" -type f -exec sed -i -r \"s/ from '([^']+)';/ from '\\1.js';/g\" {} \\;",
"append-namespace": "echo 'export as namespace Mediabunny;' >> dist/mediabunny.d.ts"
}, },
"license": "MPL-2.0", "license": "MPL-2.0",
"repository": { "repository": {
-3
View File
@@ -1,3 +0,0 @@
import { appendFileSync } from 'fs';
appendFileSync('dist/mediabunny.d.ts', '\nexport as namespace Mediabunny;');
+3
View File
@@ -6,6 +6,9 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
/// <reference types="dom-mediacapture-transform" preserve="true" />
/// <reference types="dom-webcodecs" preserve="true" />
export { export {
Output, Output,
OutputOptions, OutputOptions,
+5 -1
View File
@@ -701,7 +701,11 @@ export class IsobmffDemuxer extends Demuxer {
} }
if (relevantEntryFound) { if (relevantEntryFound) {
throw new Error('Unsupported edit list: multiple edits are not supported.'); console.warn(
'Unsupported edit list: multiple edits are not currently supported. Only using first edit.',
);
break;
} }
if (mediaTime === -1) { if (mediaTime === -1) {
+1 -2
View File
@@ -1,9 +1,8 @@
{ {
"extends": "../tsconfig.json", "extends": "../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "../build", "outDir": "../dist/modules",
"declaration": true, "declaration": true,
"sourceMap": true,
"declarationMap": true, "declarationMap": true,
"stripInternal": true, "stripInternal": true,
"noEmit": false "noEmit": false
+1 -1
View File
@@ -20,7 +20,7 @@ const rollupInput = Object.fromEntries(
export default defineConfig({ export default defineConfig({
resolve: { resolve: {
alias: { alias: {
mediabunny: path.resolve(__dirname, './dist/mediabunny.mjs'), mediabunny: path.resolve(__dirname, './dist/bundles/mediabunny.mjs'),
}, },
}, },
plugins: [ plugins: [