@remotion/media 4.0.355 → 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.
Files changed (59) hide show
  1. package/dist/audio/audio-for-preview.d.ts +30 -0
  2. package/dist/audio/audio-for-preview.js +213 -0
  3. package/dist/audio/audio-for-rendering.js +63 -12
  4. package/dist/audio/audio.js +8 -50
  5. package/dist/audio/props.d.ts +12 -3
  6. package/dist/audio-extraction/audio-cache.d.ts +1 -1
  7. package/dist/audio-extraction/audio-cache.js +5 -1
  8. package/dist/audio-extraction/audio-iterator.d.ts +7 -3
  9. package/dist/audio-extraction/audio-iterator.js +35 -12
  10. package/dist/audio-extraction/audio-manager.d.ts +10 -38
  11. package/dist/audio-extraction/audio-manager.js +40 -11
  12. package/dist/audio-extraction/extract-audio.d.ts +11 -3
  13. package/dist/audio-extraction/extract-audio.js +37 -17
  14. package/dist/caches.d.ts +11 -45
  15. package/dist/convert-audiodata/apply-tonefrequency.d.ts +2 -0
  16. package/dist/convert-audiodata/apply-tonefrequency.js +43 -0
  17. package/dist/convert-audiodata/combine-audiodata.js +2 -23
  18. package/dist/convert-audiodata/convert-audiodata.d.ts +1 -5
  19. package/dist/convert-audiodata/convert-audiodata.js +16 -24
  20. package/dist/convert-audiodata/wsola.d.ts +13 -0
  21. package/dist/convert-audiodata/wsola.js +197 -0
  22. package/dist/esm/index.mjs +2265 -589
  23. package/dist/extract-frame-and-audio.d.ts +7 -7
  24. package/dist/extract-frame-and-audio.js +69 -26
  25. package/dist/get-sink-weak.d.ts +3 -8
  26. package/dist/get-sink-weak.js +3 -11
  27. package/dist/get-sink.d.ts +13 -0
  28. package/dist/get-sink.js +15 -0
  29. package/dist/get-time-in-seconds.d.ts +10 -0
  30. package/dist/get-time-in-seconds.js +25 -0
  31. package/dist/index.d.ts +13 -3
  32. package/dist/index.js +12 -2
  33. package/dist/is-network-error.d.ts +6 -0
  34. package/dist/is-network-error.js +17 -0
  35. package/dist/render-timestamp-range.d.ts +1 -0
  36. package/dist/render-timestamp-range.js +9 -0
  37. package/dist/video/media-player.d.ts +91 -0
  38. package/dist/video/media-player.js +484 -0
  39. package/dist/video/props.d.ts +37 -18
  40. package/dist/video/resolve-playback-time.d.ts +8 -0
  41. package/dist/video/resolve-playback-time.js +22 -0
  42. package/dist/video/timeout-utils.d.ts +2 -0
  43. package/dist/video/timeout-utils.js +18 -0
  44. package/dist/video/video-for-preview.d.ts +25 -0
  45. package/dist/video/video-for-preview.js +241 -0
  46. package/dist/video/video-for-rendering.d.ts +26 -2
  47. package/dist/video/video-for-rendering.js +95 -19
  48. package/dist/video/video.js +13 -18
  49. package/dist/video-extraction/extract-frame-via-broadcast-channel.d.ts +19 -6
  50. package/dist/video-extraction/extract-frame-via-broadcast-channel.js +67 -4
  51. package/dist/video-extraction/extract-frame.d.ts +21 -2
  52. package/dist/video-extraction/extract-frame.js +46 -9
  53. package/dist/video-extraction/get-frames-since-keyframe.d.ts +17 -10
  54. package/dist/video-extraction/get-frames-since-keyframe.js +77 -21
  55. package/dist/video-extraction/keyframe-bank.d.ts +3 -2
  56. package/dist/video-extraction/keyframe-bank.js +32 -12
  57. package/dist/video-extraction/keyframe-manager.d.ts +3 -8
  58. package/dist/video-extraction/keyframe-manager.js +25 -10
  59. package/package.json +4 -4
@@ -1,6 +1,6 @@
1
1
  import type { LogLevel } from 'remotion';
