@remotion/media 4.0.356 → 4.0.357
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 +30 -0
- package/dist/audio/audio-for-preview.js +213 -0
- package/dist/audio/audio-for-rendering.js +32 -15
- package/dist/audio/audio.js +7 -49
- package/dist/audio/props.d.ts +8 -14
- package/dist/audio-extraction/audio-cache.d.ts +1 -1
- package/dist/audio-extraction/audio-cache.js +5 -1
- package/dist/audio-extraction/audio-iterator.d.ts +4 -1
- package/dist/audio-extraction/audio-iterator.js +22 -10
- package/dist/audio-extraction/audio-manager.d.ts +8 -37
- package/dist/audio-extraction/audio-manager.js +35 -8
- package/dist/audio-extraction/extract-audio.d.ts +9 -2
- package/dist/audio-extraction/extract-audio.js +28 -15
- package/dist/caches.d.ts +9 -44
- package/dist/convert-audiodata/apply-tonefrequency.js +0 -1
- package/dist/convert-audiodata/combine-audiodata.js +2 -23
- package/dist/convert-audiodata/convert-audiodata.d.ts +1 -5
- package/dist/convert-audiodata/convert-audiodata.js +16 -24
- package/dist/convert-audiodata/wsola.js +1 -1
- package/dist/esm/index.mjs +2681 -2162
- package/dist/extract-frame-and-audio.d.ts +6 -7
- package/dist/extract-frame-and-audio.js +28 -19
- package/dist/get-sink-weak.d.ts +1 -1
- package/dist/get-sink-weak.js +3 -11
- package/dist/get-sink.d.ts +13 -0
- package/dist/get-sink.js +15 -0
- package/dist/get-time-in-seconds.d.ts +10 -0
- package/dist/get-time-in-seconds.js +25 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/is-network-error.d.ts +6 -0
- package/dist/is-network-error.js +17 -0
- package/dist/render-timestamp-range.d.ts +1 -0
- package/dist/render-timestamp-range.js +9 -0
- package/dist/video/media-player.d.ts +28 -7
- package/dist/video/media-player.js +123 -58
- package/dist/video/props.d.ts +1 -0
- package/dist/video/resolve-playback-time.d.ts +8 -0
- package/dist/video/resolve-playback-time.js +22 -0
- package/dist/video/video-for-preview.d.ts +8 -0
- package/dist/video/video-for-preview.js +113 -90
- package/dist/video/video-for-rendering.d.ts +3 -0
- package/dist/video/video-for-rendering.js +58 -25
- package/dist/video/video.js +6 -10
- package/dist/video-extraction/extract-frame-via-broadcast-channel.d.ts +18 -6
- package/dist/video-extraction/extract-frame-via-broadcast-channel.js +21 -7
- package/dist/video-extraction/extract-frame.d.ts +20 -2
- package/dist/video-extraction/extract-frame.js +40 -9
- package/dist/video-extraction/get-frames-since-keyframe.d.ts +5 -3
- package/dist/video-extraction/get-frames-since-keyframe.js +7 -4
- package/dist/video-extraction/keyframe-bank.d.ts +3 -2
- package/dist/video-extraction/keyframe-bank.js +32 -12
- package/dist/video-extraction/keyframe-manager.d.ts +3 -8
- package/dist/video-extraction/keyframe-manager.js +25 -10
- package/package.json +4 -4
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { LogLevel } from 'remotion';
|
|
2
|
-
import type {
|
|
3
|
-
export declare const extractFrameAndAudio: ({ src, timeInSeconds, logLevel, durationInSeconds, playbackRate, includeAudio, includeVideo, loop, audioStreamIndex, }: {
|
|
2
|
+
import type { ExtractFrameViaBroadcastChannelResult } from './video-extraction/extract-frame-via-broadcast-channel';
|
|
3
|
+
export declare const extractFrameAndAudio: ({ src, timeInSeconds, logLevel, durationInSeconds, playbackRate, includeAudio, includeVideo, loop, audioStreamIndex, trimAfter, trimBefore, fps, }: {
|
|
4
4
|
src: string;
|
|
5
5
|
timeInSeconds: number;
|
|
6
6
|
logLevel: LogLevel;
|
|
@@ -10,8 +10,7 @@ export declare const extractFrameAndAudio: ({ src, timeInSeconds, logLevel, dura
|
|
|
10
10
|
includeVideo: boolean;
|
|
11
11
|
loop: boolean;
|
|
12
12
|
audioStreamIndex: number;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
} | "cannot-decode" | "unknown-container-format" | "network-error">;
|
|
13
|
+
trimAfter: number | undefined;
|
|
14
|
+
trimBefore: number | undefined;
|
|
15
|
+
fps: number;
|
|
16
|
+
}) => Promise<ExtractFrameViaBroadcastChannelResult>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { extractAudio } from './audio-extraction/extract-audio';
|
|
2
|
+
import { isNetworkError } from './is-network-error';
|
|
2
3
|
import { extractFrame } from './video-extraction/extract-frame';
|
|
3
|
-
export const extractFrameAndAudio = async ({ src, timeInSeconds, logLevel, durationInSeconds, playbackRate, includeAudio, includeVideo, loop, audioStreamIndex, }) => {
|
|
4
|
+
export const extractFrameAndAudio = async ({ src, timeInSeconds, logLevel, durationInSeconds, playbackRate, includeAudio, includeVideo, loop, audioStreamIndex, trimAfter, trimBefore, fps, }) => {
|
|
4
5
|
try {
|
|
5
6
|
const [frame, audio] = await Promise.all([
|
|
6
7
|
includeVideo
|
|
@@ -9,6 +10,10 @@ export const extractFrameAndAudio = async ({ src, timeInSeconds, logLevel, durat
|
|
|
9
10
|
timeInSeconds,
|
|
10
11
|
logLevel,
|
|
11
12
|
loop,
|
|
13
|
+
trimAfter,
|
|
14
|
+
playbackRate,
|
|
15
|
+
trimBefore,
|
|
16
|
+
fps,
|
|
12
17
|
})
|
|
13
18
|
: null,
|
|
14
19
|
includeAudio
|
|
@@ -20,43 +25,47 @@ export const extractFrameAndAudio = async ({ src, timeInSeconds, logLevel, durat
|
|
|
20
25
|
loop,
|
|
21
26
|
playbackRate,
|
|
22
27
|
audioStreamIndex,
|
|
28
|
+
trimAfter,
|
|
29
|
+
fps,
|
|
30
|
+
trimBefore,
|
|
23
31
|
})
|
|
24
32
|
: null,
|
|
25
33
|
]);
|
|
26
|
-
if (frame === 'cannot-decode') {
|
|
27
|
-
return
|
|
34
|
+
if (frame?.type === 'cannot-decode') {
|
|
35
|
+
return {
|
|
36
|
+
type: 'cannot-decode',
|
|
37
|
+
durationInSeconds: frame.durationInSeconds,
|
|
38
|
+
};
|
|
28
39
|
}
|
|
29
|
-
if (frame === 'unknown-container-format') {
|
|
30
|
-
return 'unknown-container-format';
|
|
40
|
+
if (frame?.type === 'unknown-container-format') {
|
|
41
|
+
return { type: 'unknown-container-format' };
|
|
31
42
|
}
|
|
32
43
|
if (audio === 'unknown-container-format') {
|
|
33
44
|
if (frame !== null) {
|
|
34
|
-
frame?.close();
|
|
45
|
+
frame?.frame?.close();
|
|
35
46
|
}
|
|
36
|
-
return 'unknown-container-format';
|
|
47
|
+
return { type: 'unknown-container-format' };
|
|
37
48
|
}
|
|
38
49
|
if (audio === 'cannot-decode') {
|
|
39
|
-
if (frame !== null) {
|
|
40
|
-
frame?.close();
|
|
50
|
+
if (frame?.type === 'success' && frame.frame !== null) {
|
|
51
|
+
frame?.frame.close();
|
|
41
52
|
}
|
|
42
|
-
return
|
|
53
|
+
return {
|
|
54
|
+
type: 'cannot-decode',
|
|
55
|
+
durationInSeconds: frame?.type === 'success' ? frame.durationInSeconds : null,
|
|
56
|
+
};
|
|
43
57
|
}
|
|
44
58
|
return {
|
|
45
|
-
|
|
59
|
+
type: 'success',
|
|
60
|
+
frame: frame?.frame?.toVideoFrame() ?? null,
|
|
46
61
|
audio: audio?.data ?? null,
|
|
47
62
|
durationInSeconds: audio?.durationInSeconds ?? null,
|
|
48
63
|
};
|
|
49
64
|
}
|
|
50
65
|
catch (err) {
|
|
51
66
|
const error = err;
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
error.message.includes('Failed to fetch') ||
|
|
55
|
-
// Safari
|
|
56
|
-
error.message.includes('Load failed') ||
|
|
57
|
-
// Firefox
|
|
58
|
-
error.message.includes('NetworkError when attempting to fetch resource')) {
|
|
59
|
-
return 'network-error';
|
|
67
|
+
if (isNetworkError(error)) {
|
|
68
|
+
return { type: 'network-error' };
|
|
60
69
|
}
|
|
61
70
|
throw err;
|
|
62
71
|
}
|
package/dist/get-sink-weak.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { LogLevel } from 'remotion';
|
|
2
2
|
import type { GetSink } from './video-extraction/get-frames-since-keyframe';
|
|
3
3
|
export declare const sinkPromises: Record<string, Promise<GetSink>>;
|
|
4
|
-
export declare const
|
|
4
|
+
export declare const getSink: (src: string, logLevel: LogLevel) => Promise<{
|
|
5
5
|
getVideo: () => Promise<import("./video-extraction/get-frames-since-keyframe").VideoSinkResult>;
|
|
6
6
|
getAudio: (index: number) => Promise<import("./video-extraction/get-frames-since-keyframe").AudioSinkResult>;
|
|
7
7
|
actualMatroskaTimestamps: {
|
package/dist/get-sink-weak.js
CHANGED
|
@@ -1,23 +1,15 @@
|
|
|
1
1
|
import { Internals } from 'remotion';
|
|
2
2
|
import { getSinks } from './video-extraction/get-frames-since-keyframe';
|
|
3
3
|
export const sinkPromises = {};
|
|
4
|
-
export const
|
|
4
|
+
export const getSink = (src, logLevel) => {
|
|
5
5
|
let promise = sinkPromises[src];
|
|
6
6
|
if (!promise) {
|
|
7
|
-
promise = getSinks(src);
|
|
8
|
-
sinkPromises[src] = promise;
|
|
9
|
-
}
|
|
10
|
-
let awaited = await promise;
|
|
11
|
-
let deferredValue = awaited.deref();
|
|
12
|
-
if (!deferredValue) {
|
|
13
7
|
Internals.Log.verbose({
|
|
14
8
|
logLevel,
|
|
15
9
|
tag: '@remotion/media',
|
|
16
|
-
}, `Sink for ${src} was
|
|
10
|
+
}, `Sink for ${src} was not found, creating new sink`);
|
|
17
11
|
promise = getSinks(src);
|
|
18
12
|
sinkPromises[src] = promise;
|
|
19
|
-
awaited = await promise;
|
|
20
|
-
deferredValue = awaited.deref();
|
|
21
13
|
}
|
|
22
|
-
return
|
|
14
|
+
return promise;
|
|
23
15
|
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { LogLevel } from 'remotion';
|
|
2
|
+
import type { GetSink } from './video-extraction/get-frames-since-keyframe';
|
|
3
|
+
export declare const sinkPromises: Record<string, Promise<GetSink>>;
|
|
4
|
+
export declare const getSink: (src: string, logLevel: LogLevel) => Promise<{
|
|
5
|
+
getVideo: () => Promise<import("./video-extraction/get-frames-since-keyframe").VideoSinkResult>;
|
|
6
|
+
getAudio: (index: number) => Promise<import("./video-extraction/get-frames-since-keyframe").AudioSinkResult>;
|
|
7
|
+
actualMatroskaTimestamps: {
|
|
8
|
+
observeTimestamp: (startTime: number) => void;
|
|
9
|
+
getRealTimestamp: (observedTimestamp: number) => number | null;
|
|
10
|
+
};
|
|
11
|
+
isMatroska: boolean;
|
|
12
|
+
getDuration: () => Promise<number>;
|
|
13
|
+
}>;
|
package/dist/get-sink.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
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
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const getTimeInSeconds: ({ loop, mediaDurationInSeconds, unloopedTimeInSeconds, src, trimAfter, trimBefore, fps, playbackRate, }: {
|
|
2
|
+
loop: boolean;
|
|
3
|
+
mediaDurationInSeconds: number | null;
|
|
4
|
+
unloopedTimeInSeconds: number;
|
|
5
|
+
src: string;
|
|
6
|
+
trimAfter: number | undefined;
|
|
7
|
+
trimBefore: number | undefined;
|
|
8
|
+
playbackRate: number;
|
|
9
|
+
fps: number;
|
|
10
|
+
}) => number | null;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Internals } from 'remotion';
|
|
2
|
+
export const getTimeInSeconds = ({ loop, mediaDurationInSeconds, unloopedTimeInSeconds, src, trimAfter, trimBefore, fps, playbackRate, }) => {
|
|
3
|
+
if (mediaDurationInSeconds === null && loop) {
|
|
4
|
+
throw new Error(`Could not determine duration of ${src}, but "loop" was set.`);
|
|
5
|
+
}
|
|
6
|
+
const loopDuration = loop
|
|
7
|
+
? Internals.calculateLoopDuration({
|
|
8
|
+
trimAfter,
|
|
9
|
+
mediaDurationInFrames: mediaDurationInSeconds * fps,
|
|
10
|
+
// Playback rate was already specified before
|
|
11
|
+
playbackRate: 1,
|
|
12
|
+
trimBefore,
|
|
13
|
+
}) / fps
|
|
14
|
+
: Infinity;
|
|
15
|
+
const timeInSeconds = (unloopedTimeInSeconds * playbackRate) % loopDuration;
|
|
16
|
+
if ((trimAfter ?? null) !== null) {
|
|
17
|
+
if (!loop) {
|
|
18
|
+
const time = (trimAfter - (trimBefore ?? 0)) / fps;
|
|
19
|
+
if (timeInSeconds >= time) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return timeInSeconds + (trimBefore ?? 0) / fps;
|
|
25
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export declare const experimental_Audio: import("react").FC<import(".").AudioPro
|
|
|
8
8
|
* @deprecated Now just `Video`
|
|
9
9
|
*/
|
|
10
10
|
export declare const experimental_Video: import("react").FC<import(".").VideoProps>;
|
|
11
|
+
export { AudioForPreview } from './audio/audio-for-preview';
|
|
11
12
|
export { AudioProps, FallbackHtml5AudioProps } from './audio/props';
|
|
12
13
|
export { VideoProps } from './video/props';
|
|
13
14
|
export { Audio, Video };
|
package/dist/index.js
CHANGED
|
@@ -0,0 +1,17 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const renderTimestampRange: (timestamps: number[]) => string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const renderTimestampRange = (timestamps) => {
|
|
2
|
+
if (timestamps.length === 0) {
|
|
3
|
+
return '(none)';
|
|
4
|
+
}
|
|
5
|
+
if (timestamps.length === 1) {
|
|
6
|
+
return timestamps[0].toFixed(3);
|
|
7
|
+
}
|
|
8
|
+
return `${timestamps[0].toFixed(3)}...${timestamps[timestamps.length - 1].toFixed(3)}`;
|
|
9
|
+
};
|
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
import type { LogLevel } from 'remotion';
|
|
2
2
|
export declare const SEEK_THRESHOLD = 0.05;
|
|
3
|
+
export type MediaPlayerInitResult = {
|
|
4
|
+
type: 'success';
|
|
5
|
+
} | {
|
|
6
|
+
type: 'unknown-container-format';
|
|
7
|
+
} | {
|
|
8
|
+
type: 'cannot-decode';
|
|
9
|
+
} | {
|
|
10
|
+
type: 'network-error';
|
|
11
|
+
} | {
|
|
12
|
+
type: 'no-tracks';
|
|
13
|
+
};
|
|
3
14
|
export declare class MediaPlayer {
|
|
4
15
|
private canvas;
|
|
5
16
|
private context;
|
|
6
17
|
private src;
|
|
7
18
|
private logLevel;
|
|
8
19
|
private playbackRate;
|
|
20
|
+
private audioStreamIndex;
|
|
9
21
|
private canvasSink;
|
|
10
22
|
private videoFrameIterator;
|
|
11
23
|
private nextFrame;
|
|
@@ -17,8 +29,12 @@ export declare class MediaPlayer {
|
|
|
17
29
|
private audioSyncAnchor;
|
|
18
30
|
private playing;
|
|
19
31
|
private muted;
|
|
32
|
+
private loop;
|
|
33
|
+
private trimBeforeSeconds;
|
|
34
|
+
private trimAfterSeconds;
|
|
20
35
|
private animationFrameId;
|
|
21
36
|
private videoAsyncId;
|
|
37
|
+
private audioAsyncId;
|
|
22
38
|
private initialized;
|
|
23
39
|
private totalDuration;
|
|
24
40
|
private isBuffering;
|
|
@@ -27,17 +43,22 @@ export declare class MediaPlayer {
|
|
|
27
43
|
private audioIteratorStarted;
|
|
28
44
|
private readonly HEALTHY_BUFER_THRESHOLD_SECONDS;
|
|
29
45
|
private onVideoFrameCallback?;
|
|
30
|
-
constructor({ canvas, src, logLevel, sharedAudioContext, }: {
|
|
31
|
-
canvas: HTMLCanvasElement;
|
|
46
|
+
constructor({ canvas, src, logLevel, sharedAudioContext, loop, trimBeforeSeconds, trimAfterSeconds, playbackRate, audioStreamIndex, }: {
|
|
47
|
+
canvas: HTMLCanvasElement | null;
|
|
32
48
|
src: string;
|
|
33
49
|
logLevel: LogLevel;
|
|
34
50
|
sharedAudioContext: AudioContext;
|
|
51
|
+
loop: boolean;
|
|
52
|
+
trimBeforeSeconds: number | undefined;
|
|
53
|
+
trimAfterSeconds: number | undefined;
|
|
54
|
+
playbackRate: number;
|
|
55
|
+
audioStreamIndex: number;
|
|
35
56
|
});
|
|
36
57
|
private input;
|
|
37
58
|
private isReady;
|
|
38
59
|
private hasAudio;
|
|
39
60
|
private isCurrentlyBuffering;
|
|
40
|
-
initialize(
|
|
61
|
+
initialize(startTimeUnresolved: number): Promise<MediaPlayerInitResult>;
|
|
41
62
|
private cleanupAudioQueue;
|
|
42
63
|
private cleanAudioIteratorAndNodes;
|
|
43
64
|
seekTo(time: number): Promise<void>;
|
|
@@ -45,13 +66,13 @@ export declare class MediaPlayer {
|
|
|
45
66
|
pause(): void;
|
|
46
67
|
setMuted(muted: boolean): void;
|
|
47
68
|
setVolume(volume: number): void;
|
|
48
|
-
setPlaybackRate(rate: number):
|
|
69
|
+
setPlaybackRate(rate: number): void;
|
|
70
|
+
setLoop(loop: boolean): void;
|
|
49
71
|
dispose(): void;
|
|
50
72
|
private getPlaybackTime;
|
|
51
|
-
private getAdjustedTimestamp;
|
|
52
73
|
private scheduleAudioChunk;
|
|
53
|
-
onBufferingChange(callback: (isBuffering: boolean) => void): void;
|
|
54
|
-
onVideoFrame(callback: (frame: CanvasImageSource) => void): void;
|
|
74
|
+
onBufferingChange(callback: (isBuffering: boolean) => void): () => void;
|
|
75
|
+
onVideoFrame(callback: (frame: CanvasImageSource) => void): () => void;
|
|
55
76
|
private canRenderVideo;
|
|
56
77
|
private startRenderLoop;
|
|
57
78
|
private stopRenderLoop;
|