@remotion/webcodecs 4.0.265 → 4.0.267
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-decoder.js +8 -1
- package/dist/audio-encoder-config.js +7 -0
- package/dist/convert-media.d.ts +2 -1
- package/dist/convert-media.js +3 -1
- package/dist/create/iso-base-media/mp4-header.js +1 -1
- package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stts.js +4 -1
- package/dist/esm/index.mjs +26 -8
- package/dist/index.d.ts +20 -11
- package/dist/on-audio-track.js +4 -4
- package/dist/test/remux-serverside.test.js +1 -1
- package/package.json +5 -5
package/dist/audio-decoder.js
CHANGED
|
@@ -75,7 +75,14 @@ const createAudioDecoder = ({ onFrame, onError, controller, config, logLevel, tr
|
|
|
75
75
|
// Don't flush, it messes up the audio
|
|
76
76
|
const chunk = new EncodedAudioChunk(audioSample);
|
|
77
77
|
audioDecoder.decode(chunk);
|
|
78
|
-
|
|
78
|
+
// https://test-streams.mux.dev/x36xhzz/url_0/url_525/193039199_mp4_h264_aac_hd_7.ts
|
|
79
|
+
// has a 16 byte audio sample at the end which chrome does not decode
|
|
80
|
+
// Might be empty audio
|
|
81
|
+
// For now only reporting chunks that are bigger than that
|
|
82
|
+
// 16 was chosen arbitrarily, can be improved
|
|
83
|
+
if (chunk.byteLength > 16) {
|
|
84
|
+
ioSynchronizer.inputItem(chunk.timestamp, audioSample.type === 'key');
|
|
85
|
+
}
|
|
79
86
|
};
|
|
80
87
|
let queue = Promise.resolve();
|
|
81
88
|
return {
|
|
@@ -27,6 +27,13 @@ const getAudioEncoderConfig = async (config) => {
|
|
|
27
27
|
if ((await AudioEncoder.isConfigSupported(actualConfig)).supported) {
|
|
28
28
|
return actualConfig;
|
|
29
29
|
}
|
|
30
|
+
const maybeItIsTheSampleRateThatIsTheProblem = config.sampleRate !== 48000 && config.sampleRate !== 44100;
|
|
31
|
+
if (maybeItIsTheSampleRateThatIsTheProblem) {
|
|
32
|
+
return (0, exports.getAudioEncoderConfig)({
|
|
33
|
+
...config,
|
|
34
|
+
sampleRate: config.sampleRate === 22050 ? 44100 : 48000,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
30
37
|
return null;
|
|
31
38
|
};
|
|
32
39
|
exports.getAudioEncoderConfig = getAudioEncoderConfig;
|
package/dist/convert-media.d.ts
CHANGED
|
@@ -35,7 +35,7 @@ export type ConvertMediaOnAudioData = (options: {
|
|
|
35
35
|
audioData: AudioData;
|
|
36
36
|
track: AudioTrack;
|
|
37
37
|
}) => Promise<AudioData> | AudioData;
|
|
38
|
-
export declare const convertMedia: <F extends Options<ParseMediaFields>>({ src, onVideoFrame, onAudioData, onProgress: onProgressDoNotCallDirectly, audioCodec, container, videoCodec, controller, onAudioTrack: userAudioResolver, onVideoTrack: userVideoResolver, reader, fields, logLevel, writer, progressIntervalInMs, rotate, apiKey, resize, onAudioCodec, onContainer, onDimensions, onDurationInSeconds, onFps, onImages, onInternalStats, onIsHdr, onKeyframes, onLocation, onMetadata, onMimeType, onName, onNumberOfAudioChannels, onRotation, onSampleRate, onSize, onSlowAudioBitrate, onSlowDurationInSeconds, onSlowFps, onSlowKeyframes, onSlowNumberOfFrames, onSlowVideoBitrate, onStructure, onTracks, onUnrotatedDimensions, onVideoCodec, ...more }: {
|
|
38
|
+
export declare const convertMedia: <F extends Options<ParseMediaFields>>({ src, onVideoFrame, onAudioData, onProgress: onProgressDoNotCallDirectly, audioCodec, container, videoCodec, controller, onAudioTrack: userAudioResolver, onVideoTrack: userVideoResolver, reader, fields, logLevel, writer, progressIntervalInMs, rotate, apiKey, resize, onAudioCodec, onContainer, onDimensions, onDurationInSeconds, onFps, onImages, onInternalStats, onIsHdr, onKeyframes, onLocation, onMetadata, onMimeType, onName, onNumberOfAudioChannels, onRotation, onSampleRate, onSize, onSlowAudioBitrate, onSlowDurationInSeconds, onSlowFps, onSlowKeyframes, onSlowNumberOfFrames, onSlowVideoBitrate, onStructure, onTracks, onUnrotatedDimensions, onVideoCodec, onM3uStreams, selectM3uStream, ...more }: {
|
|
39
39
|
src: ParseMediaOptions<F>["src"];
|
|
40
40
|
container: ConvertMediaContainer;
|
|
41
41
|
onVideoFrame?: ConvertMediaOnVideoFrame;
|
|
@@ -46,6 +46,7 @@ export declare const convertMedia: <F extends Options<ParseMediaFields>>({ src,
|
|
|
46
46
|
controller?: WebCodecsController;
|
|
47
47
|
onAudioTrack?: ConvertMediaOnAudioTrackHandler;
|
|
48
48
|
onVideoTrack?: ConvertMediaOnVideoTrackHandler;
|
|
49
|
+
selectM3uStream?: ParseMediaOptions<F>["selectM3uStream"];
|
|
49
50
|
reader?: ParseMediaOptions<F>["reader"];
|
|
50
51
|
logLevel?: LogLevel;
|
|
51
52
|
writer?: WriterInterface;
|
package/dist/convert-media.js
CHANGED
|
@@ -21,7 +21,7 @@ const select_container_creator_1 = require("./select-container-creator");
|
|
|
21
21
|
const send_telemetry_event_1 = require("./send-telemetry-event");
|
|
22
22
|
const throttled_state_update_1 = require("./throttled-state-update");
|
|
23
23
|
const webcodecs_controller_1 = require("./webcodecs-controller");
|
|
24
|
-
const convertMedia = async function ({ src, onVideoFrame, onAudioData, onProgress: onProgressDoNotCallDirectly, audioCodec, container, videoCodec, controller = (0, webcodecs_controller_1.webcodecsController)(), onAudioTrack: userAudioResolver, onVideoTrack: userVideoResolver, reader, fields, logLevel = 'info', writer, progressIntervalInMs, rotate, apiKey, resize, onAudioCodec, onContainer, onDimensions, onDurationInSeconds, onFps, onImages, onInternalStats, onIsHdr, onKeyframes, onLocation, onMetadata, onMimeType, onName, onNumberOfAudioChannels, onRotation, onSampleRate, onSize, onSlowAudioBitrate, onSlowDurationInSeconds, onSlowFps, onSlowKeyframes, onSlowNumberOfFrames, onSlowVideoBitrate, onStructure, onTracks, onUnrotatedDimensions, onVideoCodec, ...more }) {
|
|
24
|
+
const convertMedia = async function ({ src, onVideoFrame, onAudioData, onProgress: onProgressDoNotCallDirectly, audioCodec, container, videoCodec, controller = (0, webcodecs_controller_1.webcodecsController)(), onAudioTrack: userAudioResolver, onVideoTrack: userVideoResolver, reader, fields, logLevel = 'info', writer, progressIntervalInMs, rotate, apiKey, resize, onAudioCodec, onContainer, onDimensions, onDurationInSeconds, onFps, onImages, onInternalStats, onIsHdr, onKeyframes, onLocation, onMetadata, onMimeType, onName, onNumberOfAudioChannels, onRotation, onSampleRate, onSize, onSlowAudioBitrate, onSlowDurationInSeconds, onSlowFps, onSlowKeyframes, onSlowNumberOfFrames, onSlowVideoBitrate, onStructure, onTracks, onUnrotatedDimensions, onVideoCodec, onM3uStreams, selectM3uStream, ...more }) {
|
|
25
25
|
var _a, _b;
|
|
26
26
|
if (controller._internals.signal.aborted) {
|
|
27
27
|
return Promise.reject(new media_parser_1.MediaParserAbortError('Aborted'));
|
|
@@ -173,6 +173,8 @@ const convertMedia = async function ({ src, onVideoFrame, onAudioData, onProgres
|
|
|
173
173
|
onUnrotatedDimensions: onUnrotatedDimensions !== null && onUnrotatedDimensions !== void 0 ? onUnrotatedDimensions : null,
|
|
174
174
|
onVideoCodec: onVideoCodec !== null && onVideoCodec !== void 0 ? onVideoCodec : null,
|
|
175
175
|
apiName: 'convertMedia()',
|
|
176
|
+
onM3uStreams: onM3uStreams !== null && onM3uStreams !== void 0 ? onM3uStreams : null,
|
|
177
|
+
selectM3uStream: selectM3uStream !== null && selectM3uStream !== void 0 ? selectM3uStream : media_parser_1.defaultSelectM3uStreamFn,
|
|
176
178
|
})
|
|
177
179
|
.then(() => {
|
|
178
180
|
return state.waitForFinish();
|
|
@@ -13,7 +13,7 @@ const serialize_track_1 = require("./serialize-track");
|
|
|
13
13
|
const create_meta_1 = require("./udta/create-meta");
|
|
14
14
|
const create_hdlr_1 = require("./udta/meta/create-hdlr");
|
|
15
15
|
// TODO: Creates a header that is way too large
|
|
16
|
-
const HEADER_LENGTH =
|
|
16
|
+
const HEADER_LENGTH = 2048000;
|
|
17
17
|
const createPaddedMoovAtom = ({ durationInUnits, trackInfo, timescale, }) => {
|
|
18
18
|
return (0, primitives_1.padIsoBaseMediaBytes)((0, create_moov_1.createMoov)({
|
|
19
19
|
mvhd: (0, create_mvhd_1.createMvhd)({
|
|
@@ -18,7 +18,10 @@ const createSttsAtom = (samplePositions) => {
|
|
|
18
18
|
var _a, _b;
|
|
19
19
|
// TODO: Why does 0 appear here?
|
|
20
20
|
if (a[i].duration === undefined || a[i].duration === 0) {
|
|
21
|
-
|
|
21
|
+
if (a[i + 1] === undefined) {
|
|
22
|
+
return a[i].dts - ((_b = (_a = a[i - 1]) === null || _a === void 0 ? void 0 : _a.dts) !== null && _b !== void 0 ? _b : a[i].dts);
|
|
23
|
+
}
|
|
24
|
+
return a[i + 1].dts - a[i].dts;
|
|
22
25
|
}
|
|
23
26
|
return a[i].duration;
|
|
24
27
|
});
|
package/dist/esm/index.mjs
CHANGED
|
@@ -748,7 +748,9 @@ var createAudioDecoder = ({
|
|
|
748
748
|
});
|
|
749
749
|
const chunk = new EncodedAudioChunk(audioSample);
|
|
750
750
|
audioDecoder.decode(chunk);
|
|
751
|
-
|
|
751
|
+
if (chunk.byteLength > 16) {
|
|
752
|
+
ioSynchronizer.inputItem(chunk.timestamp, audioSample.type === "key");
|
|
753
|
+
}
|
|
752
754
|
};
|
|
753
755
|
let queue = Promise.resolve();
|
|
754
756
|
return {
|
|
@@ -996,6 +998,13 @@ var getAudioEncoderConfig = async (config) => {
|
|
|
996
998
|
if ((await AudioEncoder.isConfigSupported(actualConfig)).supported) {
|
|
997
999
|
return actualConfig;
|
|
998
1000
|
}
|
|
1001
|
+
const maybeItIsTheSampleRateThatIsTheProblem = config.sampleRate !== 48000 && config.sampleRate !== 44100;
|
|
1002
|
+
if (maybeItIsTheSampleRateThatIsTheProblem) {
|
|
1003
|
+
return getAudioEncoderConfig({
|
|
1004
|
+
...config,
|
|
1005
|
+
sampleRate: config.sampleRate === 22050 ? 44100 : 48000
|
|
1006
|
+
});
|
|
1007
|
+
}
|
|
999
1008
|
return null;
|
|
1000
1009
|
};
|
|
1001
1010
|
|
|
@@ -1420,6 +1429,7 @@ var canReencodeVideoTrack = async ({
|
|
|
1420
1429
|
};
|
|
1421
1430
|
// src/convert-media.ts
|
|
1422
1431
|
import {
|
|
1432
|
+
defaultSelectM3uStreamFn,
|
|
1423
1433
|
MediaParserAbortError as MediaParserAbortError3,
|
|
1424
1434
|
MediaParserInternals as MediaParserInternals9
|
|
1425
1435
|
} from "@remotion/media-parser";
|
|
@@ -1711,15 +1721,15 @@ var makeAudioTrackHandler = ({
|
|
|
1711
1721
|
}
|
|
1712
1722
|
const codecPrivate = audioOperation.audioCodec === "aac" ? MediaParserInternals3.createAacCodecPrivate({
|
|
1713
1723
|
audioObjectType: 2,
|
|
1714
|
-
sampleRate:
|
|
1715
|
-
channelConfiguration:
|
|
1724
|
+
sampleRate: audioEncoderConfig.sampleRate,
|
|
1725
|
+
channelConfiguration: audioEncoderConfig.numberOfChannels,
|
|
1716
1726
|
codecPrivate: null
|
|
1717
1727
|
}) : null;
|
|
1718
1728
|
const { trackNumber } = await state.addTrack({
|
|
1719
1729
|
type: "audio",
|
|
1720
1730
|
codec: audioOperation.audioCodec === "wav" ? "pcm-s16" : audioOperation.audioCodec,
|
|
1721
|
-
numberOfChannels:
|
|
1722
|
-
sampleRate:
|
|
1731
|
+
numberOfChannels: audioEncoderConfig.numberOfChannels,
|
|
1732
|
+
sampleRate: audioEncoderConfig.sampleRate,
|
|
1723
1733
|
codecPrivate,
|
|
1724
1734
|
timescale: track.timescale
|
|
1725
1735
|
});
|
|
@@ -3302,7 +3312,10 @@ var createSttsAtom = (samplePositions) => {
|
|
|
3302
3312
|
let lastDuration = null;
|
|
3303
3313
|
const durations = samplePositions.map((_, i, a) => {
|
|
3304
3314
|
if (a[i].duration === undefined || a[i].duration === 0) {
|
|
3305
|
-
|
|
3315
|
+
if (a[i + 1] === undefined) {
|
|
3316
|
+
return a[i].dts - (a[i - 1]?.dts ?? a[i].dts);
|
|
3317
|
+
}
|
|
3318
|
+
return a[i + 1].dts - a[i].dts;
|
|
3306
3319
|
}
|
|
3307
3320
|
return a[i].duration;
|
|
3308
3321
|
});
|
|
@@ -3505,7 +3518,7 @@ var createMeta = ({
|
|
|
3505
3518
|
};
|
|
3506
3519
|
|
|
3507
3520
|
// src/create/iso-base-media/mp4-header.ts
|
|
3508
|
-
var HEADER_LENGTH =
|
|
3521
|
+
var HEADER_LENGTH = 2048000;
|
|
3509
3522
|
var createPaddedMoovAtom = ({
|
|
3510
3523
|
durationInUnits,
|
|
3511
3524
|
trackInfo,
|
|
@@ -4792,6 +4805,8 @@ var convertMedia = async function({
|
|
|
4792
4805
|
onTracks,
|
|
4793
4806
|
onUnrotatedDimensions,
|
|
4794
4807
|
onVideoCodec,
|
|
4808
|
+
onM3uStreams,
|
|
4809
|
+
selectM3uStream,
|
|
4795
4810
|
...more
|
|
4796
4811
|
}) {
|
|
4797
4812
|
if (controller._internals.signal.aborted) {
|
|
@@ -4940,7 +4955,9 @@ var convertMedia = async function({
|
|
|
4940
4955
|
onTracks: onTracks ?? null,
|
|
4941
4956
|
onUnrotatedDimensions: onUnrotatedDimensions ?? null,
|
|
4942
4957
|
onVideoCodec: onVideoCodec ?? null,
|
|
4943
|
-
apiName: "convertMedia()"
|
|
4958
|
+
apiName: "convertMedia()",
|
|
4959
|
+
onM3uStreams: onM3uStreams ?? null,
|
|
4960
|
+
selectM3uStream: selectM3uStream ?? defaultSelectM3uStreamFn
|
|
4944
4961
|
}).then(() => {
|
|
4945
4962
|
return state.waitForFinish();
|
|
4946
4963
|
}).then(() => {
|
|
@@ -4980,6 +4997,7 @@ var getAvailableAudioCodecs = ({
|
|
|
4980
4997
|
}
|
|
4981
4998
|
throw new Error(`Unsupported container: ${container}`);
|
|
4982
4999
|
};
|
|
5000
|
+
|
|
4983
5001
|
// src/index.ts
|
|
4984
5002
|
var WebCodecsInternals = {
|
|
4985
5003
|
rotateAndResizeVideoFrame,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,23 +1,32 @@
|
|
|
1
|
-
export { createAudioDecoder
|
|
2
|
-
export {
|
|
1
|
+
export { createAudioDecoder } from './audio-decoder';
|
|
2
|
+
export type { WebCodecsAudioDecoder } from './audio-decoder';
|
|
3
|
+
export { createAudioEncoder } from './audio-encoder';
|
|
4
|
+
export type { WebCodecsAudioEncoder } from './audio-encoder';
|
|
3
5
|
export { canCopyAudioTrack } from './can-copy-audio-track';
|
|
4
6
|
export { canCopyVideoTrack } from './can-copy-video-track';
|
|
5
7
|
export { canReencodeAudioTrack } from './can-reencode-audio-track';
|
|
6
8
|
export { canReencodeVideoTrack } from './can-reencode-video-track';
|
|
7
|
-
export { convertMedia
|
|
9
|
+
export { convertMedia } from './convert-media';
|
|
10
|
+
export type { ConvertMediaOnAudioData, ConvertMediaOnProgress, ConvertMediaOnVideoFrame, ConvertMediaProgress, ConvertMediaResult, } from './convert-media';
|
|
8
11
|
export { defaultOnAudioTrackHandler } from './default-on-audio-track-handler';
|
|
9
12
|
export { defaultOnVideoTrackHandler } from './default-on-video-track-handler';
|
|
10
|
-
export {
|
|
11
|
-
export {
|
|
12
|
-
export {
|
|
13
|
+
export { getAvailableAudioCodecs } from './get-available-audio-codecs';
|
|
14
|
+
export type { ConvertMediaAudioCodec } from './get-available-audio-codecs';
|
|
15
|
+
export { getAvailableContainers } from './get-available-containers';
|
|
16
|
+
export type { ConvertMediaContainer } from './get-available-containers';
|
|
17
|
+
export { getAvailableVideoCodecs } from './get-available-video-codecs';
|
|
18
|
+
export type { ConvertMediaVideoCodec } from './get-available-video-codecs';
|
|
13
19
|
export { getDefaultAudioCodec } from './get-default-audio-codec';
|
|
14
20
|
export { getDefaultVideoCodec } from './get-default-video-codec';
|
|
15
|
-
export { AudioOperation, ConvertMediaOnAudioTrackHandler, } from './on-audio-track-handler';
|
|
16
|
-
export { ConvertMediaOnVideoTrackHandler, VideoOperation, } from './on-video-track-handler';
|
|
21
|
+
export type { AudioOperation, ConvertMediaOnAudioTrackHandler, } from './on-audio-track-handler';
|
|
22
|
+
export type { ConvertMediaOnVideoTrackHandler, VideoOperation, } from './on-video-track-handler';
|
|
17
23
|
export type { ResizeOperation } from './resizing/mode';
|
|
18
|
-
export { createVideoDecoder
|
|
19
|
-
export {
|
|
20
|
-
export {
|
|
24
|
+
export { createVideoDecoder } from './video-decoder';
|
|
25
|
+
export type { WebCodecsVideoDecoder } from './video-decoder';
|
|
26
|
+
export { createVideoEncoder } from './video-encoder';
|
|
27
|
+
export type { WebCodecsVideoEncoder } from './video-encoder';
|
|
28
|
+
export { webcodecsController } from './webcodecs-controller';
|
|
29
|
+
export type { WebCodecsController } from './webcodecs-controller';
|
|
21
30
|
export declare const WebCodecsInternals: {
|
|
22
31
|
rotateAndResizeVideoFrame: ({ frame, rotation, videoCodec, resizeOperation, }: {
|
|
23
32
|
frame: VideoFrame;
|
package/dist/on-audio-track.js
CHANGED
|
@@ -79,8 +79,8 @@ const makeAudioTrackHandler = ({ state, defaultAudioCodec: audioCodec, controlle
|
|
|
79
79
|
const codecPrivate = audioOperation.audioCodec === 'aac'
|
|
80
80
|
? media_parser_1.MediaParserInternals.createAacCodecPrivate({
|
|
81
81
|
audioObjectType: 2,
|
|
82
|
-
sampleRate:
|
|
83
|
-
channelConfiguration:
|
|
82
|
+
sampleRate: audioEncoderConfig.sampleRate,
|
|
83
|
+
channelConfiguration: audioEncoderConfig.numberOfChannels,
|
|
84
84
|
codecPrivate: null,
|
|
85
85
|
})
|
|
86
86
|
: null;
|
|
@@ -89,8 +89,8 @@ const makeAudioTrackHandler = ({ state, defaultAudioCodec: audioCodec, controlle
|
|
|
89
89
|
codec: audioOperation.audioCodec === 'wav'
|
|
90
90
|
? 'pcm-s16'
|
|
91
91
|
: audioOperation.audioCodec,
|
|
92
|
-
numberOfChannels:
|
|
93
|
-
sampleRate:
|
|
92
|
+
numberOfChannels: audioEncoderConfig.numberOfChannels,
|
|
93
|
+
sampleRate: audioEncoderConfig.sampleRate,
|
|
94
94
|
codecPrivate,
|
|
95
95
|
timescale: track.timescale,
|
|
96
96
|
});
|
|
@@ -18,6 +18,6 @@ const convert_media_1 = require("../convert-media");
|
|
|
18
18
|
writer: (0, node_writer_1.nodeWriter)('outputbun.mp4'),
|
|
19
19
|
});
|
|
20
20
|
const data = await save();
|
|
21
|
-
(0, bun_test_1.expect)(data.size).toBe(
|
|
21
|
+
(0, bun_test_1.expect)(data.size).toBe(16330323);
|
|
22
22
|
(0, node_fs_1.unlinkSync)('outputbun.mp4');
|
|
23
23
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remotion/webcodecs",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.267",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"module": "dist/esm/index.mjs",
|
|
@@ -17,15 +17,15 @@
|
|
|
17
17
|
"author": "Jonny Burger <jonny@remotion.dev>",
|
|
18
18
|
"license": "Remotion License (See https://remotion.dev/docs/webcodecs#license)",
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@remotion/media-parser": "4.0.
|
|
21
|
-
"@remotion/licensing": "4.0.
|
|
20
|
+
"@remotion/media-parser": "4.0.267",
|
|
21
|
+
"@remotion/licensing": "4.0.267"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@types/dom-webcodecs": "0.1.11",
|
|
26
26
|
"eslint": "9.19.0",
|
|
27
|
-
"@remotion/example-videos": "4.0.
|
|
28
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
27
|
+
"@remotion/example-videos": "4.0.267",
|
|
28
|
+
"@remotion/eslint-config-internal": "4.0.267"
|
|
29
29
|
},
|
|
30
30
|
"keywords": [],
|
|
31
31
|
"publishConfig": {
|