mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-10-09 16:53:47 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b382d3e57 | ||
|
|
f78fc697cd | ||
|
|
39df195ada | ||
|
|
326e03cfc9 | ||
|
|
23aef27154 | ||
|
|
9daab77bb5 | ||
|
|
5a6e3eebda | ||
|
|
c4fb325329 | ||
|
|
1071bf9d49 | ||
|
|
a8fa2e4cec | ||
|
|
12f14b1f66 | ||
|
|
d4d93a7007 | ||
|
|
f44cb26d76 |
@@ -1 +0,0 @@
|
|||||||
build/* linguist-generated
|
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
<img src="./docs/public/mediabunny-logo.svg" height="180">
|
<img src="./docs/public/mediabunny-logo.svg" height="180">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
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, 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.
|
||||||
|
|
||||||
[Documentation](https://mediabunny.dev) | [Examples](https://mediabunny.dev/examples) | [Sponsoring](#sponsoring) | [License](#license) | [Discord](https://discord.gg/hmpkyYuS4U)
|
[Documentation](https://mediabunny.dev) | [Examples](https://mediabunny.dev/examples) | [Sponsoring](#sponsoring) | [License](#license) | [Discord](https://discord.gg/hmpkyYuS4U)
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -21,7 +21,7 @@
|
|||||||
chunked: true,
|
chunked: true,
|
||||||
chunkSize: 2**20
|
chunkSize: 2**20
|
||||||
});
|
});
|
||||||
const outputFormat = new Mediabunny.MovOutputFormat();
|
const outputFormat = new Mediabunny.Mp4OutputFormat();
|
||||||
|
|
||||||
const button = document.createElement('button');
|
const button = document.createElement('button');
|
||||||
button.textContent = 'Cancel';
|
button.textContent = 'Cancel';
|
||||||
@@ -38,7 +38,8 @@
|
|||||||
target
|
target
|
||||||
}),
|
}),
|
||||||
audio: {
|
audio: {
|
||||||
codec: 'pcm-f64'
|
codec: 'opus',
|
||||||
|
bitrate: 128000,
|
||||||
//numberOfChannels: 1,
|
//numberOfChannels: 1,
|
||||||
//sampleRate: 4000
|
//sampleRate: 4000
|
||||||
//discard: true
|
//discard: true
|
||||||
|
|||||||
@@ -11,11 +11,14 @@ export default withMermaid({
|
|||||||
+ ' faster than anybunny else.',
|
+ ' faster than anybunny else.',
|
||||||
cleanUrls: true,
|
cleanUrls: true,
|
||||||
head: [
|
head: [
|
||||||
['link', { rel: 'icon', type: 'image/svg+xml', href: '/mediabunny-logo.svg' }],
|
|
||||||
['link', { rel: 'icon', type: 'image/png', href: '/mediabunny-logo.png' }],
|
['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:type', content: 'website' }],
|
||||||
['meta', { property: 'og:site_name', content: 'Mediabunny' }],
|
['meta', { property: 'og:site_name', content: 'Mediabunny' }],
|
||||||
|
['meta', { property: 'og:url', content: 'https://mediabunny.dev/' }],
|
||||||
['meta', { property: 'og:image', content: '/mediabunny-og-image.png' }],
|
['meta', { property: 'og:image', content: '/mediabunny-og-image.png' }],
|
||||||
|
['meta', { property: 'og:locale', content: 'en-US' }],
|
||||||
|
['meta', { name: 'twitter:card', content: 'summary_large_image' }],
|
||||||
],
|
],
|
||||||
themeConfig: {
|
themeConfig: {
|
||||||
logo: '/mediabunny-logo.svg',
|
logo: '/mediabunny-logo.svg',
|
||||||
|
|||||||
+1
-1
@@ -37,7 +37,7 @@ features:
|
|||||||
target: _self
|
target: _self
|
||||||
icon:
|
icon:
|
||||||
src: /mingcute--magic-3-line.svg
|
src: /mingcute--magic-3-line.svg
|
||||||
- title: Live recording
|
- title: Live recording & streaming
|
||||||
details: Record a video from live sources and stream it to a video element.
|
details: Record a video from live sources and stream it to a video element.
|
||||||
link: /examples/live-recording
|
link: /examples/live-recording
|
||||||
target: _self
|
target: _self
|
||||||
|
|||||||
@@ -66,6 +66,13 @@ This library is the result of unifying these libraries into one, solving all the
|
|||||||
|
|
||||||
Due to tree shaking, if you only need an MP4 or WebM muxer, this library's bundle size will still be very small.
|
Due to tree shaking, if you only need an MP4 or WebM muxer, this library's bundle size will still be very small.
|
||||||
|
|
||||||
|
### Migration
|
||||||
|
|
||||||
|
If you're coming from mp4-muxer or webm-muxer, you should migrate to Mediabunny. For that, refer to these guides:
|
||||||
|
|
||||||
|
- [Guide: Migrating from mp4-muxer to Mediabunny](https://github.com/Vanilagy/mp4-muxer/blob/main/MIGRATION-GUIDE.md)
|
||||||
|
- [Guide: Migrating from webm-muxer to Mediabunny](https://github.com/Vanilagy/webm-muxer/blob/main/MIGRATION-GUIDE.md)
|
||||||
|
|
||||||
## Technical overview
|
## Technical overview
|
||||||
|
|
||||||
At its core, Mediabunny is a collection of multiplexers and demultiplexers, one of each for every container format. Demultiplexers stream data from *sources*, while multiplexers stream data to *targets*. Every demultiplexer is capable of extracting file metadata as well as compressed media data, while multiplexers write metadata and encoded media data into a new file.
|
At its core, Mediabunny is a collection of multiplexers and demultiplexers, one of each for every container format. Demultiplexers stream data from *sources*, while multiplexers stream data to *targets*. Every demultiplexer is capable of extracting file metadata as well as compressed media data, while multiplexers write metadata and encoded media data into a new file.
|
||||||
|
|||||||
+5
-4
@@ -6,7 +6,7 @@ title: Mediabunny
|
|||||||
hero:
|
hero:
|
||||||
name: Mediabunny
|
name: Mediabunny
|
||||||
text: Complete media toolkit
|
text: Complete media toolkit
|
||||||
tagline: A JavaScript library for reading, writing, and converting media files. Directly in the browser, and faster than anybunny else.
|
tagline: A JavaScript library for reading, writing, and converting video and audio files. Directly in the browser, and faster than anybunny else.
|
||||||
image:
|
image:
|
||||||
src: /mediabunny-logo.svg
|
src: /mediabunny-logo.svg
|
||||||
alt: Mediabunny logo
|
alt: Mediabunny logo
|
||||||
@@ -92,6 +92,7 @@ const sponsors = {
|
|||||||
{ image: '/sponsors/diffusionstudio.png', name: 'Diffusion Studio', url: 'https://diffusion.studio/' },
|
{ image: '/sponsors/diffusionstudio.png', name: 'Diffusion Studio', url: 'https://diffusion.studio/' },
|
||||||
],
|
],
|
||||||
individual: [
|
individual: [
|
||||||
|
{ image: 'https://avatars.githubusercontent.com/u/84167135', name: 'Memenome', url: 'https://github.com/memenome' },
|
||||||
{ image: 'https://avatars.githubusercontent.com/u/30229596', name: 'Pablo Bonilla', url: 'https://github.com/devPablo' },
|
{ image: 'https://avatars.githubusercontent.com/u/30229596', name: 'Pablo Bonilla', url: 'https://github.com/devPablo' },
|
||||||
{ image: 'https://avatars.githubusercontent.com/u/58149663', name: 'H7GhosT', url: 'https://github.com/H7GhosT' },
|
{ image: 'https://avatars.githubusercontent.com/u/58149663', name: 'H7GhosT', url: 'https://github.com/H7GhosT' },
|
||||||
],
|
],
|
||||||
@@ -123,7 +124,7 @@ npm install mediabunny
|
|||||||
<div class="flex flex-col lg:flex-row lg:gap-20 lg:items-center">
|
<div class="flex flex-col lg:flex-row lg:gap-20 lg:items-center">
|
||||||
<div class="flex-1 min-w-0">
|
<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>
|
<h1 class="inline-block" style="background: -webkit-linear-gradient(-30deg, #ff45ac, #ff78c2); -webkit-background-clip: text; color: transparent;">Read any media file, efficiently</h1>
|
||||||
<p class="text-lg">Mediabunny allows you efficiently read data from any media 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>
|
<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">
|
<a class="!no-underline inline-flex items-center gap-1.5" :no-icon="true" href="/guide/reading-media-files">
|
||||||
Docs
|
Docs
|
||||||
<span class="vpi-arrow-right" />
|
<span class="vpi-arrow-right" />
|
||||||
@@ -323,7 +324,7 @@ await conversion.execute();
|
|||||||
<template v-if="sponsors.gold.length > 0">
|
<template v-if="sponsors.gold.length > 0">
|
||||||
<h3 class="!text-2xl">Gold sponsors</h3>
|
<h3 class="!text-2xl">Gold sponsors</h3>
|
||||||
<div class="flex flex-wrap mt-1 justify-center gap-1">
|
<div class="flex flex-wrap mt-1 justify-center gap-1">
|
||||||
<a v-for="sponsor in sponsors.gold" :href="sponsor.url" target="_blank" class="flex items-center p-2 rounded-full hover:bg-(--vp-c-gray-3) !text-[initial] !no-underline">
|
<a v-for="sponsor in sponsors.gold" :href="sponsor.url" target="_blank" class="flex items-center p-2 rounded-full hover:bg-(--vp-c-gray-3) !text-(--vp-c-text-1) !no-underline">
|
||||||
<img :src="sponsor.image" class="size-16 rounded-full">
|
<img :src="sponsor.image" class="size-16 rounded-full">
|
||||||
<p class="!my-0 !font-medium px-3">{{ sponsor.name }}</p>
|
<p class="!my-0 !font-medium px-3">{{ sponsor.name }}</p>
|
||||||
</a>
|
</a>
|
||||||
@@ -332,7 +333,7 @@ await conversion.execute();
|
|||||||
<template v-if="sponsors.individual.length > 0">
|
<template v-if="sponsors.individual.length > 0">
|
||||||
<h4>Individual sponsors</h4>
|
<h4>Individual sponsors</h4>
|
||||||
<div class="flex flex-wrap mt-1 justify-center">
|
<div class="flex flex-wrap mt-1 justify-center">
|
||||||
<a v-for="sponsor in sponsors.individual" :href="sponsor.url" target="_blank" class="flex gap-1 w-24 flex-col items-center p-2 rounded-xl hover:bg-(--vp-c-gray-3) !text-[initial] !no-underline">
|
<a v-for="sponsor in sponsors.individual" :href="sponsor.url" target="_blank" class="flex gap-1 w-24 flex-col items-center p-2 rounded-xl hover:bg-(--vp-c-gray-3) !text-(--vp-c-text-1) !no-underline">
|
||||||
<img :src="sponsor.image" class="size-8 rounded-full">
|
<img :src="sponsor.image" class="size-8 rounded-full">
|
||||||
<p class="!my-0 !font-medium text-xs !leading-4">{{ sponsor.name }}</p>
|
<p class="!my-0 !font-medium text-xs !leading-4">{{ sponsor.name }}</p>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ const compressFile = async (file: File) => {
|
|||||||
selectMediaButton.addEventListener('click', () => {
|
selectMediaButton.addEventListener('click', () => {
|
||||||
const fileInput = document.createElement('input');
|
const fileInput = document.createElement('input');
|
||||||
fileInput.type = 'file';
|
fileInput.type = 'file';
|
||||||
|
fileInput.accept = 'video/*,video/x-matroska,audio/*';
|
||||||
fileInput.addEventListener('change', () => {
|
fileInput.addEventListener('change', () => {
|
||||||
const file = fileInput.files?.[0];
|
const file = fileInput.files?.[0];
|
||||||
if (!file) {
|
if (!file) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Live recording example | Mediabunny</title>
|
<title>Live recording & streaming example | Mediabunny</title>
|
||||||
<script type="module" src="../base.ts"></script>
|
<script type="module" src="../base.ts"></script>
|
||||||
<script type="module" src="./live-recording.ts"></script>
|
<script type="module" src="./live-recording.ts"></script>
|
||||||
<link rel="stylesheet" href="../base.css">
|
<link rel="stylesheet" href="../base.css">
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
</head>
|
</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">
|
<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">
|
||||||
<h1 class="text-3xl font-bold text-orange-500 text-center">Live recording example</h1>
|
<h1 class="text-3xl font-bold text-orange-500 text-center">Live recording & streaming example</h1>
|
||||||
<p class="max-w-lg text-center">The live canvas state and your microphone input will be written into a fragmented MP4 file and live-streamed to a <code><video></code> element.</p>
|
<p class="max-w-lg text-center">The live canvas state and your microphone input will be written into a fragmented MP4 file and live-streamed to a <code><video></code> element.</p>
|
||||||
|
|
||||||
<button id="toggle-button" class="rounded-lg bg-zinc-200 dark:bg-zinc-750 hover:bg-zinc-300 dark:hover:bg-zinc-700 px-5 py-2 mt-4">
|
<button id="toggle-button" class="rounded-lg bg-zinc-200 dark:bg-zinc-750 hover:bg-zinc-300 dark:hover:bg-zinc-700 px-5 py-2 mt-4">
|
||||||
|
|||||||
@@ -544,6 +544,7 @@ const formatSeconds = (seconds: number) => {
|
|||||||
selectMediaButton.addEventListener('click', () => {
|
selectMediaButton.addEventListener('click', () => {
|
||||||
const fileInput = document.createElement('input');
|
const fileInput = document.createElement('input');
|
||||||
fileInput.type = 'file';
|
fileInput.type = 'file';
|
||||||
|
fileInput.accept = 'video/*,video/x-matroska,audio/*';
|
||||||
fileInput.addEventListener('change', () => {
|
fileInput.addEventListener('change', () => {
|
||||||
const file = fileInput.files?.[0];
|
const file = fileInput.files?.[0];
|
||||||
if (!file) {
|
if (!file) {
|
||||||
|
|||||||
@@ -155,6 +155,7 @@ const shortDelay = () => {
|
|||||||
selectMediaButton.addEventListener('click', () => {
|
selectMediaButton.addEventListener('click', () => {
|
||||||
const fileInput = document.createElement('input');
|
const fileInput = document.createElement('input');
|
||||||
fileInput.type = 'file';
|
fileInput.type = 'file';
|
||||||
|
fileInput.accept = 'video/*,video/x-matroska,audio/*';
|
||||||
fileInput.addEventListener('change', () => {
|
fileInput.addEventListener('change', () => {
|
||||||
const file = fileInput.files?.[0];
|
const file = fileInput.files?.[0];
|
||||||
if (!file) {
|
if (!file) {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
<p id="error-element" class="text-red-500"></p>
|
<p id="error-element" class="text-red-500"></p>
|
||||||
|
|
||||||
<div class="w-full max-w-80 h-2 rounded-full bg-zinc-200 dark:bg-zinc-750 overflow-hidden" id="progress-bar-container" style="display: none;">
|
<div class="w-full max-w-80 h-2 rounded-full bg-zinc-200 dark:bg-zinc-750 overflow-hidden" id="progress-bar-container" style="display: none;">
|
||||||
<div class="h-full bg-teal-500 w-0" id="progress-bar"></div>
|
<div class="h-full bg-pink-500 w-0" id="progress-bar"></div>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-xs font-medium mt-1.5 tabular-nums" id="progress-text" style="display: none;"></p>
|
<p class="text-xs font-medium mt-1.5 tabular-nums" id="progress-text" style="display: none;"></p>
|
||||||
|
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ const generateThumbnails = async (file: File) => {
|
|||||||
selectMediaButton.addEventListener('click', () => {
|
selectMediaButton.addEventListener('click', () => {
|
||||||
const fileInput = document.createElement('input');
|
const fileInput = document.createElement('input');
|
||||||
fileInput.type = 'file';
|
fileInput.type = 'file';
|
||||||
|
fileInput.accept = 'video/*,video/x-matroska,audio/*';
|
||||||
fileInput.addEventListener('change', () => {
|
fileInput.addEventListener('change', () => {
|
||||||
const file = fileInput.files?.[0];
|
const file = fileInput.files?.[0];
|
||||||
if (!file) {
|
if (!file) {
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "mediabunny",
|
"name": "mediabunny",
|
||||||
"version": "0.1.0",
|
"version": "1.0.2",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "mediabunny",
|
"name": "mediabunny",
|
||||||
"version": "0.1.0",
|
"version": "1.0.2",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/dom-mediacapture-transform": "^0.1.11",
|
"@types/dom-mediacapture-transform": "^0.1.11",
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "mediabunny",
|
"name": "mediabunny",
|
||||||
"author": "Vanilagy",
|
"author": "Vanilagy",
|
||||||
"version": "1.0.0",
|
"version": "1.0.2",
|
||||||
"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/mediabunny.js",
|
||||||
|
|||||||
+6
-4
@@ -416,8 +416,9 @@ class VideoEncoderWrapper {
|
|||||||
const support = await VideoEncoder.isConfigSupported(encoderConfig);
|
const support = await VideoEncoder.isConfigSupported(encoderConfig);
|
||||||
if (!support.supported) {
|
if (!support.supported) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'This specific encoder configuration is not supported by this browser. Consider using another'
|
`This specific encoder configuration (${encoderConfig.codec}, ${encoderConfig.bitrate} bps,`
|
||||||
+ ' codec or changing your video parameters.',
|
+ ` ${encoderConfig.width}x${encoderConfig.height}) is not supported by this browser. Consider`
|
||||||
|
+ ` using another codec or changing your video parameters.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -988,8 +989,9 @@ class AudioEncoderWrapper {
|
|||||||
const support = await AudioEncoder.isConfigSupported(encoderConfig);
|
const support = await AudioEncoder.isConfigSupported(encoderConfig);
|
||||||
if (!support.supported) {
|
if (!support.supported) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'This specific encoder configuration not supported by this browser. Consider using another'
|
`This specific encoder configuration (${encoderConfig.codec}, ${encoderConfig.bitrate} bps,`
|
||||||
+ ' codec or changing your audio parameters.',
|
+ ` ${encoderConfig.numberOfChannels} channels, ${encoderConfig.sampleRate} Hz) is not`
|
||||||
|
+ ` supported by this browser. Consider using another codec or changing your audio parameters.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-4
@@ -134,7 +134,9 @@ export const writeBits = (bytes: Uint8Array, start: number, end: number, value:
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const toUint8Array = (source: AllowSharedBufferSource): Uint8Array => {
|
export const toUint8Array = (source: AllowSharedBufferSource): Uint8Array => {
|
||||||
if (source instanceof ArrayBuffer) {
|
if (source instanceof Uint8Array) {
|
||||||
|
return source;
|
||||||
|
} else if (source instanceof ArrayBuffer) {
|
||||||
return new Uint8Array(source);
|
return new Uint8Array(source);
|
||||||
} else {
|
} else {
|
||||||
return new Uint8Array(source.buffer, source.byteOffset, source.byteLength);
|
return new Uint8Array(source.buffer, source.byteOffset, source.byteLength);
|
||||||
@@ -142,7 +144,9 @@ export const toUint8Array = (source: AllowSharedBufferSource): Uint8Array => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const toDataView = (source: AllowSharedBufferSource) => {
|
export const toDataView = (source: AllowSharedBufferSource) => {
|
||||||
if (source instanceof ArrayBuffer) {
|
if (source instanceof DataView) {
|
||||||
|
return source;
|
||||||
|
} else if (source instanceof ArrayBuffer) {
|
||||||
return new DataView(source);
|
return new DataView(source);
|
||||||
} else {
|
} else {
|
||||||
return new DataView(source.buffer, source.byteOffset, source.byteLength);
|
return new DataView(source.buffer, source.byteOffset, source.byteLength);
|
||||||
@@ -202,11 +206,10 @@ export const colorSpaceIsComplete = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const isAllowSharedBufferSource = (x: unknown) => {
|
export const isAllowSharedBufferSource = (x: unknown) => {
|
||||||
// Quite a mouthful:
|
|
||||||
return (
|
return (
|
||||||
x instanceof ArrayBuffer
|
x instanceof ArrayBuffer
|
||||||
|| (typeof SharedArrayBuffer !== 'undefined' && x instanceof SharedArrayBuffer)
|
|| (typeof SharedArrayBuffer !== 'undefined' && x instanceof SharedArrayBuffer)
|
||||||
|| (ArrayBuffer.isView(x) && !(x instanceof DataView))
|
|| ArrayBuffer.isView(x)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+1
-5
@@ -890,7 +890,6 @@ export class AudioSample {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new AudioData({
|
return new AudioData({
|
||||||
|
|
||||||
format: this.format,
|
format: this.format,
|
||||||
sampleRate: this.sampleRate,
|
sampleRate: this.sampleRate,
|
||||||
numberOfFrames: this.numberOfFrames,
|
numberOfFrames: this.numberOfFrames,
|
||||||
@@ -900,11 +899,9 @@ export class AudioSample {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const data = new ArrayBuffer(this.allocationSize({ planeIndex: 0, format: this.format }));
|
const data = new ArrayBuffer(this.allocationSize({ planeIndex: 0, format: this.format }));
|
||||||
|
this.copyTo(data, { planeIndex: 0, format: this.format });
|
||||||
this.copyTo(new DataView(data), { planeIndex: 0, format: this.format });
|
|
||||||
|
|
||||||
return new AudioData({
|
return new AudioData({
|
||||||
|
|
||||||
format: this.format,
|
format: this.format,
|
||||||
sampleRate: this.sampleRate,
|
sampleRate: this.sampleRate,
|
||||||
numberOfFrames: this.numberOfFrames,
|
numberOfFrames: this.numberOfFrames,
|
||||||
@@ -916,7 +913,6 @@ export class AudioSample {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return new AudioData({
|
return new AudioData({
|
||||||
|
|
||||||
format: this.format,
|
format: this.format,
|
||||||
sampleRate: this.sampleRate,
|
sampleRate: this.sampleRate,
|
||||||
numberOfFrames: this.numberOfFrames,
|
numberOfFrames: this.numberOfFrames,
|
||||||
|
|||||||
Reference in New Issue
Block a user