@remotion/media 4.0.430 → 4.0.432
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/audio-for-preview.d.ts +1 -0
- package/dist/audio/audio-preview-iterator.d.ts +16 -9
- package/dist/audio/props.d.ts +1 -0
- package/dist/audio-iterator-manager.d.ts +24 -13
- package/dist/debug-overlay/preview-overlay.d.ts +24 -14
- package/dist/esm/index.mjs +755 -537
- package/dist/make-iterator-with-priming.d.ts +6 -0
- package/dist/media-player.d.ts +12 -7
- package/dist/prewarm-iterator-for-looping.d.ts +3 -2
- package/dist/set-global-time-anchor.d.ts +11 -0
- package/dist/shared-audio-context-for-media-player.d.ts +8 -0
- package/dist/use-common-effects.d.ts +32 -0
- package/dist/video/props.d.ts +1 -0
- package/dist/video/video-for-preview.d.ts +1 -0
- package/package.json +4 -4
- package/dist/audio/allow-wait.d.ts +0 -6
- package/dist/audio/allow-wait.js +0 -15
- package/dist/audio/audio-for-preview.js +0 -304
- package/dist/audio/audio-for-rendering.js +0 -194
- package/dist/audio/audio-preview-iterator.js +0 -176
- package/dist/audio/audio.js +0 -20
- package/dist/audio/props.js +0 -1
- package/dist/audio-extraction/audio-cache.js +0 -66
- package/dist/audio-extraction/audio-iterator.js +0 -132
- package/dist/audio-extraction/audio-manager.js +0 -113
- package/dist/audio-extraction/extract-audio.js +0 -132
- package/dist/audio-iterator-manager.js +0 -228
- package/dist/browser-can-use-webgl2.js +0 -13
- package/dist/caches.js +0 -61
- package/dist/calculate-playbacktime.js +0 -4
- package/dist/convert-audiodata/apply-volume.js +0 -17
- package/dist/convert-audiodata/combine-audiodata.js +0 -23
- package/dist/convert-audiodata/convert-audiodata.js +0 -73
- package/dist/convert-audiodata/resample-audiodata.js +0 -94
- package/dist/debug-overlay/preview-overlay.js +0 -42
- package/dist/extract-frame-and-audio.js +0 -101
- package/dist/get-sink.js +0 -15
- package/dist/get-time-in-seconds.js +0 -40
- package/dist/helpers/round-to-4-digits.js +0 -4
- package/dist/index.js +0 -12
- package/dist/is-type-of-error.js +0 -20
- package/dist/looped-frame.js +0 -10
- package/dist/media-player.js +0 -431
- package/dist/nonce-manager.js +0 -13
- package/dist/prewarm-iterator-for-looping.js +0 -56
- package/dist/render-timestamp-range.js +0 -9
- package/dist/show-in-timeline.js +0 -31
- package/dist/use-media-in-timeline.js +0 -103
- package/dist/video/props.js +0 -1
- package/dist/video/video-for-preview.js +0 -331
- package/dist/video/video-for-rendering.js +0 -263
- package/dist/video/video-preview-iterator.js +0 -122
- package/dist/video/video.js +0 -35
- package/dist/video-extraction/add-broadcast-channel-listener.js +0 -125
- package/dist/video-extraction/extract-frame-via-broadcast-channel.js +0 -113
- package/dist/video-extraction/extract-frame.js +0 -85
- package/dist/video-extraction/get-allocation-size.js +0 -6
- package/dist/video-extraction/get-frames-since-keyframe.js +0 -108
- package/dist/video-extraction/keyframe-bank.js +0 -159
- package/dist/video-extraction/keyframe-manager.js +0 -206
- package/dist/video-extraction/remember-actual-matroska-timestamps.js +0 -19
- package/dist/video-extraction/rotate-frame.js +0 -34
- package/dist/video-iterator-manager.js +0 -109
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
// Remotion exports all videos with 2 channels.
|
|
2
|
-
export const TARGET_NUMBER_OF_CHANNELS = 2;
|
|
3
|
-
// Remotion exports all videos with 48kHz sample rate.
|
|
4
|
-
export const TARGET_SAMPLE_RATE = 48000;
|
|
5
|
-
const fixFloatingPoint = (value) => {
|
|
6
|
-
if (value % 1 < 0.0000001) {
|
|
7
|
-
return Math.floor(value);
|
|
8
|
-
}
|
|
9
|
-
if (value % 1 > 0.9999999) {
|
|
10
|
-
return Math.ceil(value);
|
|
11
|
-
}
|
|
12
|
-
return value;
|
|
13
|
-
};
|
|
14
|
-
export const resampleAudioData = ({ srcNumberOfChannels, sourceChannels, destination, targetFrames, chunkSize, }) => {
|
|
15
|
-
const getSourceValues = (startUnfixed, endUnfixed, channelIndex) => {
|
|
16
|
-
const start = fixFloatingPoint(startUnfixed);
|
|
17
|
-
const end = fixFloatingPoint(endUnfixed);
|
|
18
|
-
const startFloor = Math.floor(start);
|
|
19
|
-
const startCeil = Math.ceil(start);
|
|
20
|
-
const startFraction = start - startFloor;
|
|
21
|
-
const endFraction = end - Math.floor(end);
|
|
22
|
-
const endFloor = Math.floor(end);
|
|
23
|
-
let weightedSum = 0;
|
|
24
|
-
let totalWeight = 0;
|
|
25
|
-
// Handle first fractional sample
|
|
26
|
-
if (startFraction > 0) {
|
|
27
|
-
const firstSample = sourceChannels[startFloor * srcNumberOfChannels + channelIndex];
|
|
28
|
-
weightedSum += firstSample * (1 - startFraction);
|
|
29
|
-
totalWeight += 1 - startFraction;
|
|
30
|
-
}
|
|
31
|
-
// Handle full samples
|
|
32
|
-
for (let k = startCeil; k < endFloor; k++) {
|
|
33
|
-
const num = sourceChannels[k * srcNumberOfChannels + channelIndex];
|
|
34
|
-
weightedSum += num;
|
|
35
|
-
totalWeight += 1;
|
|
36
|
-
}
|
|
37
|
-
// Handle last fractional sample
|
|
38
|
-
if (endFraction > 0) {
|
|
39
|
-
const lastSample = sourceChannels[endFloor * srcNumberOfChannels + channelIndex];
|
|
40
|
-
weightedSum += lastSample * endFraction;
|
|
41
|
-
totalWeight += endFraction;
|
|
42
|
-
}
|
|
43
|
-
const average = weightedSum / totalWeight;
|
|
44
|
-
return average;
|
|
45
|
-
};
|
|
46
|
-
for (let newFrameIndex = 0; newFrameIndex < targetFrames; newFrameIndex++) {
|
|
47
|
-
const start = newFrameIndex * chunkSize;
|
|
48
|
-
const end = start + chunkSize;
|
|
49
|
-
if (TARGET_NUMBER_OF_CHANNELS === srcNumberOfChannels) {
|
|
50
|
-
for (let i = 0; i < srcNumberOfChannels; i++) {
|
|
51
|
-
destination[newFrameIndex * srcNumberOfChannels + i] = getSourceValues(start, end, i);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
// The following formulas were taken from Mediabunnys audio resampler:
|
|
55
|
-
// https://github.com/Vanilagy/mediabunny/blob/b9f7ab2fa2b9167784cbded044d466185308999f/src/conversion.ts
|
|
56
|
-
// Mono to Stereo: M -> L, M -> R
|
|
57
|
-
if (srcNumberOfChannels === 1) {
|
|
58
|
-
const m = getSourceValues(start, end, 0);
|
|
59
|
-
destination[newFrameIndex * 2 + 0] = m;
|
|
60
|
-
destination[newFrameIndex * 2 + 1] = m;
|
|
61
|
-
}
|
|
62
|
-
// Quad to Stereo: 0.5 * (L + SL), 0.5 * (R + SR)
|
|
63
|
-
else if (srcNumberOfChannels === 4) {
|
|
64
|
-
const l = getSourceValues(start, end, 0);
|
|
65
|
-
const r = getSourceValues(start, end, 1);
|
|
66
|
-
const sl = getSourceValues(start, end, 2);
|
|
67
|
-
const sr = getSourceValues(start, end, 3);
|
|
68
|
-
const l2 = 0.5 * (l + sl);
|
|
69
|
-
const r2 = 0.5 * (r + sr);
|
|
70
|
-
destination[newFrameIndex * 2 + 0] = l2;
|
|
71
|
-
destination[newFrameIndex * 2 + 1] = r2;
|
|
72
|
-
}
|
|
73
|
-
// 5.1 to Stereo: L + sqrt(1/2) * (C + SL), R + sqrt(1/2) * (C + SR)
|
|
74
|
-
else if (srcNumberOfChannels === 6) {
|
|
75
|
-
const l = getSourceValues(start, end, 0);
|
|
76
|
-
const r = getSourceValues(start, end, 1);
|
|
77
|
-
const c = getSourceValues(start, end, 2);
|
|
78
|
-
const sl = getSourceValues(start, end, 3);
|
|
79
|
-
const sr = getSourceValues(start, end, 4);
|
|
80
|
-
const sq = Math.sqrt(1 / 2);
|
|
81
|
-
const l2 = l + sq * (c + sl);
|
|
82
|
-
const r2 = r + sq * (c + sr);
|
|
83
|
-
destination[newFrameIndex * 2 + 0] = l2;
|
|
84
|
-
destination[newFrameIndex * 2 + 1] = r2;
|
|
85
|
-
}
|
|
86
|
-
// Discrete fallback: direct mapping with zero-fill or drop
|
|
87
|
-
else {
|
|
88
|
-
for (let i = 0; i < srcNumberOfChannels; i++) {
|
|
89
|
-
destination[newFrameIndex * TARGET_NUMBER_OF_CHANNELS + i] =
|
|
90
|
-
getSourceValues(start, end, i);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
};
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
export const drawPreviewOverlay = ({ context, audioTime, audioContextState, audioSyncAnchor, playing, audioIteratorManager, videoIteratorManager, }) => {
|
|
2
|
-
// Collect all lines to be rendered
|
|
3
|
-
const lines = [
|
|
4
|
-
'Debug overlay',
|
|
5
|
-
`Video iterators created: ${videoIteratorManager?.getVideoIteratorsCreated()}`,
|
|
6
|
-
`Audio iterators created: ${audioIteratorManager?.getAudioIteratorsCreated()}`,
|
|
7
|
-
`Frames rendered: ${videoIteratorManager?.getFramesRendered()}`,
|
|
8
|
-
`Audio context state: ${audioContextState}`,
|
|
9
|
-
`Audio time: ${(audioTime - audioSyncAnchor).toFixed(3)}s`,
|
|
10
|
-
];
|
|
11
|
-
if (audioIteratorManager) {
|
|
12
|
-
const queuedPeriod = audioIteratorManager
|
|
13
|
-
.getAudioBufferIterator()
|
|
14
|
-
?.getQueuedPeriod();
|
|
15
|
-
const numberOfChunksAfterResuming = audioIteratorManager
|
|
16
|
-
?.getAudioBufferIterator()
|
|
17
|
-
?.getNumberOfChunksAfterResuming();
|
|
18
|
-
if (queuedPeriod) {
|
|
19
|
-
lines.push(`Audio queued until: ${(queuedPeriod.until - (audioTime - audioSyncAnchor)).toFixed(3)}s`);
|
|
20
|
-
}
|
|
21
|
-
else if (numberOfChunksAfterResuming) {
|
|
22
|
-
lines.push(`Audio chunks for after resuming: ${numberOfChunksAfterResuming}`);
|
|
23
|
-
}
|
|
24
|
-
lines.push(`Playing: ${playing}`);
|
|
25
|
-
}
|
|
26
|
-
const lineHeight = 30; // px, should match or exceed font size
|
|
27
|
-
const boxPaddingX = 10;
|
|
28
|
-
const boxPaddingY = 10;
|
|
29
|
-
const boxLeft = 20;
|
|
30
|
-
const boxTop = 20;
|
|
31
|
-
const boxWidth = 600;
|
|
32
|
-
const boxHeight = lines.length * lineHeight + 2 * boxPaddingY;
|
|
33
|
-
// Draw background for text legibility
|
|
34
|
-
context.fillStyle = 'rgba(0, 0, 0, 1)';
|
|
35
|
-
context.fillRect(boxLeft, boxTop, boxWidth, boxHeight);
|
|
36
|
-
context.fillStyle = 'white';
|
|
37
|
-
context.font = '24px sans-serif';
|
|
38
|
-
context.textBaseline = 'top';
|
|
39
|
-
for (let i = 0; i < lines.length; i++) {
|
|
40
|
-
context.fillText(lines[i], boxLeft + boxPaddingX, boxTop + boxPaddingY + i * lineHeight);
|
|
41
|
-
}
|
|
42
|
-
};
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { extractAudio } from './audio-extraction/extract-audio';
|
|
2
|
-
import { isNetworkError } from './is-type-of-error';
|
|
3
|
-
import { extractFrame } from './video-extraction/extract-frame';
|
|
4
|
-
import { rotateFrame } from './video-extraction/rotate-frame';
|
|
5
|
-
export const extractFrameAndAudio = async ({ src, timeInSeconds, logLevel, durationInSeconds, playbackRate, includeAudio, includeVideo, loop, audioStreamIndex, trimAfter, trimBefore, fps, maxCacheSize, }) => {
|
|
6
|
-
try {
|
|
7
|
-
const [frame, audio] = await Promise.all([
|
|
8
|
-
includeVideo
|
|
9
|
-
? extractFrame({
|
|
10
|
-
src,
|
|
11
|
-
timeInSeconds,
|
|
12
|
-
logLevel,
|
|
13
|
-
loop,
|
|
14
|
-
trimAfter,
|
|
15
|
-
playbackRate,
|
|
16
|
-
trimBefore,
|
|
17
|
-
fps,
|
|
18
|
-
maxCacheSize,
|
|
19
|
-
})
|
|
20
|
-
: null,
|
|
21
|
-
includeAudio
|
|
22
|
-
? extractAudio({
|
|
23
|
-
src,
|
|
24
|
-
timeInSeconds,
|
|
25
|
-
durationInSeconds,
|
|
26
|
-
logLevel,
|
|
27
|
-
loop,
|
|
28
|
-
playbackRate,
|
|
29
|
-
audioStreamIndex,
|
|
30
|
-
trimAfter,
|
|
31
|
-
fps,
|
|
32
|
-
trimBefore,
|
|
33
|
-
maxCacheSize,
|
|
34
|
-
})
|
|
35
|
-
: null,
|
|
36
|
-
]);
|
|
37
|
-
if (frame?.type === 'cannot-decode') {
|
|
38
|
-
return {
|
|
39
|
-
type: 'cannot-decode',
|
|
40
|
-
durationInSeconds: frame.durationInSeconds,
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
if (frame?.type === 'unknown-container-format') {
|
|
44
|
-
return { type: 'unknown-container-format' };
|
|
45
|
-
}
|
|
46
|
-
if (frame?.type === 'cannot-decode-alpha') {
|
|
47
|
-
return {
|
|
48
|
-
type: 'cannot-decode-alpha',
|
|
49
|
-
durationInSeconds: frame.durationInSeconds,
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
if (frame?.type === 'network-error') {
|
|
53
|
-
return { type: 'network-error' };
|
|
54
|
-
}
|
|
55
|
-
if (audio === 'unknown-container-format') {
|
|
56
|
-
if (frame !== null) {
|
|
57
|
-
frame?.frame?.close();
|
|
58
|
-
}
|
|
59
|
-
return { type: 'unknown-container-format' };
|
|
60
|
-
}
|
|
61
|
-
if (audio === 'network-error') {
|
|
62
|
-
if (frame !== null) {
|
|
63
|
-
frame?.frame?.close();
|
|
64
|
-
}
|
|
65
|
-
return { type: 'network-error' };
|
|
66
|
-
}
|
|
67
|
-
if (audio === 'cannot-decode') {
|
|
68
|
-
if (frame?.type === 'success' && frame.frame !== null) {
|
|
69
|
-
frame?.frame.close();
|
|
70
|
-
}
|
|
71
|
-
return {
|
|
72
|
-
type: 'cannot-decode',
|
|
73
|
-
durationInSeconds: frame?.type === 'success' ? frame.durationInSeconds : null,
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
if (!frame?.frame) {
|
|
77
|
-
return {
|
|
78
|
-
type: 'success',
|
|
79
|
-
frame: null,
|
|
80
|
-
audio: audio?.data ?? null,
|
|
81
|
-
durationInSeconds: audio?.durationInSeconds ?? null,
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
return {
|
|
85
|
-
type: 'success',
|
|
86
|
-
frame: await rotateFrame({
|
|
87
|
-
frame: frame.frame.toVideoFrame(),
|
|
88
|
-
rotation: frame.frame.rotation,
|
|
89
|
-
}),
|
|
90
|
-
audio: audio?.data ?? null,
|
|
91
|
-
durationInSeconds: audio?.durationInSeconds ?? null,
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
catch (err) {
|
|
95
|
-
const error = err;
|
|
96
|
-
if (isNetworkError(error)) {
|
|
97
|
-
return { type: 'network-error' };
|
|
98
|
-
}
|
|
99
|
-
throw err;
|
|
100
|
-
}
|
|
101
|
-
};
|
package/dist/get-sink.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { Internals } from 'remotion';
|
|
2
|
-
import { getSinks } from './video-extraction/get-frames-since-keyframe';
|
|
3
|
-
export const sinkPromises = {};
|
|
4
|
-
export const getSink = (src, logLevel) => {
|
|
5
|
-
let promise = sinkPromises[src];
|
|
6
|
-
if (!promise) {
|
|
7
|
-
Internals.Log.verbose({
|
|
8
|
-
logLevel,
|
|
9
|
-
tag: '@remotion/media',
|
|
10
|
-
}, `Sink for ${src} was not found, creating new sink`);
|
|
11
|
-
promise = getSinks(src);
|
|
12
|
-
sinkPromises[src] = promise;
|
|
13
|
-
}
|
|
14
|
-
return promise;
|
|
15
|
-
};
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { Internals } from 'remotion';
|
|
2
|
-
export const getTimeInSeconds = ({ loop, mediaDurationInSeconds, unloopedTimeInSeconds, src, trimAfter, trimBefore, fps, playbackRate, ifNoMediaDuration, }) => {
|
|
3
|
-
if (mediaDurationInSeconds === null && loop && ifNoMediaDuration === 'fail') {
|
|
4
|
-
throw new Error(`Could not determine duration of ${src}, but "loop" was set.`);
|
|
5
|
-
}
|
|
6
|
-
const loopDuration = loop
|
|
7
|
-
? Internals.calculateMediaDuration({
|
|
8
|
-
trimAfter,
|
|
9
|
-
mediaDurationInFrames: mediaDurationInSeconds
|
|
10
|
-
? mediaDurationInSeconds * fps
|
|
11
|
-
: Infinity,
|
|
12
|
-
// Playback rate was already specified before
|
|
13
|
-
playbackRate: 1,
|
|
14
|
-
trimBefore,
|
|
15
|
-
}) / fps
|
|
16
|
-
: Infinity;
|
|
17
|
-
const timeInSeconds = (unloopedTimeInSeconds * playbackRate) % loopDuration;
|
|
18
|
-
if ((trimAfter ?? null) !== null && !loop) {
|
|
19
|
-
const time = (trimAfter - (trimBefore ?? 0)) / fps;
|
|
20
|
-
if (timeInSeconds >= time) {
|
|
21
|
-
return null;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
return timeInSeconds + (trimBefore ?? 0) / fps;
|
|
25
|
-
};
|
|
26
|
-
export const calculateEndTime = ({ mediaDurationInSeconds, ifNoMediaDuration, src, trimAfter, trimBefore, fps, }) => {
|
|
27
|
-
if (mediaDurationInSeconds === null && ifNoMediaDuration === 'fail') {
|
|
28
|
-
throw new Error(`Could not determine duration of ${src}, but "loop" was set.`);
|
|
29
|
-
}
|
|
30
|
-
const mediaDuration = Internals.calculateMediaDuration({
|
|
31
|
-
trimAfter,
|
|
32
|
-
mediaDurationInFrames: mediaDurationInSeconds
|
|
33
|
-
? mediaDurationInSeconds * fps
|
|
34
|
-
: Infinity,
|
|
35
|
-
// Playback rate was already specified before
|
|
36
|
-
playbackRate: 1,
|
|
37
|
-
trimBefore,
|
|
38
|
-
}) / fps;
|
|
39
|
-
return mediaDuration + (trimBefore ?? 0) / fps;
|
|
40
|
-
};
|
package/dist/index.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { Audio } from './audio/audio';
|
|
2
|
-
import { Video } from './video/video';
|
|
3
|
-
/**
|
|
4
|
-
* @deprecated Now just `Audio`
|
|
5
|
-
*/
|
|
6
|
-
export const experimental_Audio = Audio;
|
|
7
|
-
/**
|
|
8
|
-
* @deprecated Now just `Video`
|
|
9
|
-
*/
|
|
10
|
-
export const experimental_Video = Video;
|
|
11
|
-
export { AudioForPreview } from './audio/audio-for-preview';
|
|
12
|
-
export { Audio, Video };
|
package/dist/is-type-of-error.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Utility to check if error is network error
|
|
3
|
-
* @param error
|
|
4
|
-
* @returns
|
|
5
|
-
*/
|
|
6
|
-
export function isNetworkError(error) {
|
|
7
|
-
if (
|
|
8
|
-
// Chrome
|
|
9
|
-
error.message.includes('Failed to fetch') ||
|
|
10
|
-
// Safari
|
|
11
|
-
error.message.includes('Load failed') ||
|
|
12
|
-
// Firefox
|
|
13
|
-
error.message.includes('NetworkError when attempting to fetch resource')) {
|
|
14
|
-
return true;
|
|
15
|
-
}
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
export function isUnsupportedConfigurationError(error) {
|
|
19
|
-
return error.message.includes('Unsupported configuration');
|
|
20
|
-
}
|
package/dist/looped-frame.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export const frameForVolumeProp = ({ behavior, loop, assetDurationInSeconds, fps, frame, startsAt, }) => {
|
|
2
|
-
if (!loop) {
|
|
3
|
-
return frame + startsAt;
|
|
4
|
-
}
|
|
5
|
-
if (behavior === 'extend') {
|
|
6
|
-
return frame + startsAt;
|
|
7
|
-
}
|
|
8
|
-
const assetDurationInFrames = Math.floor(assetDurationInSeconds * fps) - startsAt;
|
|
9
|
-
return (frame % assetDurationInFrames) + startsAt;
|
|
10
|
-
};
|