@remotion/webcodecs 4.0.293 → 4.0.294
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/convert-media.d.ts +2 -1
- package/dist/convert-media.js +2 -1
- package/dist/create/iso-base-media/create-iso-base-media.d.ts +1 -1
- package/dist/create/iso-base-media/create-iso-base-media.js +2 -1
- package/dist/create/iso-base-media/header-length.d.ts +4 -1
- package/dist/create/iso-base-media/header-length.js +7 -3
- package/dist/create/iso-base-media/mp4-header.d.ts +2 -1
- package/dist/create/iso-base-media/mp4-header.js +5 -2
- package/dist/create/media-fn.d.ts +1 -0
- package/dist/esm/index.mjs +20 -7
- package/dist/get-codec-string.js +1 -1
- package/dist/select-container-creator.d.ts +1 -1
- package/package.json +5 -5
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, onM3uStreams, selectM3uStream, selectM3uAssociatedPlaylists, expectedDurationInSeconds, seekingHints, ...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, selectM3uAssociatedPlaylists, expectedDurationInSeconds, expectedFrameRate, seekingHints, ...more }: {
|
|
39
39
|
src: ParseMediaOptions<F>["src"];
|
|
40
40
|
container: ConvertMediaContainer;
|
|
41
41
|
onVideoFrame?: ConvertMediaOnVideoFrame;
|
|
@@ -49,6 +49,7 @@ export declare const convertMedia: <F extends Options<ParseMediaFields>>({ src,
|
|
|
49
49
|
selectM3uStream?: ParseMediaOptions<F>["selectM3uStream"];
|
|
50
50
|
selectM3uAssociatedPlaylists?: ParseMediaOptions<F>["selectM3uAssociatedPlaylists"];
|
|
51
51
|
expectedDurationInSeconds?: number | null;
|
|
52
|
+
expectedFrameRate?: number | null;
|
|
52
53
|
reader?: ParseMediaOptions<F>["reader"];
|
|
53
54
|
logLevel?: LogLevel;
|
|
54
55
|
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, onM3uStreams, selectM3uStream, selectM3uAssociatedPlaylists, expectedDurationInSeconds, seekingHints, ...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, selectM3uAssociatedPlaylists, expectedDurationInSeconds, expectedFrameRate, seekingHints, ...more }) {
|
|
25
25
|
if (controller._internals.signal.aborted) {
|
|
26
26
|
return Promise.reject(new media_parser_1.MediaParserAbortError('Aborted'));
|
|
27
27
|
}
|
|
@@ -78,6 +78,7 @@ const convertMedia = async function ({ src, onVideoFrame, onAudioData, onProgres
|
|
|
78
78
|
logLevel,
|
|
79
79
|
progressTracker,
|
|
80
80
|
expectedDurationInSeconds: expectedDurationInSeconds ?? null,
|
|
81
|
+
expectedFrameRate: expectedFrameRate ?? null,
|
|
81
82
|
});
|
|
82
83
|
const onVideoTrack = (0, on_video_track_1.makeVideoTrackHandler)({
|
|
83
84
|
state,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { MediaFn, MediaFnGeneratorInput } from '../media-fn';
|
|
2
|
-
export declare const createIsoBaseMedia: ({ writer, onBytesProgress, onMillisecondsProgress, logLevel, filename, progressTracker, expectedDurationInSeconds, }: MediaFnGeneratorInput) => Promise<MediaFn>;
|
|
2
|
+
export declare const createIsoBaseMedia: ({ writer, onBytesProgress, onMillisecondsProgress, logLevel, filename, progressTracker, expectedDurationInSeconds, expectedFrameRate, }: MediaFnGeneratorInput) => Promise<MediaFn>;
|
|
@@ -7,7 +7,7 @@ const create_ftyp_1 = require("./create-ftyp");
|
|
|
7
7
|
const mp4_header_1 = require("./mp4-header");
|
|
8
8
|
const primitives_1 = require("./primitives");
|
|
9
9
|
const CONTAINER_TIMESCALE = 1000;
|
|
10
|
-
const createIsoBaseMedia = async ({ writer, onBytesProgress, onMillisecondsProgress, logLevel, filename, progressTracker, expectedDurationInSeconds, }) => {
|
|
10
|
+
const createIsoBaseMedia = async ({ writer, onBytesProgress, onMillisecondsProgress, logLevel, filename, progressTracker, expectedDurationInSeconds, expectedFrameRate, }) => {
|
|
11
11
|
const header = (0, create_ftyp_1.createIsoBaseMediaFtyp)({
|
|
12
12
|
compatibleBrands: ['isom', 'iso2', 'avc1', 'mp42'],
|
|
13
13
|
majorBrand: 'isom',
|
|
@@ -40,6 +40,7 @@ const createIsoBaseMedia = async ({ writer, onBytesProgress, onMillisecondsProgr
|
|
|
40
40
|
timescale: CONTAINER_TIMESCALE,
|
|
41
41
|
expectedDurationInSeconds,
|
|
42
42
|
logLevel,
|
|
43
|
+
expectedFrameRate,
|
|
43
44
|
});
|
|
44
45
|
};
|
|
45
46
|
await w.write(getPaddedMoovAtom());
|
|
@@ -1 +1,4 @@
|
|
|
1
|
-
export declare const calculateAReasonableMp4HeaderLength: (expectedDurationInSeconds
|
|
1
|
+
export declare const calculateAReasonableMp4HeaderLength: ({ expectedDurationInSeconds, expectedFrameRate, }: {
|
|
2
|
+
expectedDurationInSeconds: number | null;
|
|
3
|
+
expectedFrameRate: number | null;
|
|
4
|
+
}) => number;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.calculateAReasonableMp4HeaderLength = void 0;
|
|
4
|
-
const calculateAReasonableMp4HeaderLength = (expectedDurationInSeconds) => {
|
|
4
|
+
const calculateAReasonableMp4HeaderLength = ({ expectedDurationInSeconds, expectedFrameRate, }) => {
|
|
5
5
|
if (expectedDurationInSeconds === null) {
|
|
6
6
|
return 2048000;
|
|
7
7
|
}
|
|
@@ -9,11 +9,15 @@ const calculateAReasonableMp4HeaderLength = (expectedDurationInSeconds) => {
|
|
|
9
9
|
* we had a video that was 1 hour 40 minutes long and the header ended up being 3.7MB. the header approximately grows linearly to the video length in seconds, but we should reserve enough, like at least 50KB in any case.
|
|
10
10
|
* it's better to be safe than to fail, so let's add a 30% safety margin
|
|
11
11
|
*/
|
|
12
|
+
// This was however with 30fps, and there can also be 60fps videos, so let's
|
|
13
|
+
// estimate even more conservatively and estimate 60fps
|
|
14
|
+
const assumedFrameRate = expectedFrameRate ?? 60;
|
|
15
|
+
const frameRateMultiplier = assumedFrameRate / 30;
|
|
12
16
|
// 1h40m = 6000 seconds resulted in 3.7MB header
|
|
13
17
|
// So bytes per second = 3.7MB / 6000 = ~616 bytes/second
|
|
14
18
|
const bytesPerSecond = (3.7 * 1024 * 1024) / 6000;
|
|
15
|
-
// Add 20% safety margin
|
|
16
|
-
const bytesWithSafetyMargin = bytesPerSecond * 1.2;
|
|
19
|
+
// Add 20% safety margin and multiply by frame rate multiplier
|
|
20
|
+
const bytesWithSafetyMargin = bytesPerSecond * 1.2 * frameRateMultiplier;
|
|
17
21
|
// Calculate based on duration, with minimum 50KB
|
|
18
22
|
const calculatedBytes = Math.max(50 * 1024, Math.ceil(expectedDurationInSeconds * bytesWithSafetyMargin));
|
|
19
23
|
return calculatedBytes;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { LogLevel } from '@remotion/media-parser';
|
|
2
2
|
import type { IsoBaseMediaTrackData } from './serialize-track';
|
|
3
|
-
export declare const createPaddedMoovAtom: ({ durationInUnits, trackInfo, timescale, expectedDurationInSeconds, logLevel, }: {
|
|
3
|
+
export declare const createPaddedMoovAtom: ({ durationInUnits, trackInfo, timescale, expectedDurationInSeconds, logLevel, expectedFrameRate, }: {
|
|
4
4
|
durationInUnits: number;
|
|
5
5
|
trackInfo: IsoBaseMediaTrackData[];
|
|
6
6
|
timescale: number;
|
|
7
7
|
expectedDurationInSeconds: number | null;
|
|
8
8
|
logLevel: LogLevel;
|
|
9
|
+
expectedFrameRate: number | null;
|
|
9
10
|
}) => Uint8Array<ArrayBufferLike>;
|
|
@@ -14,8 +14,11 @@ const primitives_1 = require("./primitives");
|
|
|
14
14
|
const serialize_track_1 = require("./serialize-track");
|
|
15
15
|
const create_meta_1 = require("./udta/create-meta");
|
|
16
16
|
const create_hdlr_1 = require("./udta/meta/create-hdlr");
|
|
17
|
-
const createPaddedMoovAtom = ({ durationInUnits, trackInfo, timescale, expectedDurationInSeconds, logLevel, }) => {
|
|
18
|
-
const headerLength = (0, header_length_1.calculateAReasonableMp4HeaderLength)(
|
|
17
|
+
const createPaddedMoovAtom = ({ durationInUnits, trackInfo, timescale, expectedDurationInSeconds, logLevel, expectedFrameRate, }) => {
|
|
18
|
+
const headerLength = (0, header_length_1.calculateAReasonableMp4HeaderLength)({
|
|
19
|
+
expectedDurationInSeconds,
|
|
20
|
+
expectedFrameRate,
|
|
21
|
+
});
|
|
19
22
|
if (expectedDurationInSeconds !== null) {
|
|
20
23
|
log_1.Log.verbose(logLevel, `Expecting duration of the video to be ${expectedDurationInSeconds} seconds, allocating ${headerLength} bytes for the MP4 header.`);
|
|
21
24
|
}
|
package/dist/esm/index.mjs
CHANGED
|
@@ -3031,12 +3031,17 @@ var createUdta = (children) => {
|
|
|
3031
3031
|
};
|
|
3032
3032
|
|
|
3033
3033
|
// src/create/iso-base-media/header-length.ts
|
|
3034
|
-
var calculateAReasonableMp4HeaderLength = (
|
|
3034
|
+
var calculateAReasonableMp4HeaderLength = ({
|
|
3035
|
+
expectedDurationInSeconds,
|
|
3036
|
+
expectedFrameRate
|
|
3037
|
+
}) => {
|
|
3035
3038
|
if (expectedDurationInSeconds === null) {
|
|
3036
3039
|
return 2048000;
|
|
3037
3040
|
}
|
|
3041
|
+
const assumedFrameRate = expectedFrameRate ?? 60;
|
|
3042
|
+
const frameRateMultiplier = assumedFrameRate / 30;
|
|
3038
3043
|
const bytesPerSecond = 3.7 * 1024 * 1024 / 6000;
|
|
3039
|
-
const bytesWithSafetyMargin = bytesPerSecond * 1.2;
|
|
3044
|
+
const bytesWithSafetyMargin = bytesPerSecond * 1.2 * frameRateMultiplier;
|
|
3040
3045
|
const calculatedBytes = Math.max(50 * 1024, Math.ceil(expectedDurationInSeconds * bytesWithSafetyMargin));
|
|
3041
3046
|
return calculatedBytes;
|
|
3042
3047
|
};
|
|
@@ -3782,9 +3787,13 @@ var createPaddedMoovAtom = ({
|
|
|
3782
3787
|
trackInfo,
|
|
3783
3788
|
timescale,
|
|
3784
3789
|
expectedDurationInSeconds,
|
|
3785
|
-
logLevel
|
|
3790
|
+
logLevel,
|
|
3791
|
+
expectedFrameRate
|
|
3786
3792
|
}) => {
|
|
3787
|
-
const headerLength = calculateAReasonableMp4HeaderLength(
|
|
3793
|
+
const headerLength = calculateAReasonableMp4HeaderLength({
|
|
3794
|
+
expectedDurationInSeconds,
|
|
3795
|
+
expectedFrameRate
|
|
3796
|
+
});
|
|
3788
3797
|
if (expectedDurationInSeconds !== null) {
|
|
3789
3798
|
Log.verbose(logLevel, `Expecting duration of the video to be ${expectedDurationInSeconds} seconds, allocating ${headerLength} bytes for the MP4 header.`);
|
|
3790
3799
|
} else {
|
|
@@ -3828,7 +3837,8 @@ var createIsoBaseMedia = async ({
|
|
|
3828
3837
|
logLevel,
|
|
3829
3838
|
filename,
|
|
3830
3839
|
progressTracker,
|
|
3831
|
-
expectedDurationInSeconds
|
|
3840
|
+
expectedDurationInSeconds,
|
|
3841
|
+
expectedFrameRate
|
|
3832
3842
|
}) => {
|
|
3833
3843
|
const header = createIsoBaseMediaFtyp({
|
|
3834
3844
|
compatibleBrands: ["isom", "iso2", "avc1", "mp42"],
|
|
@@ -3861,7 +3871,8 @@ var createIsoBaseMedia = async ({
|
|
|
3861
3871
|
}),
|
|
3862
3872
|
timescale: CONTAINER_TIMESCALE,
|
|
3863
3873
|
expectedDurationInSeconds,
|
|
3864
|
-
logLevel
|
|
3874
|
+
logLevel,
|
|
3875
|
+
expectedFrameRate
|
|
3865
3876
|
});
|
|
3866
3877
|
};
|
|
3867
3878
|
await w.write(getPaddedMoovAtom());
|
|
@@ -5060,6 +5071,7 @@ var convertMedia = async function({
|
|
|
5060
5071
|
selectM3uStream,
|
|
5061
5072
|
selectM3uAssociatedPlaylists,
|
|
5062
5073
|
expectedDurationInSeconds,
|
|
5074
|
+
expectedFrameRate,
|
|
5063
5075
|
seekingHints,
|
|
5064
5076
|
...more
|
|
5065
5077
|
}) {
|
|
@@ -5118,7 +5130,8 @@ var convertMedia = async function({
|
|
|
5118
5130
|
},
|
|
5119
5131
|
logLevel,
|
|
5120
5132
|
progressTracker,
|
|
5121
|
-
expectedDurationInSeconds: expectedDurationInSeconds ?? null
|
|
5133
|
+
expectedDurationInSeconds: expectedDurationInSeconds ?? null,
|
|
5134
|
+
expectedFrameRate: expectedFrameRate ?? null
|
|
5122
5135
|
});
|
|
5123
5136
|
const onVideoTrack = makeVideoTrackHandler({
|
|
5124
5137
|
state,
|
package/dist/get-codec-string.js
CHANGED
|
@@ -5,7 +5,7 @@ const choose_correct_avc1_profile_1 = require("./choose-correct-avc1-profile");
|
|
|
5
5
|
const choose_correct_hevc_profile_1 = require("./choose-correct-hevc-profile");
|
|
6
6
|
const getCodecStringForEncoder = ({ codec, fps, height, width, }) => {
|
|
7
7
|
if (codec === 'h264') {
|
|
8
|
-
return (0, choose_correct_avc1_profile_1.chooseCorrectAvc1Profile)({ fps, height, width });
|
|
8
|
+
return (0, choose_correct_avc1_profile_1.chooseCorrectAvc1Profile)({ fps, height, width }); // return chooseCorrectAvc1Profile({fps, height, width});
|
|
9
9
|
}
|
|
10
10
|
if (codec === 'h265') {
|
|
11
11
|
return (0, choose_correct_hevc_profile_1.chooseCorrectHevcProfile)({ fps, height, width });
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ConvertMediaContainer } from './get-available-containers';
|
|
2
|
-
export declare const selectContainerCreator: (container: ConvertMediaContainer) => ({ writer, onBytesProgress, onMillisecondsProgress, logLevel, filename, progressTracker, expectedDurationInSeconds, }: import("./create/media-fn").MediaFnGeneratorInput) => Promise<import("./create/media-fn").MediaFn>;
|
|
2
|
+
export declare const selectContainerCreator: (container: ConvertMediaContainer) => ({ writer, onBytesProgress, onMillisecondsProgress, logLevel, filename, progressTracker, expectedDurationInSeconds, expectedFrameRate, }: import("./create/media-fn").MediaFnGeneratorInput) => Promise<import("./create/media-fn").MediaFn>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remotion/webcodecs",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.294",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"module": "dist/esm/index.mjs",
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
"author": "Jonny Burger <jonny@remotion.dev>",
|
|
20
20
|
"license": "Remotion License (See https://remotion.dev/docs/webcodecs#license)",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@remotion/media-parser": "4.0.
|
|
23
|
-
"@remotion/licensing": "4.0.
|
|
22
|
+
"@remotion/media-parser": "4.0.294",
|
|
23
|
+
"@remotion/licensing": "4.0.294"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {},
|
|
26
26
|
"devDependencies": {
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"playwright": "1.51.1",
|
|
29
29
|
"@playwright/test": "1.51.1",
|
|
30
30
|
"eslint": "9.19.0",
|
|
31
|
-
"@remotion/example-videos": "4.0.
|
|
32
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
31
|
+
"@remotion/example-videos": "4.0.294",
|
|
32
|
+
"@remotion/eslint-config-internal": "4.0.294"
|
|
33
33
|
},
|
|
34
34
|
"keywords": [],
|
|
35
35
|
"publishConfig": {
|