2
- import type { PcmS16AudioData } from './convert-audiodata/convert-audiodata';
3
- export declare const extractFrameAndAudio: ({ src, timeInSeconds, logLevel, durationInSeconds, playbackRate, includeAudio, includeVideo, loop, }: {
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;
@@ -9,8 +9,8 @@ export declare const extractFrameAndAudio: ({ src, timeInSeconds, logLevel, dura
9
9
  includeAudio: boolean;
10
10
  includeVideo: boolean;
11
11
  loop: boolean;
12
- }) => Promise<{
13
- frame: VideoFrame | null;
14
- audio: PcmS16AudioData | null;
15
- durationInSeconds: number | null;
16
- }>;
12
+ audioStreamIndex: number;
13
+ trimAfter: number | undefined;
14
+ trimBefore: number | undefined;
15
+ fps: number;
16
+ }) => Promise<ExtractFrameViaBroadcastChannelResult>;
@@ -1,29 +1,72 @@
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, }) => {
4
- const [frame, audio] = await Promise.all([
5
- includeVideo
6
- ? extractFrame({
7
- src,
8
- timeInSeconds,
9
- logLevel,
10
- loop,
11
- })
12
- : null,
13
- includeAudio
14
- ? extractAudio({
15
- src,
16
- timeInSeconds,
17
- durationInSeconds,
18
- logLevel,
19
- loop,
20
- playbackRate,
21
- })
22
- : null,
23
- ]);
24
- return {
25
- frame: frame?.toVideoFrame() ?? null,
26
- audio: audio?.data ?? null,
27
- durationInSeconds: audio?.durationInSeconds ?? null,
28
- };
4
+ export const extractFrameAndAudio = async ({ src, timeInSeconds, logLevel, durationInSeconds, playbackRate, includeAudio, includeVideo, loop, audioStreamIndex, trimAfter, trimBefore, fps, }) => {
5
+ try {
6
+ const [frame, audio] = await Promise.all([
7
+ includeVideo
8
+ ? extractFrame({
9
+ src,
10
+ timeInSeconds,
11
+ logLevel,
12
+ loop,
13
+ trimAfter,
14
+ playbackRate,
15
+ trimBefore,
16
+ fps,
17
+ })
18
+ : null,
19
+ includeAudio
20
+ ? extractAudio({
21
+ src,
22
+ timeInSeconds,
23
+ durationInSeconds,
24
+ logLevel,
25
+ loop,
26
+ playbackRate,
27
+ audioStreamIndex,
28
+ trimAfter,
29
+ fps,
30
+ trimBefore,
31
+ })
32
+ : null,
33
+ ]);
34
+ if (frame?.type === 'cannot-decode') {
35
+ return {
36
+ type: 'cannot-decode',
37
+ durationInSeconds: frame.durationInSeconds,
38
+ };
39
+ }
40
+ if (frame?.type === 'unknown-container-format') {
41
+ return { type: 'unknown-container-format' };
42
+ }
43
+ if (audio === 'unknown-container-format') {
44
+ if (frame !== null) {
45
+ frame?.frame?.close();
46
+ }
47
+ return { type: 'unknown-container-format' };
48
+ }
49
+ if (audio === 'cannot-decode') {
50
+ if (frame?.type === 'success' && frame.frame !== null) {
51
+ frame?.frame.close();
52
+ }
53
+ return {
54
+ type: 'cannot-decode',
55
+ durationInSeconds: frame?.type === 'success' ? frame.durationInSeconds : null,
56
+ };
57
+ }
58
+ return {
59
+ type: 'success',
60
+ frame: frame?.frame?.toVideoFrame() ?? null,
61
+ audio: audio?.data ?? null,
62
+ durationInSeconds: audio?.durationInSeconds ?? null,
63
+ };
64
+ }
65
+ catch (err) {
66
+ const error = err;
67
+ if (isNetworkError(error)) {
68
+ return { type: 'network-error' };
69
+ }
70
+ throw err;
71
+ }
29
72
  };
@@ -1,14 +1,9 @@
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 getSinkWeak: (src: string, logLevel: LogLevel) => Promise<{
5
- video: {
6
- sampleSink: import("mediabunny").VideoSampleSink;
7
- packetSink: import("mediabunny").EncodedPacketSink;
8
- } | null;
9
- audio: {
10
- sampleSink: import("mediabunny").AudioSampleSink;
11
- } | null;
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>;
12
7
  actualMatroskaTimestamps: {
13
8
  observeTimestamp: (startTime: number) => void;
14
9
  getRealTimestamp: (observedTimestamp: number) => number | null;
@@ -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 getSinkWeak = async (src, logLevel) => {
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 garbage collected, creating new sink`);
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 deferredValue;
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
+ }>;
@@ -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
@@ -1,4 +1,14 @@
1
- export { Audio as experimental_Audio } from './audio/audio';
2
- export { AudioProps } from './audio/props';
1
+ import { Audio } from './audio/audio';
2
+ import { Video } from './video/video';
3
+ /**
4
+ * @deprecated Now just `Audio`
5
+ */
6
+ export declare const experimental_Audio: import("react").FC<import(".").AudioProps>;
7
+ /**
8
+ * @deprecated Now just `Video`
9
+ */
10
+ export declare const experimental_Video: import("react").FC<import(".").VideoProps>;
11
+ export { AudioForPreview } from './audio/audio-for-preview';
12
+ export { AudioProps, FallbackHtml5AudioProps } from './audio/props';
3
13
  export { VideoProps } from './video/props';
4
- export { Video as experimental_Video } from './video/video';
14
+ export { Audio, Video };
package/dist/index.js CHANGED
@@ -1,2 +1,12 @@
1
- export { Audio as experimental_Audio } from './audio/audio';
2
- export { Video as experimental_Video } from './video/video';
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 };
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Utility to check if error is network error
3
+ * @param error
4
+ * @returns
5
+ */
6
+ export declare function isNetworkError(error: Error): boolean;
@@ -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
+ };
@@ -0,0 +1,91 @@
1
+ import type { LogLevel } from 'remotion';
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
+ };
14
+ export declare class MediaPlayer {
15
+ private canvas;
16
+ private context;
17
+ private src;
18
+ private logLevel;
19
+ private playbackRate;
20
+ private audioStreamIndex;
21
+ private canvasSink;
22
+ private videoFrameIterator;
23
+ private nextFrame;
24
+ private audioSink;
25
+ private audioBufferIterator;
26
+ private queuedAudioNodes;
27
+ private gainNode;
28
+ private sharedAudioContext;
29
+ private audioSyncAnchor;
30
+ private playing;
31
+ private muted;
32
+ private loop;
33
+ private trimBeforeSeconds;
34
+ private trimAfterSeconds;
35
+ private animationFrameId;
36
+ private videoAsyncId;
37
+ private audioAsyncId;
38
+ private initialized;
39
+ private totalDuration;
40
+ private isBuffering;
41
+ private onBufferingChangeCallback?;
42
+ private audioBufferHealth;
43
+ private audioIteratorStarted;
44
+ private readonly HEALTHY_BUFER_THRESHOLD_SECONDS;
45
+ private onVideoFrameCallback?;
46
+ constructor({ canvas, src, logLevel, sharedAudioContext, loop, trimBeforeSeconds, trimAfterSeconds, playbackRate, audioStreamIndex, }: {
47
+ canvas: HTMLCanvasElement | null;
48
+ src: string;
49
+ logLevel: LogLevel;
50
+ sharedAudioContext: AudioContext;
51
+ loop: boolean;
52
+ trimBeforeSeconds: number | undefined;
53
+ trimAfterSeconds: number | undefined;
54
+ playbackRate: number;
55
+ audioStreamIndex: number;
56
+ });
57
+ private input;
58
+ private isReady;
59
+ private hasAudio;
60
+ private isCurrentlyBuffering;
61
+ initialize(startTimeUnresolved: number): Promise<MediaPlayerInitResult>;
62
+ private cleanupAudioQueue;
63
+ private cleanAudioIteratorAndNodes;
64
+ seekTo(time: number): Promise<void>;
65
+ play(): Promise<void>;
66
+ pause(): void;
67
+ setMuted(muted: boolean): void;
68
+ setVolume(volume: number): void;
69
+ setPlaybackRate(rate: number): void;
70
+ setLoop(loop: boolean): void;
71
+ dispose(): void;
72
+ private getPlaybackTime;
73
+ private scheduleAudioChunk;
74
+ onBufferingChange(callback: (isBuffering: boolean) => void): () => void;
75
+ onVideoFrame(callback: (frame: CanvasImageSource) => void): () => void;
76
+ private canRenderVideo;
77
+ private startRenderLoop;
78
+ private stopRenderLoop;
79
+ private render;
80
+ private shouldRenderFrame;
81
+ private drawCurrentFrame;
82
+ private startAudioIterator;
83
+ private startVideoIterator;
84
+ private updateNextFrame;
85
+ private bufferingStartedAtMs;
86
+ private minBufferingTimeoutMs;
87
+ private setBufferingState;
88
+ private maybeResumeFromBuffering;
89
+ private maybeForceResumeFromBuffering;
90
+ private runAudioIterator;
91
+ }