@remotion/webcodecs 4.0.287 → 4.0.288
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/audio-data/data-types.d.ts +1 -0
- package/dist/audio-data/data-types.js +26 -0
- package/dist/audio-data/is-planar-format.d.ts +1 -0
- package/dist/audio-data/is-planar-format.js +7 -0
- package/dist/audio-encoder.js +5 -1
- package/dist/can-reencode-audio-track.d.ts +2 -1
- package/dist/can-reencode-audio-track.js +2 -2
- package/dist/convert-audiodata.d.ts +10 -0
- package/dist/convert-audiodata.js +85 -0
- package/dist/create/iso-base-media/codec-specific/create-codec-specific-data.js +8 -0
- package/dist/create/iso-base-media/create-iso-base-media.js +2 -0
- package/dist/create/iso-base-media/example-stts.js +620 -0
- package/dist/create/matroska/create-matroska-media.js +1 -1
- package/dist/create/matroska/matroska-utils.d.ts +1 -1
- package/dist/default-on-audio-track-handler.js +2 -0
- package/dist/esm/index.mjs +176 -15
- package/dist/get-wave-audio-decoder.js +29 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -1
- package/dist/on-audio-track-handler.d.ts +1 -0
- package/dist/on-audio-track.js +3 -3
- package/dist/resample-audiodata.d.ts +4 -0
- package/dist/resample-audiodata.js +35 -0
- package/dist/wav-audio-encoder.d.ts +1 -1
- package/dist/wav-audio-encoder.js +11 -4
- package/package.json +12 -7
- package/dist/test/avc1.test.d.ts +0 -1
- package/dist/test/avc1.test.js +0 -39
- package/dist/test/avcc.test.d.ts +0 -1
- package/dist/test/avcc.test.js +0 -15
- package/dist/test/avi-to-mp4.test.d.ts +0 -1
- package/dist/test/avi-to-mp4.test.js +0 -15
- package/dist/test/cmt.test.d.ts +0 -1
- package/dist/test/cmt.test.js +0 -13
- package/dist/test/colr.test.d.ts +0 -1
- package/dist/test/colr.test.js +0 -16
- package/dist/test/correct-byte-length.test.d.ts +0 -1
- package/dist/test/correct-byte-length.test.js +0 -23
- package/dist/test/create-ftyp.test.d.ts +0 -1
- package/dist/test/create-ftyp.test.js +0 -47
- package/dist/test/create-mvhd.test.d.ts +0 -1
- package/dist/test/create-mvhd.test.js +0 -108
- package/dist/test/ctts.test.d.ts +0 -1
- package/dist/test/ctts.test.js +0 -49
- package/dist/test/dinf.test.d.ts +0 -1
- package/dist/test/dinf.test.js +0 -12
- package/dist/test/ilst.test.d.ts +0 -1
- package/dist/test/ilst.test.js +0 -22
- package/dist/test/mdhd.test.d.ts +0 -1
- package/dist/test/mdhd.test.js +0 -17
- package/dist/test/meta.test.d.ts +0 -1
- package/dist/test/meta.test.js +0 -26
- package/dist/test/mp4-header-length.test.d.ts +0 -1
- package/dist/test/mp4-header-length.test.js +0 -12
- package/dist/test/mp4a.test.d.ts +0 -1
- package/dist/test/mp4a.test.js +0 -24
- package/dist/test/pasp.test.d.ts +0 -1
- package/dist/test/pasp.test.js +0 -12
- package/dist/test/remux-serverside.test.d.ts +0 -1
- package/dist/test/remux-serverside.test.js +0 -23
- package/dist/test/stbl.test.d.ts +0 -0
- package/dist/test/stbl.test.js +0 -176
- package/dist/test/stco.test.d.ts +0 -1
- package/dist/test/stco.test.js +0 -34
- package/dist/test/stsc.test.d.ts +0 -1
- package/dist/test/stsc.test.js +0 -63
- package/dist/test/stss.test.d.ts +0 -1
- package/dist/test/stss.test.js +0 -14
- package/dist/test/stsz.test.d.ts +0 -1
- package/dist/test/stsz.test.js +0 -43
- package/dist/test/stts.test.d.ts +0 -1
- package/dist/test/stts.test.js +0 -12
- package/dist/test/tkhd.test.d.ts +0 -1
- package/dist/test/tkhd.test.js +0 -175
- package/dist/test/too.test.d.ts +0 -1
- package/dist/test/too.test.js +0 -12
- package/dist/test/url.test.d.ts +0 -1
- package/dist/test/url.test.js +0 -11
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const getDataTypeForAudioFormat: (format: AudioSampleFormat) => Uint8ArrayConstructor | Float32ArrayConstructor | Int16ArrayConstructor | Int32ArrayConstructor;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getDataTypeForAudioFormat = void 0;
|
|
4
|
+
const getDataTypeForAudioFormat = (format) => {
|
|
5
|
+
switch (format) {
|
|
6
|
+
case 'f32':
|
|
7
|
+
return Float32Array;
|
|
8
|
+
case 'f32-planar':
|
|
9
|
+
return Float32Array;
|
|
10
|
+
case 's16':
|
|
11
|
+
return Int16Array;
|
|
12
|
+
case 's16-planar':
|
|
13
|
+
return Int16Array;
|
|
14
|
+
case 'u8':
|
|
15
|
+
return Uint8Array;
|
|
16
|
+
case 'u8-planar':
|
|
17
|
+
return Uint8Array;
|
|
18
|
+
case 's32':
|
|
19
|
+
return Int32Array;
|
|
20
|
+
case 's32-planar':
|
|
21
|
+
return Int32Array;
|
|
22
|
+
default:
|
|
23
|
+
throw new Error(`Unsupported audio format: ${format}`);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
exports.getDataTypeForAudioFormat = getDataTypeForAudioFormat;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const isPlanarFormat: (format: AudioSampleFormat) => boolean;
|
package/dist/audio-encoder.js
CHANGED
|
@@ -9,7 +9,11 @@ const createAudioEncoder = ({ onChunk, onError, codec, controller, config: audio
|
|
|
9
9
|
throw new media_parser_1.MediaParserAbortError('Not creating audio encoder, already aborted');
|
|
10
10
|
}
|
|
11
11
|
if (codec === 'wav') {
|
|
12
|
-
return (0, wav_audio_encoder_1.getWaveAudioEncoder)({
|
|
12
|
+
return (0, wav_audio_encoder_1.getWaveAudioEncoder)({
|
|
13
|
+
onChunk,
|
|
14
|
+
controller,
|
|
15
|
+
config: audioEncoderConfig,
|
|
16
|
+
});
|
|
13
17
|
}
|
|
14
18
|
const ioSynchronizer = (0, io_synchronizer_1.makeIoSynchronizer)({
|
|
15
19
|
logLevel,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { AudioTrack } from '@remotion/media-parser';
|
|
2
2
|
import type { ConvertMediaAudioCodec } from './get-available-audio-codecs';
|
|
3
|
-
export declare const canReencodeAudioTrack: ({ track, audioCodec, bitrate, }: {
|
|
3
|
+
export declare const canReencodeAudioTrack: ({ track, audioCodec, bitrate, sampleRate, }: {
|
|
4
4
|
track: AudioTrack;
|
|
5
5
|
audioCodec: ConvertMediaAudioCodec;
|
|
6
6
|
bitrate: number;
|
|
7
|
+
sampleRate: number | null;
|
|
7
8
|
}) => Promise<boolean>;
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.canReencodeAudioTrack = void 0;
|
|
4
4
|
const audio_decoder_config_1 = require("./audio-decoder-config");
|
|
5
5
|
const audio_encoder_config_1 = require("./audio-encoder-config");
|
|
6
|
-
const canReencodeAudioTrack = async ({ track, audioCodec, bitrate, }) => {
|
|
6
|
+
const canReencodeAudioTrack = async ({ track, audioCodec, bitrate, sampleRate, }) => {
|
|
7
7
|
const audioDecoderConfig = await (0, audio_decoder_config_1.getAudioDecoderConfig)(track);
|
|
8
8
|
if (audioCodec === 'wav' && audioDecoderConfig) {
|
|
9
9
|
return true;
|
|
@@ -11,7 +11,7 @@ const canReencodeAudioTrack = async ({ track, audioCodec, bitrate, }) => {
|
|
|
11
11
|
const audioEncoderConfig = await (0, audio_encoder_config_1.getAudioEncoderConfig)({
|
|
12
12
|
codec: audioCodec,
|
|
13
13
|
numberOfChannels: track.numberOfChannels,
|
|
14
|
-
sampleRate: track.sampleRate,
|
|
14
|
+
sampleRate: sampleRate ?? track.sampleRate,
|
|
15
15
|
bitrate,
|
|
16
16
|
});
|
|
17
17
|
return Boolean(audioDecoderConfig && audioEncoderConfig);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type ConvertAudioDataOptions = {
|
|
2
|
+
audioData: AudioData;
|
|
3
|
+
newSampleRate?: number;
|
|
4
|
+
format?: AudioSampleFormat | null;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Converts an `AudioData` object to a new `AudioData` object with a different sample rate or format.
|
|
8
|
+
* @see [Documentation](https://remotion.dev/docs/webcodecs/convert-audiodata)
|
|
9
|
+
*/
|
|
10
|
+
export declare const convertAudioData: ({ audioData, newSampleRate, format, }: ConvertAudioDataOptions) => AudioData;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.convertAudioData = void 0;
|
|
4
|
+
const data_types_1 = require("./audio-data/data-types");
|
|
5
|
+
const is_planar_format_1 = require("./audio-data/is-planar-format");
|
|
6
|
+
const validateRange = (format, value) => {
|
|
7
|
+
if (format === 'f32' || format === 'f32-planar') {
|
|
8
|
+
if (value < -1 || value > 1) {
|
|
9
|
+
throw new Error('All values in a Float32 array must be between -1 and 1');
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Converts an `AudioData` object to a new `AudioData` object with a different sample rate or format.
|
|
15
|
+
* @see [Documentation](https://remotion.dev/docs/webcodecs/convert-audiodata)
|
|
16
|
+
*/
|
|
17
|
+
const convertAudioData = ({ audioData, newSampleRate = audioData.sampleRate, format = audioData.format, }) => {
|
|
18
|
+
const { numberOfChannels, sampleRate: currentSampleRate, numberOfFrames: currentNumberOfFrames, } = audioData;
|
|
19
|
+
const ratio = currentSampleRate / newSampleRate;
|
|
20
|
+
const newNumberOfFrames = Math.floor(currentNumberOfFrames / ratio);
|
|
21
|
+
if (newNumberOfFrames === 0) {
|
|
22
|
+
throw new Error('Cannot resample - the given sample rate would result in less than 1 sample');
|
|
23
|
+
}
|
|
24
|
+
if (newSampleRate < 3000 || newSampleRate > 768000) {
|
|
25
|
+
throw new Error('newSampleRate must be between 3000 and 768000');
|
|
26
|
+
}
|
|
27
|
+
if (!format) {
|
|
28
|
+
throw new Error('AudioData format is not set');
|
|
29
|
+
}
|
|
30
|
+
if (format === audioData.format &&
|
|
31
|
+
newNumberOfFrames === currentNumberOfFrames) {
|
|
32
|
+
return audioData.clone();
|
|
33
|
+
}
|
|
34
|
+
const DataType = (0, data_types_1.getDataTypeForAudioFormat)(format);
|
|
35
|
+
const isPlanar = (0, is_planar_format_1.isPlanarFormat)(format);
|
|
36
|
+
const planes = isPlanar ? numberOfChannels : 1;
|
|
37
|
+
const srcChannels = new Array(planes)
|
|
38
|
+
.fill(true)
|
|
39
|
+
.map(() => new DataType((isPlanar ? 1 : numberOfChannels) * currentNumberOfFrames));
|
|
40
|
+
for (let i = 0; i < planes; i++) {
|
|
41
|
+
audioData.clone().copyTo(srcChannels[i], {
|
|
42
|
+
planeIndex: i,
|
|
43
|
+
format,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
const data = new DataType(newNumberOfFrames * numberOfChannels);
|
|
47
|
+
const chunkSize = currentNumberOfFrames / newNumberOfFrames;
|
|
48
|
+
for (let newFrameIndex = 0; newFrameIndex < newNumberOfFrames; newFrameIndex++) {
|
|
49
|
+
const start = Math.floor(newFrameIndex * chunkSize);
|
|
50
|
+
const end = Math.max(Math.floor(start + chunkSize), start + 1);
|
|
51
|
+
if (isPlanar) {
|
|
52
|
+
for (let channelIndex = 0; channelIndex < numberOfChannels; channelIndex++) {
|
|
53
|
+
const chunk = srcChannels[channelIndex].slice(start, end);
|
|
54
|
+
const average = chunk.reduce((a, b) => {
|
|
55
|
+
return a + b;
|
|
56
|
+
}, 0) / chunk.length;
|
|
57
|
+
validateRange(format, average);
|
|
58
|
+
data[newFrameIndex + channelIndex * newNumberOfFrames] = average;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
const sampleCountAvg = end - start;
|
|
63
|
+
for (let channelIndex = 0; channelIndex < numberOfChannels; channelIndex++) {
|
|
64
|
+
const items = [];
|
|
65
|
+
for (let k = 0; k < sampleCountAvg; k++) {
|
|
66
|
+
const num = srcChannels[0][(start + k) * numberOfChannels + channelIndex];
|
|
67
|
+
items.push(num);
|
|
68
|
+
}
|
|
69
|
+
const average = items.reduce((a, b) => a + b, 0) / items.length;
|
|
70
|
+
validateRange(format, average);
|
|
71
|
+
data[newFrameIndex * numberOfChannels + channelIndex] = average;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const newAudioData = new AudioData({
|
|
76
|
+
data,
|
|
77
|
+
format,
|
|
78
|
+
numberOfChannels,
|
|
79
|
+
numberOfFrames: newNumberOfFrames,
|
|
80
|
+
sampleRate: newSampleRate,
|
|
81
|
+
timestamp: audioData.timestamp,
|
|
82
|
+
});
|
|
83
|
+
return newAudioData;
|
|
84
|
+
};
|
|
85
|
+
exports.convertAudioData = convertAudioData;
|
|
@@ -10,6 +10,10 @@ const mp4a_1 = require("./mp4a");
|
|
|
10
10
|
const createCodecSpecificData = (track) => {
|
|
11
11
|
if (track.type === 'video') {
|
|
12
12
|
if (track.codec === 'h264') {
|
|
13
|
+
// May not have it initially
|
|
14
|
+
if (!track.codecPrivate) {
|
|
15
|
+
return new Uint8Array([]);
|
|
16
|
+
}
|
|
13
17
|
return (0, avc1_1.createAvc1Data)({
|
|
14
18
|
avccBox: (0, create_avcc_1.createAvccBox)(track.codecPrivate),
|
|
15
19
|
compressorName: 'WebCodecs',
|
|
@@ -23,6 +27,10 @@ const createCodecSpecificData = (track) => {
|
|
|
23
27
|
});
|
|
24
28
|
}
|
|
25
29
|
if (track.codec === 'h265') {
|
|
30
|
+
// May not have it initially
|
|
31
|
+
if (!track.codecPrivate) {
|
|
32
|
+
return new Uint8Array([]);
|
|
33
|
+
}
|
|
26
34
|
return (0, hvc1_1.createHvc1Data)({
|
|
27
35
|
hvccBox: (0, create_hvcc_1.createHvccBox)(track.codecPrivate),
|
|
28
36
|
compressorName: 'WebCodecs',
|
|
@@ -127,6 +127,8 @@ const createIsoBaseMedia = async ({ writer, onBytesProgress, onMillisecondsProgr
|
|
|
127
127
|
dts: Math.round((chunk.dts / 1000000) * currentTrack.timescale),
|
|
128
128
|
duration: Math.round(((chunk.duration ?? 0) / 1000000) * currentTrack.timescale),
|
|
129
129
|
size: chunk.data.length,
|
|
130
|
+
bigEndian: false,
|
|
131
|
+
chunkSize: null,
|
|
130
132
|
};
|
|
131
133
|
lastChunkWasVideo = isVideo;
|
|
132
134
|
samplePositions[trackNumber].push(samplePositionToAdd);
|