Holistic technical website cleanup

This commit is contained in:
Vanilagy
2026-05-03 19:47:39 +02:00
parent 4810c13c29
commit 1680bd02ad
49 changed files with 407 additions and 41 deletions
+109 -12
View File
@@ -1,3 +1,4 @@
/* eslint-disable @stylistic/max-len */
import { withMermaid } from 'vitepress-plugin-mermaid';
import footnote from 'markdown-it-footnote';
import tailwindcss from '@tailwindcss/vite';
@@ -7,9 +8,12 @@ import { HeadConfig } from 'vitepress';
// @ts-ignore This file gets generated once docs:generate is run
import apiRoutes from '../api/index.json';
import m3u8Grammar from './m3u8-grammar.json' with { type: 'json' };
import fs from 'node:fs/promises';
import path from 'node:path';
const DESCRIPTION = 'A JavaScript library for reading, writing, and converting media files. Directly in the browser,'
+ ' and faster than anybunny else.';
const ORIGIN = 'https://mediabunny.dev';
// https://vitepress.dev/reference/site-config
export default withMermaid({
@@ -17,22 +21,31 @@ export default withMermaid({
description: DESCRIPTION,
cleanUrls: true,
sitemap: {
hostname: 'https://mediabunny.dev',
hostname: ORIGIN,
transformItems: async (items) => {
const entries = await fs.readdir('./examples');
for (const entry of entries) {
const isDirectory = await fs.stat(path.join('./examples', entry)).then(stat => stat.isDirectory());
if (isDirectory) {
items.push({
url: `/examples/${entry}/`, // With trailing slash
});
}
}
return items;
},
},
lastUpdated: true,
// lastUpdated: true,
head: [
['link', { rel: 'icon', type: 'image/png', href: '/mediabunny-logo.png' }],
['link', { rel: 'icon', type: 'image/svg+xml', href: '/mediabunny-logo.svg' }],
['meta', { property: 'og:type', content: 'website' }],
['meta', { property: 'og:site_name', content: 'Mediabunny' }],
['meta', { property: 'og:url', content: 'https://mediabunny.dev/' }],
['meta', { property: 'og:image', content: 'https://mediabunny.dev/mediabunny-og-image.png' }],
['meta', { property: 'og:image', content: `${ORIGIN}/mediabunny-og-image.png` }],
['meta', { property: 'og:locale', content: 'en-US' }],
['meta', { property: 'og:description', content: DESCRIPTION }],
['meta', { name: 'twitter:image', content: 'https://mediabunny.dev/mediabunny-og-image.png' }],
['meta', { name: 'twitter:image', content: `${ORIGIN}/mediabunny-og-image.png` }],
['meta', { name: 'twitter:card', content: 'summary_large_image' }],
['meta', { name: 'twitter:site', content: '@vanilagy' }],
['meta', { name: 'twitter:description', content: DESCRIPTION }],
],
themeConfig: {
logo: '/mediabunny-logo.svg',
@@ -40,12 +53,12 @@ export default withMermaid({
// https://vitepress.dev/reference/default-theme-config
nav: [
{ text: 'Guide', link: '/guide/introduction', activeMatch: '/guide' },
{ text: 'API', link: '/api', activeMatch: '/api' },
{ text: 'API', link: '/api/', activeMatch: '/api/' }, // Trailing slash because it's index.html from there
{ text: 'LLMs', link: '/llms', activeMatch: '/llms' },
{ text: 'Examples', link: '/examples', activeMatch: '/examples' },
{ text: 'Blog', link: '/blog', activeMatch: '/blog' },
{ text: 'Sponsors', link: '/#sponsors', activeMatch: '/#sponsors' },
{ text: 'License', link: 'https://github.com/Vanilagy/mediabunny#license' },
{ text: 'License', link: 'https://github.com/Vanilagy/mediabunny#license', rel: 'noopener' },
{
text: 'More',
items: [
@@ -186,6 +199,8 @@ export default withMermaid({
llmstxt({
ignoreFiles: [
'api/*',
'examples.md',
'llms.md',
],
}),
],
@@ -196,14 +211,96 @@ export default withMermaid({
if (title !== 'Mediabunny') {
title += ' | Mediabunny';
}
const canonicalUrl = `https://mediabunny.dev/${pageData.relativePath}`
const canonicalUrl = `${ORIGIN}/${pageData.relativePath}`
.replace(/index\.md$/, '')
.replace(/\.md$/, '');
const isBlogPost = canonicalUrl.includes('/blog/');
const breadcrumbs: object[] = [];
if (canonicalUrl.includes('/guide/')) {
breadcrumbs.push({
'@type': 'ListItem',
'position': 1,
'name': 'Guide',
'item': `${ORIGIN}/guide`,
}, {
'@type': 'ListItem',
'position': 2,
'name': pageData.title,
});
}
if (canonicalUrl.includes('/api/')) {
breadcrumbs.push({
'@type': 'ListItem',
'position': 1,
'name': 'API docs',
'item': `${ORIGIN}/api/`,
}, {
'@type': 'ListItem',
'position': 2,
'name': pageData.title,
});
}
if (canonicalUrl.includes('/codec-registry/')) {
breadcrumbs.push({
'@type': 'ListItem',
'position': 1,
'name': 'Codec registry',
'item': `${ORIGIN}/codec-registry/overview`,
}, {
'@type': 'ListItem',
'position': 2,
'name': pageData.title,
});
}
((pageData.frontmatter['head'] ??= []) as HeadConfig[]).push(
['meta', { property: 'og:type', content: isBlogPost ? 'article' : 'website' }],
['meta', { property: 'og:title', content: title }],
['meta', { property: 'twitter:title', content: title }],
['meta', { property: 'og:description', content: pageData.description || DESCRIPTION }],
['meta', { property: 'og:url', content: canonicalUrl }],
['meta', { name: 'twitter:title', content: title }],
['meta', { name: 'twitter:description', content: pageData.description || DESCRIPTION }],
['link', { rel: 'canonical', href: canonicalUrl }],
);
if (isBlogPost) {
((pageData.frontmatter['head'] ??= []) as HeadConfig[]).push(
['meta', { property: 'article:published_time', content: String(pageData.frontmatter['publishedOnIso']) }],
['meta', { property: 'article:author', content: String(pageData.frontmatter['author']) }],
);
breadcrumbs.push({
'@type': 'ListItem',
'position': 1,
'name': 'Blog posts',
'item': `${ORIGIN}/blog`,
}, {
'@type': 'ListItem',
'position': 2,
'name': pageData.title,
});
}
if (breadcrumbs.length > 0) {
((pageData.frontmatter['head'] ??= []) as HeadConfig[]).push(
['script', { type: 'application/ld+json' }, JSON.stringify({
'@context': 'https://schema.org',
'@type': 'BreadcrumbList',
'itemListElement': breadcrumbs,
})],
);
}
},
buildEnd: async () => {
const files = await fs.readdir('./docs/api');
for (const file of files) {
await fs.copyFile('./docs/api/' + file, './dist-docs/api/' + file);
}
},
});
+1
View File
@@ -1,6 +1,7 @@
{
"heading": "Mediabunny API reference",
"intro": "Here you can find detailed documentation for all classes, functions, constants and types exposed by Mediabunny's public API.",
"description": "Detailed documentation for all classes, functions, constants and types exposed by Mediabunny's public API.",
"Samples": "Raw, unencoded chunks of media data, such as video frames or sections of audio.",
"Packets": "Chunks of encoded media data.",
+2
View File
@@ -1,4 +1,6 @@
---
title: Blog posts
description: Announcements, news, and devblogs about Mediabunny.
outline: false
---
+2
View File
@@ -1,6 +1,8 @@
---
title: Mediabunny now supports HLS!
description: Mediabunny v1.42.0 adds read/write support for HTTP Live Streaming (HLS), pushing the frontier of fully client-side media processing.
publishedOn: April 24, 2026
publishedOnIso: "2026-04-24"
author: Vanilagy
authorImage: /vani.png
authorLink: https://github.com/Vanilagy
+4
View File
@@ -1,3 +1,7 @@
---
description: Advanced Audio Coding (AAC) audio codec definition, defining legal codec strings, decoder configs, and packet data formats.
---
<script setup>
import { VPBadge } from 'vitepress/theme'
</script>
+4
View File
@@ -1,3 +1,7 @@
---
description: Dolby Digital (AC-3) audio codec definition, defining legal codec strings, decoder configs, and packet data formats.
---
<script setup>
import { VPBadge } from 'vitepress/theme'
</script>
+4
View File
@@ -1,3 +1,7 @@
---
description: A-law companded PCM audio codec definition, defining legal codec strings, decoder configs, and packet data formats.
---
<script setup>
import { VPBadge } from 'vitepress/theme'
</script>
+4
View File
@@ -1,3 +1,7 @@
---
description: AOMedia Video 1 (AV1) video codec definition, defining legal codec strings, decoder configs, and packet data formats.
---
<script setup>
import { VPBadge } from 'vitepress/theme'
</script>
+4
View File
@@ -1,3 +1,7 @@
---
description: Advanced Video Coding (H.264) video codec definition, defining legal codec strings, decoder configs, and packet data formats.
---
<script setup>
import { VPBadge } from 'vitepress/theme'
</script>
+4
View File
@@ -1,3 +1,7 @@
---
description: Dolby Digital Plus (E-AC-3) audio codec definition, defining legal codec strings, decoder configs, and packet data formats.
---
<script setup>
import { VPBadge } from 'vitepress/theme'
</script>
+4
View File
@@ -1,3 +1,7 @@
---
description: Free Lossless Audio Codec (FLAC) audio codec definition, defining legal codec strings, decoder configs, and packet data formats.
---
<script setup>
import { VPBadge } from 'vitepress/theme'
</script>
+4
View File
@@ -1,3 +1,7 @@
---
description: High Efficiency Video Coding (H.265) video codec definition, defining legal codec strings, decoder configs, and packet data formats.
---
<script setup>
import { VPBadge } from 'vitepress/theme'
</script>
+4
View File
@@ -1,3 +1,7 @@
---
description: MP3 (MPEG-1/2 Audio Layer III) audio codec definition, defining legal codec strings, decoder configs, and packet data formats.
---
<script setup>
import { VPBadge } from 'vitepress/theme'
</script>
+4
View File
@@ -1,3 +1,7 @@
---
description: Opus audio codec definition, defining legal codec strings, decoder configs, and packet data formats.
---
<script setup>
import { VPBadge } from 'vitepress/theme'
</script>
+4
View File
@@ -1,3 +1,7 @@
---
description: The Mediabunny Codec Registry formalizes the precise definitions of all video and audio codecs supported by Mediabunny, like expected codec string and packet data format.
---
# Mediabunny Codec Registry
The Mediabunny Codec Registry formalizes the precise definitions of all video and audio codecs supported by Mediabunny. More specifically, for any given codec, it describes the format that `EncodedPacket`, `VideoDecoderConfig` and `AudioDecoderConfig` must adhere to. All packets coming out of or going into Mediabunny are expected to adhere to this registry.
+4
View File
@@ -1,3 +1,7 @@
---
description: PCM audio codec definitions, defining legal codec strings, decoder configs, and packet data formats.
---
<script setup>
import { VPBadge } from 'vitepress/theme'
</script>
+4
View File
@@ -1,3 +1,7 @@
---
description: μ-law companded PCM audio codec definition, defining legal codec strings, decoder configs, and packet data formats.
---
<script setup>
import { VPBadge } from 'vitepress/theme'
</script>
+4
View File
@@ -1,3 +1,7 @@
---
description: Vorbis audio codec definition, defining legal codec strings, decoder configs, and packet data formats.
---
<script setup>
import { VPBadge } from 'vitepress/theme'
</script>
+4
View File
@@ -1,3 +1,7 @@
---
description: VP8 video codec definition, defining legal codec strings, decoder configs, and packet data formats.
---
<script setup>
import { VPBadge } from 'vitepress/theme'
</script>
+4
View File
@@ -1,3 +1,7 @@
---
description: VP9 video codec definition, defining legal codec strings, decoder configs, and packet data formats.
---
<script setup>
import { VPBadge } from 'vitepress/theme'
</script>
+1
View File
@@ -1,4 +1,5 @@
---
description: "Demos showcasing the various features of Mediabunny: metadata extraction, thumbnail generation, compression, media playback, live streaming, and more."
layout: home
title: Examples
+4
View File
@@ -1,3 +1,7 @@
---
description: Efficiently convert any media file to any format, directly in the browser. Optionally apply trimming, video resizing, rotation, custom overlays, and more.
---
# Converting media files
The [reading](./reading-media-files) and [writing](./writing-media-files) primitives in Mediabunny provide everything you need to convert media files. However, since this is such a common operation and the details can be tricky, Mediabunny ships with a built-in file conversion abstraction.
+4
View File
@@ -1,3 +1,7 @@
---
description: The @mediabunny/aac-encoder extension provides a fast AAC encoder polyfill for use in the browser and on the server.
---
# @mediabunny/aac-encoder
Some browsers lack support for AAC encoding in their WebCodecs implementations. This extension package provides a reliable AAC-LC encoder for use with Mediabunny. It is implemented using Mediabunny's [custom coder API](../supported-formats-and-codecs#custom-coders) and uses a fast, size-optimized WASM build of [FFmpeg](https://ffmpeg.org/)'s AAC encoder under the hood.
+4
View File
@@ -1,3 +1,7 @@
---
description: The @mediabunny/ac3 extension provides fast AC-3 and E-AC-3 decoders and encoders for both browser and server environments.
---
# @mediabunny/ac3
Browsers have no support for AC-3 (Dolby Digital) or E-AC-3 (Dolby Digital Plus) in their WebCodecs implementations. This extension package provides both a decoder and encoder for use with Mediabunny, allowing you to decode and encode these codecs directly in the browser. It is implemented using Mediabunny's [custom coder API](../supported-formats-and-codecs#custom-coders) and uses a fast, size-optimized WASM build of [FFmpeg](https://ffmpeg.org/)'s AC-3 and E-AC-3 coders under the hood.
+4
View File
@@ -1,3 +1,7 @@
---
description: The @mediabunny/flac-encoder extension provides a highly-performant FLAC encoder polyfill for use in the browser and on the server.
---
# @mediabunny/flac-encoder
No browser currently supports FLAC encoding in their WebCodecs implementations. This extension package provides a reliable FLAC encoder for use with Mediabunny. It is implemented using Mediabunny's [custom coder API](../supported-formats-and-codecs#custom-coders) and uses a fast, size-optimized WASM build of [libFLAC](https://github.com/xiph/flac) under the hood.
+4
View File
@@ -1,3 +1,7 @@
---
description: The @mediabunny/mp3-encoder extension provides a highly-performant MP3 encoder polyfill for use in the browser and on the server.
---
# @mediabunny/mp3-encoder
Browsers typically have no support for MP3 encoding in their WebCodecs implementations. Given the ubiquity of the format, this extension package provides an MP3 encoder for use with Mediabunny. It is implemented using Mediabunny's [custom coder API](../supported-formats-and-codecs#custom-coders) and uses a highly-performant WASM build of the [LAME MP3 Encoder](https://lame.sourceforge.io/) under the hood.
+4
View File
@@ -1,3 +1,7 @@
---
description: Mediabunny supports a wide range of media input formats, such as MP4, WebM, MP3, HLS, and many more.
---
# Input formats
Mediabunny supports a wide variety of commonly used container formats for reading input files. These *input formats* are used in two ways:
+4
View File
@@ -1,3 +1,7 @@
---
description: Install Mediabunny using npm (or your favorite package manager), or include it directly as a <script> tag.
---
# Installation
Install Mediabunny using your favorite package manager:
+4
View File
@@ -1,3 +1,7 @@
---
description: Mediabunny is a zero-dependency, tree-shakable TypeScript library for reading, writing and converting media files in the browser. Like FFmpeg, but for the web.
---
# Introduction
Mediabunny is a JavaScript library for reading, writing, and converting media files (like MP4 or WebM), 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, 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 for the web's needs.
+4
View File
@@ -1,3 +1,7 @@
---
description: Media sinks enable different ways to extract video and audio data from files, from built-in decoding to manual per-packet control.
---
# Media sinks
## Introduction
+4
View File
@@ -1,3 +1,7 @@
---
description: Media sources enable multiple ways to add media data to new media files, from built-in encoding to manual per-packet control.
---
# Media sources
## Introduction
+4
View File
@@ -1,3 +1,7 @@
---
description: Mediabunny can write a wide range of media output formats, including MP4, WebM, MP3, HLS, and many more.
---
# Output formats
## Introduction
+4
View File
@@ -1,3 +1,7 @@
---
description: Learn about how packets carry encoded media data, samples carry raw decoded media data, and the operations you can perform on them.
---
# Packets & samples
## Introduction
+4
View File
@@ -1,3 +1,7 @@
---
description: A collection of short code snippets that showcase the most common operations that Mediabunny can do.
---
# Quick start
This page is a collection of short code snippets that showcase the most common operations you may use this library for.
+4
View File
@@ -1,3 +1,7 @@
---
description: Use Mediabunny to read HLS (.m3u8) playlists, both VOD and live. Extract tracks, metadata, and media data efficiently and with precise control.
---
# Reading HLS
Mediabunny has full support for reading HLS (.m3u8) playlists, both VOD and live. This page will go into HLS-specific behavior and advice. For general information about how to read any media file (including HLS) in Mediabunny, refer to [Reading media files](./reading-media-files).
+4
View File
@@ -1,3 +1,7 @@
---
description: Efficiently extract metadata, video frames, and audio samples from any media file, such as MP4 or WebM.
---
# Reading media files
Mediabunny allows you to read media files with great control and efficiency. You can use it to extract metadata (such as duration or resolution), as well as to read actual media data from video and audio tracks with frame-accurate timing. Many commonly used [input file formats](./input-formats) are supported. Using [input sources](#input-sources), data can be read from multiple sources, such as directly from memory, from the user's disk, or even over the network.
@@ -1,3 +1,7 @@
---
description: Mediabunny supports a wide range of media container formats (.mp4, .webm, .mp3, .wav, .m3u8, ...) and video/audio codecs (H.264, HEVC, VP9, AV1, AAC, Opus, FLAC, ...).
---
# Supported formats & codecs
## Container formats
+1
View File
@@ -1,4 +1,5 @@
---
description: Mediabunny can create new HLS (.m3u8) playlists directly in the browser, both VOD and live. Define tracks, add media data, and upload directly to a server.
outline: [2, 4]
---
+4
View File
@@ -1,3 +1,7 @@
---
description: Use Mediabunny to create new video and audio files of any size directly in the browser, and with full control over frame timing, tracks, and more.
---
# Writing media files
Mediabunny enables you to create media files with very fine levels of control. You can add an arbitrary number of video, audio and subtitle tracks to a media file, and precisely control the timing of media data. This library supports [many output file formats](./output-formats). Using [output targets](#output-targets), you can decide if you want to build up the entire file in memory or stream it out in chunks as it's being created - allowing you to create very large files.
+12 -11
View File
@@ -1,7 +1,8 @@
---
layout: home
title: Mediabunny
title: Mediabunny — A complete JavaScript media toolkit for the browser
titleTemplate: false
hero:
name: Mediabunny
@@ -155,7 +156,7 @@ const sponsors = {
<p class="!my-0 flex-1 text-sm !leading-6">{{ quote.quote }}</p>
<div class="shrink-0 flex gap-2 items-center mt-1.5">
<a :href="quote.url" target="_blank">
<img :src="quote.image" class="size-8 rounded-full shrink-0" alt="Author image">
<img :src="quote.image" class="size-8 rounded-full shrink-0" :alt="quote.author">
</a>
<p class="!my-0 flex-1 text-xs font-medium">{{ quote.author }}</p>
</div>
@@ -173,7 +174,7 @@ npm install mediabunny
<div class="space-y-16 mt-18">
<div class="flex flex-col lg:flex-row lg:gap-20 lg:items-center">
<div class="flex-1 min-w-0">
<h1 class="inline-block" style="background: -webkit-linear-gradient(-30deg, #ff45ac, #ff78c2); -webkit-background-clip: text; color: transparent;">Read any media file, efficiently</h1>
<h2 class="inline-block !text-[32px] !border-0 !m-0 !p-0 !leading-[40px]" style="background: -webkit-linear-gradient(-30deg, #ff45ac, #ff78c2); -webkit-background-clip: text; color: transparent;">Read any media file, efficiently</h2>
<p class="text-lg">Mediabunny allows you efficiently read data from any video or audio file, no matter the size: duration, resolution, rotation, tracks, codecs and other metadata, as well as raw or decoded media data from anywhere in the file. Load only what you need.</p>
<a class="!no-underline inline-flex items-center gap-1.5" :no-icon="true" href="/guide/reading-media-files">
Docs
@@ -249,7 +250,7 @@ const { buffer } = output.target; // Contains the final file
</div>
<div class="flex-1 min-w-0">
<h1 class="inline-block" style="background: -webkit-linear-gradient(-30deg, #ff45ac, #ff78c2); -webkit-background-clip: text; color: transparent;">Create new media files, programmatically</h1>
<h2 class="inline-block !text-[32px] !border-0 !m-0 !p-0 !leading-[40px]" style="background: -webkit-linear-gradient(-30deg, #ff45ac, #ff78c2); -webkit-background-clip: text; color: transparent;">Create new media files, programmatically</h2>
<p class="text-lg">Generate new media files (such as MP4 or WebM) directly on the client, and as fast as the hardware allows. Add multiple video, audio, or subtitle tracks, and have precise control down to the microsecond.</p>
<a class="!no-underline inline-flex items-center gap-1.5" :no-icon="true" href="/guide/writing-media-files">
Docs
@@ -260,7 +261,7 @@ const { buffer } = output.target; // Contains the final file
<div class="flex flex-col lg:flex-row lg:gap-20 lg:items-center">
<div class="flex-1 min-w-0">
<h1 class="inline-block" style="background: -webkit-linear-gradient(-30deg, #ff45ac, #ff78c2); -webkit-background-clip: text; color: transparent;">Hopping-fast file conversion</h1>
<h2 class="inline-block !text-[32px] !border-0 !m-0 !p-0 !leading-[40px]" style="background: -webkit-linear-gradient(-30deg, #ff45ac, #ff78c2); -webkit-background-clip: text; color: transparent;">Hopping-fast file conversion</h2>
<p class="text-lg">Use the Conversion API to transform any media file into any other media file: perform transmuxing, transcoding, resizing, rotation, audio resampling, trimming, and more.</p>
<a class="!no-underline inline-flex items-center gap-1.5" :no-icon="true" href="/guide/converting-media-files">
Docs
@@ -296,14 +297,14 @@ await conversion.execute();
<img class="relative" src="./assets/inspiring-io.svg">
</div>
<div class="flex-1 min-w-0">
<h1 class="inline-block" style="background: -webkit-linear-gradient(-30deg, #ff45ac, #ff78c2); -webkit-background-clip: text; color: transparent;">Universal I/O</h1>
<h2 class="inline-block !text-[32px] !border-0 !m-0 !p-0 !leading-[40px]" style="background: -webkit-linear-gradient(-30deg, #ff45ac, #ff78c2); -webkit-background-clip: text; color: transparent;">Universal I/O</h2>
<p class="text-lg">Read and write files from and to memory, disk, or the network. Create files for offline use, or live-stream them as they're being created. Inject media data from a canvas, webcam, screen, microphone, audio buffer, your own encoding stack, or whatever. It's all up to you.</p>
</div>
</div>
<div class="flex flex-col lg:flex-row gap-4 lg:gap-20 lg:items-center">
<div class="flex-1 min-w-0">
<h1 class="inline-block" style="background: -webkit-linear-gradient(-30deg, #ff45ac, #ff78c2); -webkit-background-clip: text; color: transparent;">Wide container & codec support</h1>
<h2 class="inline-block !text-[32px] !border-0 !m-0 !p-0 !leading-[40px]" style="background: -webkit-linear-gradient(-30deg, #ff45ac, #ff78c2); -webkit-background-clip: text; color: transparent;">Wide container & codec support</h2>
<p class="text-lg">Mediabunny supports many commonly used container formats and a wide variety of video and audio codecs. And all of them bidirectionally, too! (that means for reading and writing)</p>
<a class="!no-underline inline-flex items-center gap-1.5" :no-icon="true" href="/guide/supported-formats-and-codecs">
See full list
@@ -329,14 +330,14 @@ await conversion.execute();
<p class="!my-0 text-center text-[10px] opacity-50 !leading-4">Reading BigBuckBunny1080pH264.mov (691 MiB) from disk<br>Ryzen 7600X, RTX 4070, NVMe SSD, measured 2025-06-22</p>
</div>
<div class="flex-1 min-w-0">
<h1 class="inline-block" style="background: -webkit-linear-gradient(-30deg, #ff45ac, #ff78c2); -webkit-background-clip: text; color: transparent;">High performance</h1>
<h2 class="inline-block !text-[32px] !border-0 !m-0 !p-0 !leading-[40px]" style="background: -webkit-linear-gradient(-30deg, #ff45ac, #ff78c2); -webkit-background-clip: text; color: transparent;">High performance</h2>
<p class="text-lg">By reading only what you need, writing progressively, utilizing hardware-accelerated encoding and decoding via the WebCodecs API, and using a pipelined design, Mediabunny is able to get the job done fast.</p>
</div>
</div>
<div class="flex flex-col lg:flex-row gap-4 lg:gap-20 lg:items-center">
<div class="flex-1 min-w-0">
<h1 class="inline-block" style="background: -webkit-linear-gradient(-30deg, #ff45ac, #ff78c2); -webkit-background-clip: text; color: transparent;">Built from scratch, for the web</h1>
<h2 class="inline-block !text-[32px] !border-0 !m-0 !p-0 !leading-[40px]" style="background: -webkit-linear-gradient(-30deg, #ff45ac, #ff78c2); -webkit-background-clip: text; color: transparent;">Built from scratch, for the web</h2>
<p class="text-lg">Mediabunny is 100% implemented in TypeScript and has zero dependencies. Its API was designed to be highly tree-shakable, meaning you only include what you use.</p>
</div>
<div class="space-y-2 flex-1 min-w-0">
@@ -369,10 +370,10 @@ await conversion.execute();
<hr class="!my-16" />
<div class="flex flex-col items-center">
<h1 id="sponsors" class="flex items-center gap-4" style="background: -webkit-linear-gradient(-30deg, #ff45ac, #ff78c2); -webkit-background-clip: text; color: transparent;">
<h2 id="sponsors" class="flex items-center gap-4 !text-[32px] !border-0 !m-0 !p-0 !leading-[40px]" style="background: -webkit-linear-gradient(-30deg, #ff45ac, #ff78c2); -webkit-background-clip: text; color: transparent;">
Made possible by you
<img class="size-8" src="./assets/fluent-emoji--heart-suit.svg">
</h1>
</h2>
<p class="max-w-2xl">Mediabunny is an open-source project released under the <a href="https://choosealicense.com/licenses/mpl-2.0/" target="_blank">MPL-2.0</a> and is therefore free to use for any purpose, including closed-source commercial use. A permissive license is essential for a foundational library like this to truly thrive. That said, this project requires an immense amount of work and care. This is made possible by the generous financial backing of these awesome sponsors:</p>
<template v-if="sponsors.gold.length > 0">
<h3 class="!text-3xl">Gold sponsors</h3>
+4
View File
@@ -1,3 +1,7 @@
---
description: Teach Claude Code, Codex, Cursor, Copilot or any other AI coding agent how to make full use of Mediabunny.
---
# Mediabunny and LLMs
<div class="grid place-items-center my-14">
+16 -2
View File
@@ -1,15 +1,29 @@
<!DOCTYPE html>
<html lang="en" translate="no">
<html lang="en-US" translate="no">
<head>
<meta charset="UTF-8">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>File compression example | Mediabunny</title>
<meta name="description" content="Select or drop a media file, and Mediabunny will convert it to a heavily-compressed MP4 file.">
<script type="module" src="../base.ts"></script>
<script type="module" src="./file-compression.ts"></script>
<link rel="stylesheet" href="../base.css">
<link rel="icon" href="../../docs/public/mediabunny-logo.svg">
<link rel="canonical" href="https://mediabunny.dev/examples/file-compression/">
<meta property="og:site_name" content="Mediabunny">
<meta property="og:type" content="website">
<meta property="og:title" content="File compression example | Mediabunny">
<meta property="og:description" content="Select or drop a media file, and Mediabunny will convert it to a heavily-compressed MP4 file.">
<meta property="og:url" content="https://mediabunny.dev/examples/file-compression/">
<meta property="og:image" content="https://mediabunny.dev/mediabunny-og-image.png">
<meta property="og:locale" content="en-US">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@vanilagy">
<meta name="twitter:title" content="File compression example | Mediabunny">
<meta name="twitter:description" content="Select or drop a media file, and Mediabunny will convert it to a heavily-compressed MP4 file.">
<meta name="twitter:image" content="https://mediabunny.dev/mediabunny-og-image.png">
<script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Examples","item":"https://mediabunny.dev/examples"},{"@type":"ListItem","position":2,"name":"File compression"}]}</script>
</head>
<body class="flex flex-col items-center py-10 bg-zinc-50 text-zinc-800 dark:bg-zinc-900 dark:text-zinc-200 px-2">
+16 -2
View File
@@ -1,15 +1,29 @@
<!DOCTYPE html>
<html lang="en" translate="no">
<html lang="en-US" translate="no">
<head>
<meta charset="UTF-8">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HLS transcoding example | Mediabunny</title>
<meta name="description" content="Select a directory, then a video. Mediabunny will create a complete HLS VOD package with five video renditions and one audio track.">
<script type="module" src="../base.ts"></script>
<script type="module" src="./hls-transcoding.ts"></script>
<link rel="stylesheet" href="../base.css">
<link rel="icon" href="../../docs/public/mediabunny-logo.svg">
<link rel="canonical" href="https://mediabunny.dev/examples/hls-transcoding/">
<meta property="og:site_name" content="Mediabunny">
<meta property="og:type" content="website">
<meta property="og:title" content="HLS transcoding example | Mediabunny">
<meta property="og:description" content="Select a directory, then a video. Mediabunny will create a complete HLS VOD package with five video renditions and one audio track.">
<meta property="og:url" content="https://mediabunny.dev/examples/hls-transcoding/">
<meta property="og:image" content="https://mediabunny.dev/mediabunny-og-image.png">
<meta property="og:locale" content="en-US">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@vanilagy">
<meta name="twitter:title" content="HLS transcoding example | Mediabunny">
<meta name="twitter:description" content="Select a directory, then a video. Mediabunny will create a complete HLS VOD package with five video renditions and one audio track.">
<meta name="twitter:image" content="https://mediabunny.dev/mediabunny-og-image.png">
<script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Examples","item":"https://mediabunny.dev/examples"},{"@type":"ListItem","position":2,"name":"HLS transcoding"}]}</script>
</head>
<body class="flex flex-col items-center bg-zinc-50 px-2 py-10 text-zinc-800 dark:bg-zinc-900 dark:text-zinc-200">
+16 -2
View File
@@ -1,15 +1,29 @@
<!DOCTYPE html>
<html lang="en" translate="no">
<html lang="en-US" translate="no">
<head>
<meta charset="UTF-8">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Live recording & streaming example | Mediabunny</title>
<meta name="description" content="The live canvas state and your microphone input will be written into a fragmented MP4 file and live-streamed to a &lt;video&gt; element.">
<script type="module" src="../base.ts"></script>
<script type="module" src="./live-recording.ts"></script>
<link rel="stylesheet" href="../base.css">
<link rel="icon" href="../../docs/public/mediabunny-logo.svg">
<link rel="canonical" href="https://mediabunny.dev/examples/live-recording/">
<meta property="og:site_name" content="Mediabunny">
<meta property="og:type" content="website">
<meta property="og:title" content="Live recording & streaming example | Mediabunny">
<meta property="og:description" content="The live canvas state and your microphone input will be written into a fragmented MP4 file and live-streamed to a &lt;video&gt; element.">
<meta property="og:url" content="https://mediabunny.dev/examples/live-recording/">
<meta property="og:image" content="https://mediabunny.dev/mediabunny-og-image.png">
<meta property="og:locale" content="en-US">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@vanilagy">
<meta name="twitter:title" content="Live recording & streaming example | Mediabunny">
<meta name="twitter:description" content="The live canvas state and your microphone input will be written into a fragmented MP4 file and live-streamed to a &lt;video&gt; element.">
<meta name="twitter:image" content="https://mediabunny.dev/mediabunny-og-image.png">
<script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Examples","item":"https://mediabunny.dev/examples"},{"@type":"ListItem","position":2,"name":"Live recording & streaming"}]}</script>
</head>
<body class="flex flex-col items-center py-10 bg-zinc-50 text-zinc-800 dark:bg-zinc-900 dark:text-zinc-200 px-2">
+16 -2
View File
@@ -1,15 +1,29 @@
<!DOCTYPE html>
<html lang="en" translate="no">
<html lang="en-US" translate="no">
<head>
<meta charset="UTF-8">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Media player example | Mediabunny</title>
<meta name="description" content="Select or drop a media file, and a fully custom, Mediabunny-powered player will appear.">
<script type="module" src="../base.ts"></script>
<script type="module" src="./media-player.ts"></script>
<link rel="stylesheet" href="../base.css">
<link rel="icon" href="../../docs/public/mediabunny-logo.svg">
<link rel="canonical" href="https://mediabunny.dev/examples/media-player/">
<meta property="og:site_name" content="Mediabunny">
<meta property="og:type" content="website">
<meta property="og:title" content="Media player example | Mediabunny">
<meta property="og:description" content="Select or drop a media file, and a fully custom, Mediabunny-powered player will appear.">
<meta property="og:url" content="https://mediabunny.dev/examples/media-player/">
<meta property="og:image" content="https://mediabunny.dev/mediabunny-og-image.png">
<meta property="og:locale" content="en-US">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@vanilagy">
<meta name="twitter:title" content="Media player example | Mediabunny">
<meta name="twitter:description" content="Select or drop a media file, and a fully custom, Mediabunny-powered player will appear.">
<meta name="twitter:image" content="https://mediabunny.dev/mediabunny-og-image.png">
<script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Examples","item":"https://mediabunny.dev/examples"},{"@type":"ListItem","position":2,"name":"Media player"}]}</script>
</head>
<body class="flex flex-col items-center py-10 bg-zinc-50 text-zinc-800 dark:bg-zinc-900 dark:text-zinc-200 px-2 h-svh">
+16 -2
View File
@@ -1,15 +1,29 @@
<!DOCTYPE html>
<html lang="en" translate="no">
<html lang="en-US" translate="no">
<head>
<meta charset="UTF-8">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Metadata extraction example | Mediabunny</title>
<meta name="description" content="Select or drop a media file, and Mediabunny will start extracting various metadata about that file.">
<script type="module" src="../base.ts"></script>
<script type="module" src="./metadata-extraction.ts"></script>
<link rel="stylesheet" href="../base.css">
<link rel="icon" href="../../docs/public/mediabunny-logo.svg">
<link rel="canonical" href="https://mediabunny.dev/examples/metadata-extraction/">
<meta property="og:site_name" content="Mediabunny">
<meta property="og:type" content="website">
<meta property="og:title" content="Metadata extraction example | Mediabunny">
<meta property="og:description" content="Select or drop a media file, and Mediabunny will start extracting various metadata about that file.">
<meta property="og:url" content="https://mediabunny.dev/examples/metadata-extraction/">
<meta property="og:image" content="https://mediabunny.dev/mediabunny-og-image.png">
<meta property="og:locale" content="en-US">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@vanilagy">
<meta name="twitter:title" content="Metadata extraction example | Mediabunny">
<meta name="twitter:description" content="Select or drop a media file, and Mediabunny will start extracting various metadata about that file.">
<meta name="twitter:image" content="https://mediabunny.dev/mediabunny-og-image.png">
<script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Examples","item":"https://mediabunny.dev/examples"},{"@type":"ListItem","position":2,"name":"Metadata extraction"}]}</script>
</head>
<body class="flex flex-col items-center py-10 bg-zinc-50 text-zinc-800 dark:bg-zinc-900 dark:text-zinc-200 px-2">
+16 -2
View File
@@ -1,15 +1,29 @@
<!DOCTYPE html>
<html lang="en" translate="no">
<html lang="en-US" translate="no">
<head>
<meta charset="UTF-8">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Procedural Generation example | Mediabunny</title>
<meta name="description" content="Using Mediabunny, this page will procedurally generate a video of musical bouncing balls as fast as possible.">
<script type="module" src="../base.ts"></script>
<script type="module" src="./procedural-generation.ts"></script>
<link rel="stylesheet" href="../base.css">
<link rel="icon" href="../../docs/public/mediabunny-logo.svg">
<link rel="canonical" href="https://mediabunny.dev/examples/procedural-generation/">
<meta property="og:site_name" content="Mediabunny">
<meta property="og:type" content="website">
<meta property="og:title" content="Procedural Generation example | Mediabunny">
<meta property="og:description" content="Using Mediabunny, this page will procedurally generate a video of musical bouncing balls as fast as possible.">
<meta property="og:url" content="https://mediabunny.dev/examples/procedural-generation/">
<meta property="og:image" content="https://mediabunny.dev/mediabunny-og-image.png">
<meta property="og:locale" content="en-US">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@vanilagy">
<meta name="twitter:title" content="Procedural Generation example | Mediabunny">
<meta name="twitter:description" content="Using Mediabunny, this page will procedurally generate a video of musical bouncing balls as fast as possible.">
<meta name="twitter:image" content="https://mediabunny.dev/mediabunny-og-image.png">
<script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Examples","item":"https://mediabunny.dev/examples"},{"@type":"ListItem","position":2,"name":"Procedural generation"}]}</script>
</head>
<body class="flex flex-col items-center py-10 bg-zinc-50 text-zinc-800 dark:bg-zinc-900 dark:text-zinc-200 px-2">
+16 -2
View File
@@ -1,15 +1,29 @@
<!DOCTYPE html>
<html lang="en" translate="no">
<html lang="en-US" translate="no">
<head>
<meta charset="UTF-8">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Thumbnail generation example | Mediabunny</title>
<meta name="description" content="Select or drop a media file, and Mediabunny will extract video thumbnails for it.">
<script type="module" src="./../base.ts"></script>
<script type="module" src="./thumbnail-generation.ts"></script>
<link rel="stylesheet" href="../base.css">
<link rel="icon" href="../../docs/public/mediabunny-logo.svg">
<link rel="canonical" href="https://mediabunny.dev/examples/thumbnail-generation/">
<meta property="og:site_name" content="Mediabunny">
<meta property="og:type" content="website">
<meta property="og:title" content="Thumbnail generation example | Mediabunny">
<meta property="og:description" content="Select or drop a media file, and Mediabunny will extract video thumbnails for it.">
<meta property="og:url" content="https://mediabunny.dev/examples/thumbnail-generation/">
<meta property="og:image" content="https://mediabunny.dev/mediabunny-og-image.png">
<meta property="og:locale" content="en-US">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@vanilagy">
<meta name="twitter:title" content="Thumbnail generation example | Mediabunny">
<meta name="twitter:description" content="Select or drop a media file, and Mediabunny will extract video thumbnails for it.">
<meta name="twitter:image" content="https://mediabunny.dev/mediabunny-og-image.png">
<script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Examples","item":"https://mediabunny.dev/examples"},{"@type":"ListItem","position":2,"name":"Thumbnail generation"}]}</script>
</head>
<body class="flex flex-col items-center py-10 bg-gray-50 text-gray-800 dark:bg-zinc-900 dark:text-zinc-200 px-2">
+31 -4
View File
@@ -49,11 +49,13 @@ const generateDocs = (entryFiles: string[], apiConfigFile: string, dry = false)
// Extract special fields
const headingText = apiConfig['heading'] || 'API Reference';
const introText = apiConfig['intro'];
const indexDescription = apiConfig['description'];
// Create a copy without the special fields for group processing
const groupConfig = { ...apiConfig };
delete groupConfig['heading'];
delete groupConfig['intro'];
delete groupConfig['description'];
// Clear and recreate output directory (skip if dry run)
if (!dry) {
@@ -712,7 +714,7 @@ const generateDocs = (entryFiles: string[], apiConfigFile: string, dry = false)
? `${variableName}(\n${params.join(',\n')},\n): ${returnType};`
: `${variableName}(): ${returnType};`;
let markdown = `<script setup>\nimport { VPBadge } from 'vitepress/theme'\n</script>\n\n<VPBadge type="info" text="Function" />\n\n# ${variableName}\n\n\`\`\`ts\n${functionSig}\n\`\`\`${description ? `\n\n${description}` : ''}`;
let markdown = `${buildFrontmatter(description)}<script setup>\nimport { VPBadge } from 'vitepress/theme'\n</script>\n\n<VPBadge type="info" text="Function" />\n\n# ${variableName}\n\n\`\`\`ts\n${functionSig}\n\`\`\`${description ? `\n\n${description}` : ''}`;
// Find referenced types in all parameters and return type
const allTypeStrings = params.map(p => p.replace(/\t.*?:\s*/, '')).concat([returnType]);
@@ -726,7 +728,7 @@ const generateDocs = (entryFiles: string[], apiConfigFile: string, dry = false)
}
} else {
// Handle regular variables
let markdown = `<script setup>\nimport { VPBadge } from 'vitepress/theme'\n</script>\n\n<VPBadge type="info" text="Constant" />\n\n# ${variableName}\n\n${description ? `${description}\n\n` : ''}`;
let markdown = `${buildFrontmatter(description)}<script setup>\nimport { VPBadge } from 'vitepress/theme'\n</script>\n\n<VPBadge type="info" text="Constant" />\n\n# ${variableName}\n\n${description ? `${description}\n\n` : ''}`;
const variableValue = declaration.initializer ? declaration.initializer.getText() : 'undefined';
const variableDefinition = `const ${variableName} = ${variableValue};`;
markdown += `\`\`\`ts\n${variableDefinition}\n\`\`\``;
@@ -1512,7 +1514,7 @@ const generateDocs = (entryFiles: string[], apiConfigFile: string, dry = false)
deprecatedProperties.sort(compareMemberNames);
deprecatedMethods.sort(compareMemberNames);
let markdown = '';
let markdown = buildFrontmatter(description);
// Add VPBadge import and badge for all types
markdown += `<script setup>\nimport { VPBadge } from 'vitepress/theme'\n</script>\n\n`;
@@ -1794,7 +1796,7 @@ const generateDocs = (entryFiles: string[], apiConfigFile: string, dry = false)
throw new Error(`Groups found in code but not in API config: ${missingGroups.join(', ')}`);
}
let indexMarkdown = `# ${headingText}\n\n`;
let indexMarkdown = `${buildFrontmatter(indexDescription ?? '')}# ${headingText}\n\n`;
// Add intro text if provided
if (introText) {
@@ -1913,6 +1915,31 @@ const getFullJSDocDescription = (node: ts.Node): string => {
return extractJsDocDescription(node, { tagHandling: 'stopAtFirst' });
};
// Convert a markdown description (possibly multi-paragraph, with **bold**, `code`,
// and [text](link) from processed @link tags) into a single-line plain-text string
// suitable for the `description` field in YAML frontmatter.
const descriptionToFrontmatter = (description: string): string => {
return description
.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
.replace(/\*\*([^*]+)\*\*/g, '$1')
.replace(/__([^_]+)__/g, '$1')
.replace(/`([^`]+)`/g, '$1')
.replace(/\s+/g, ' ')
.trim();
};
const buildFrontmatter = (description: string): string => {
if (!description) {
return '';
}
const cleaned = descriptionToFrontmatter(description);
if (!cleaned) {
return '';
}
const yamlValue = `"${cleaned.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
return `---\ndescription: ${yamlValue}\n---\n\n`;
};
const main = () => {
const args = process.argv.slice(2);