@remotion/media 4.0.429 → 4.0.430

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 (55) hide show
  1. package/dist/audio/allow-wait.js +15 -0
  2. package/dist/audio/audio-for-preview.d.ts +0 -1
  3. package/dist/audio/audio-for-preview.js +304 -0
  4. package/dist/audio/audio-for-rendering.js +194 -0
  5. package/dist/audio/audio-preview-iterator.d.ts +4 -2
  6. package/dist/audio/audio-preview-iterator.js +176 -0
  7. package/dist/audio/audio.js +20 -0
  8. package/dist/audio/props.js +1 -0
  9. package/dist/audio-extraction/audio-cache.js +66 -0
  10. package/dist/audio-extraction/audio-iterator.js +132 -0
  11. package/dist/audio-extraction/audio-manager.js +113 -0
  12. package/dist/audio-extraction/extract-audio.js +132 -0
  13. package/dist/audio-iterator-manager.d.ts +10 -9
  14. package/dist/audio-iterator-manager.js +228 -0
  15. package/dist/browser-can-use-webgl2.js +13 -0
  16. package/dist/caches.js +61 -0
  17. package/dist/calculate-playbacktime.js +4 -0
  18. package/dist/convert-audiodata/apply-volume.js +17 -0
  19. package/dist/convert-audiodata/combine-audiodata.js +23 -0
  20. package/dist/convert-audiodata/convert-audiodata.js +73 -0
  21. package/dist/convert-audiodata/resample-audiodata.js +94 -0
  22. package/dist/debug-overlay/preview-overlay.d.ts +9 -7
  23. package/dist/debug-overlay/preview-overlay.js +42 -0
  24. package/dist/esm/index.mjs +384 -13811
  25. package/dist/extract-frame-and-audio.js +101 -0
  26. package/dist/get-sink.js +15 -0
  27. package/dist/get-time-in-seconds.js +40 -0
  28. package/dist/helpers/round-to-4-digits.js +4 -0
  29. package/dist/index.js +12 -0
  30. package/dist/is-type-of-error.js +20 -0
  31. package/dist/looped-frame.js +10 -0
  32. package/dist/media-player.d.ts +9 -5
  33. package/dist/media-player.js +431 -0
  34. package/dist/nonce-manager.js +13 -0
  35. package/dist/prewarm-iterator-for-looping.js +56 -0
  36. package/dist/render-timestamp-range.js +9 -0
  37. package/dist/show-in-timeline.js +31 -0
  38. package/dist/use-media-in-timeline.d.ts +1 -1
  39. package/dist/use-media-in-timeline.js +103 -0
  40. package/dist/video/props.js +1 -0
  41. package/dist/video/video-for-preview.js +331 -0
  42. package/dist/video/video-for-rendering.js +263 -0
  43. package/dist/video/video-preview-iterator.js +122 -0
  44. package/dist/video/video.js +35 -0
  45. package/dist/video-extraction/add-broadcast-channel-listener.js +125 -0
  46. package/dist/video-extraction/extract-frame-via-broadcast-channel.js +113 -0
  47. package/dist/video-extraction/extract-frame.js +85 -0
  48. package/dist/video-extraction/get-allocation-size.js +6 -0
  49. package/dist/video-extraction/get-frames-since-keyframe.js +108 -0
  50. package/dist/video-extraction/keyframe-bank.js +159 -0
  51. package/dist/video-extraction/keyframe-manager.js +206 -0
  52. package/dist/video-extraction/remember-actual-matroska-timestamps.js +19 -0
  53. package/dist/video-extraction/rotate-frame.js +34 -0
  54. package/dist/video-iterator-manager.js +109 -0
  55. package/package.json +3 -2
@@ -0,0 +1,101 @@
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
+ };
@@ -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,40 @@
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
+ };
@@ -0,0 +1,4 @@
1
+ // Round to only 4 digits, because WebM has a timescale of 1_000, e.g. framer.webm
2
+ export const roundTo4Digits = (timestamp) => {
3
+ return Math.round(timestamp * 1000) / 1000;
4
+ };
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
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,20 @@
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
+ }
@@ -0,0 +1,10 @@
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
+ };
@@ -1,6 +1,5 @@
1
1
  import type { LogLevel, useBufferState } from 'remotion';
2
2
  import { type AudioIteratorManager } from './audio-iterator-manager';
3
- import type { Nonce } from './nonce-manager';
4
3
  import type { VideoIteratorManager } from './video-iterator-manager';
5
4
  export type MediaPlayerInitResult = {
6
5
  type: 'success';
@@ -33,6 +32,7 @@ export declare class MediaPlayer {
33
32
  private fps;
34
33
  private trimBefore;
35
34
  private trimAfter;
35
+ private durationInFrames;
36
36
  private totalDuration;
37
37
  private debugOverlay;
38
38
  private nonceManager;
@@ -42,7 +42,7 @@ export declare class MediaPlayer {
42
42
  private isPremounting;
43
43
  private isPostmounting;
44
44
  private seekPromiseChain;
45
- constructor({ canvas, src, logLevel, sharedAudioContext, loop, trimBefore, trimAfter, playbackRate, globalPlaybackRate, audioStreamIndex, fps, debugOverlay, bufferState, isPremounting, isPostmounting, onVideoFrameCallback, playing }: {
45
+ constructor({ canvas, src, logLevel, sharedAudioContext, loop, trimBefore, trimAfter, playbackRate, globalPlaybackRate, audioStreamIndex, fps, debugOverlay, bufferState, isPremounting, isPostmounting, durationInFrames, onVideoFrameCallback, playing }: {
46
46
  canvas: HTMLCanvasElement | OffscreenCanvas | null;
47
47
  src: string;
48
48
  logLevel: LogLevel;
@@ -58,6 +58,7 @@ export declare class MediaPlayer {
58
58
  bufferState: ReturnType<typeof useBufferState>;
59
59
  isPremounting: boolean;
60
60
  isPostmounting: boolean;
61
+ durationInFrames: number;
61
62
  onVideoFrameCallback: null | ((frame: CanvasImageSource) => void);
62
63
  playing: boolean;
63
64
  });
@@ -69,27 +70,30 @@ export declare class MediaPlayer {
69
70
  private _initialize;
70
71
  private seekToWithQueue;
71
72
  seekTo(time: number): Promise<void>;
72
- seekToDoNotCallDirectly(newTime: number, nonce: Nonce): Promise<void>;
73
+ private seekToDoNotCallDirectly;
74
+ playAudio(time: number): Promise<void>;
73
75
  play(time: number): Promise<void>;
74
76
  private delayPlaybackHandleIfNotPremounting;
75
77
  pause(): void;
76
78
  setMuted(muted: boolean): void;
77
79
  setVolume(volume: number): void;
80
+ private getTrimmedTime;
78
81
  private updateAfterTrimChange;
79
82
  setTrimBefore(trimBefore: number | undefined, unloopedTimeInSeconds: number): Promise<void>;
80
83
  setTrimAfter(trimAfter: number | undefined, unloopedTimeInSeconds: number): Promise<void>;
81
84
  setDebugOverlay(debugOverlay: boolean): void;
82
85
  private updateAudioTimeAfterPlaybackRateChange;
83
- setPlaybackRate(rate: number): void;
86
+ setPlaybackRate(rate: number, unloopedTimeInSeconds: number): Promise<void>;
84
87
  setGlobalPlaybackRate(rate: number): void;
85
88
  setFps(fps: number): void;
86
89
  setIsPremounting(isPremounting: boolean): void;
87
90
  setIsPostmounting(isPostmounting: boolean): void;
88
91
  setLoop(loop: boolean): void;
92
+ setDurationInFrames(durationInFrames: number): void;
89
93
  dispose(): Promise<void>;
90
94
  private scheduleAudioNode;
91
95
  private getAudioPlaybackTime;
92
- private setPlaybackTime;
96
+ private setAudioPlaybackTime;
93
97
  setVideoFrameCallback(callback: null | ((frame: CanvasImageSource) => void)): void;
94
98
  private drawDebugOverlay;
95
99
  }