@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.
Files changed (63) hide show
  1. package/dist/audio/audio-for-preview.d.ts +1 -0
  2. package/dist/audio/audio-preview-iterator.d.ts +16 -9
  3. package/dist/audio/props.d.ts +1 -0
  4. package/dist/audio-iterator-manager.d.ts +24 -13
  5. package/dist/debug-overlay/preview-overlay.d.ts +24 -14
  6. package/dist/esm/index.mjs +755 -537
  7. package/dist/make-iterator-with-priming.d.ts +6 -0
  8. package/dist/media-player.d.ts +12 -7
  9. package/dist/prewarm-iterator-for-looping.d.ts +3 -2
  10. package/dist/set-global-time-anchor.d.ts +11 -0
  11. package/dist/shared-audio-context-for-media-player.d.ts +8 -0
  12. package/dist/use-common-effects.d.ts +32 -0
  13. package/dist/video/props.d.ts +1 -0
  14. package/dist/video/video-for-preview.d.ts +1 -0
  15. package/package.json +4 -4
  16. package/dist/audio/allow-wait.d.ts +0 -6
  17. package/dist/audio/allow-wait.js +0 -15
  18. package/dist/audio/audio-for-preview.js +0 -304
  19. package/dist/audio/audio-for-rendering.js +0 -194
  20. package/dist/audio/audio-preview-iterator.js +0 -176
  21. package/dist/audio/audio.js +0 -20
  22. package/dist/audio/props.js +0 -1
  23. package/dist/audio-extraction/audio-cache.js +0 -66
  24. package/dist/audio-extraction/audio-iterator.js +0 -132
  25. package/dist/audio-extraction/audio-manager.js +0 -113
  26. package/dist/audio-extraction/extract-audio.js +0 -132
  27. package/dist/audio-iterator-manager.js +0 -228
  28. package/dist/browser-can-use-webgl2.js +0 -13
  29. package/dist/caches.js +0 -61
  30. package/dist/calculate-playbacktime.js +0 -4
  31. package/dist/convert-audiodata/apply-volume.js +0 -17
  32. package/dist/convert-audiodata/combine-audiodata.js +0 -23
  33. package/dist/convert-audiodata/convert-audiodata.js +0 -73
  34. package/dist/convert-audiodata/resample-audiodata.js +0 -94
  35. package/dist/debug-overlay/preview-overlay.js +0 -42
  36. package/dist/extract-frame-and-audio.js +0 -101
  37. package/dist/get-sink.js +0 -15
  38. package/dist/get-time-in-seconds.js +0 -40
  39. package/dist/helpers/round-to-4-digits.js +0 -4
  40. package/dist/index.js +0 -12
  41. package/dist/is-type-of-error.js +0 -20
  42. package/dist/looped-frame.js +0 -10
  43. package/dist/media-player.js +0 -431
  44. package/dist/nonce-manager.js +0 -13
  45. package/dist/prewarm-iterator-for-looping.js +0 -56
  46. package/dist/render-timestamp-range.js +0 -9
  47. package/dist/show-in-timeline.js +0 -31
  48. package/dist/use-media-in-timeline.js +0 -103
  49. package/dist/video/props.js +0 -1
  50. package/dist/video/video-for-preview.js +0 -331
  51. package/dist/video/video-for-rendering.js +0 -263
  52. package/dist/video/video-preview-iterator.js +0 -122
  53. package/dist/video/video.js +0 -35
  54. package/dist/video-extraction/add-broadcast-channel-listener.js +0 -125
  55. package/dist/video-extraction/extract-frame-via-broadcast-channel.js +0 -113
  56. package/dist/video-extraction/extract-frame.js +0 -85
  57. package/dist/video-extraction/get-allocation-size.js +0 -6
  58. package/dist/video-extraction/get-frames-since-keyframe.js +0 -108
  59. package/dist/video-extraction/keyframe-bank.js +0 -159
  60. package/dist/video-extraction/keyframe-manager.js +0 -206
  61. package/dist/video-extraction/remember-actual-matroska-timestamps.js +0 -19
  62. package/dist/video-extraction/rotate-frame.js +0 -34
  63. package/dist/video-iterator-manager.js +0 -109
@@ -0,0 +1,6 @@
1
+ import type { AudioBufferSink, WrappedAudioBuffer } from 'mediabunny';
2
+ export declare const makeIteratorWithPriming: ({ audioSink, timeToSeek, maximumTimestamp, }: {
3
+ audioSink: AudioBufferSink;
4
+ timeToSeek: number;
5
+ maximumTimestamp: number;
6
+ }) => AsyncGenerator<WrappedAudioBuffer, void, unknown>;
@@ -1,5 +1,6 @@
1
1
  import type { LogLevel, useBufferState } from 'remotion';
2
2
  import { type AudioIteratorManager } from './audio-iterator-manager';
3
+ import type { SharedAudioContextForMediaPlayer } from './shared-audio-context-for-media-player';
3
4
  import type { VideoIteratorManager } from './video-iterator-manager';
4
5
  export type MediaPlayerInitResult = {
5
6
  type: 'success';
@@ -26,7 +27,7 @@ export declare class MediaPlayer {
26
27
  private sharedAudioContext;
27
28
  audioIteratorManager: AudioIteratorManager | null;
28
29
  videoIteratorManager: VideoIteratorManager | null;
29
- private audioSyncAnchor;
30
+ private sequenceOffset;
30
31
  private playing;
31
32
  private loop;
32
33
  private fps;
@@ -35,6 +36,7 @@ export declare class MediaPlayer {
35
36
  private durationInFrames;
36
37
  private totalDuration;
37
38
  private debugOverlay;
39
+ private debugAudioScheduling;
38
40
  private nonceManager;
39
41
  private onVideoFrameCallback;
40
42
  private initializationPromise;
@@ -42,11 +44,11 @@ export declare class MediaPlayer {
42
44
  private isPremounting;
43
45
  private isPostmounting;
44
46
  private seekPromiseChain;
45
- constructor({ canvas, src, logLevel, sharedAudioContext, loop, trimBefore, trimAfter, playbackRate, globalPlaybackRate, audioStreamIndex, fps, debugOverlay, bufferState, isPremounting, isPostmounting, durationInFrames, onVideoFrameCallback, playing }: {
47
+ constructor({ canvas, src, logLevel, sharedAudioContext, loop, trimBefore, trimAfter, playbackRate, globalPlaybackRate, audioStreamIndex, fps, debugOverlay, debugAudioScheduling, bufferState, isPremounting, isPostmounting, durationInFrames, onVideoFrameCallback, playing, sequenceOffset }: {
46
48
  canvas: HTMLCanvasElement | OffscreenCanvas | null;
47
49
  src: string;
48
50
  logLevel: LogLevel;
49
- sharedAudioContext: AudioContext | null;
51
+ sharedAudioContext: SharedAudioContextForMediaPlayer | null;
50
52
  loop: boolean;
51
53
  trimBefore: number | undefined;
52
54
  trimAfter: number | undefined;
@@ -55,12 +57,14 @@ export declare class MediaPlayer {
55
57
  audioStreamIndex: number;
56
58
  fps: number;
57
59
  debugOverlay: boolean;
60
+ debugAudioScheduling: boolean;
58
61
  bufferState: ReturnType<typeof useBufferState>;
59
62
  isPremounting: boolean;
60
63
  isPostmounting: boolean;
61
64
  durationInFrames: number;
62
65
  onVideoFrameCallback: null | ((frame: CanvasImageSource) => void);
63
66
  playing: boolean;
67
+ sequenceOffset: number;
64
68
  });
65
69
  private input;
66
70
  private isDisposalError;
@@ -71,8 +75,8 @@ export declare class MediaPlayer {
71
75
  private seekToWithQueue;
72
76
  seekTo(time: number): Promise<void>;
73
77
  private seekToDoNotCallDirectly;
74
- playAudio(time: number): Promise<void>;
75
- play(time: number): Promise<void>;
78
+ playAudio(): void;
79
+ play(): void;
76
80
  private delayPlaybackHandleIfNotPremounting;
77
81
  pause(): void;
78
82
  setMuted(muted: boolean): void;
@@ -82,18 +86,19 @@ export declare class MediaPlayer {
82
86
  setTrimBefore(trimBefore: number | undefined, unloopedTimeInSeconds: number): Promise<void>;
83
87
  setTrimAfter(trimAfter: number | undefined, unloopedTimeInSeconds: number): Promise<void>;
84
88
  setDebugOverlay(debugOverlay: boolean): void;
85
- private updateAudioTimeAfterPlaybackRateChange;
89
+ setDebugAudioScheduling(debugAudioScheduling: boolean): void;
90
+ private rescheduleAudioChunks;
86
91
  setPlaybackRate(rate: number, unloopedTimeInSeconds: number): Promise<void>;
87
92
  setGlobalPlaybackRate(rate: number): void;
88
93
  setFps(fps: number): void;
89
94
  setIsPremounting(isPremounting: boolean): void;
90
95
  setIsPostmounting(isPostmounting: boolean): void;
91
96
  setLoop(loop: boolean): void;
97
+ setSequenceOffset(offset: number): void;
92
98
  setDurationInFrames(durationInFrames: number): void;
93
99
  dispose(): Promise<void>;
94
100
  private scheduleAudioNode;
95
101
  private getAudioPlaybackTime;
96
- private setAudioPlaybackTime;
97
102
  setVideoFrameCallback(callback: null | ((frame: CanvasImageSource) => void)): void;
98
103
  private drawDebugOverlay;
99
104
  }
@@ -8,10 +8,11 @@ export declare const makePrewarmedVideoIteratorCache: (videoSink: CanvasSink) =>
8
8
  };
9
9
  export type PrewarmedVideoIteratorCache = ReturnType<typeof makePrewarmedVideoIteratorCache>;
10
10
  export declare const makePrewarmedAudioIteratorCache: (audioSink: AudioBufferSink) => {
11
- prewarmIteratorForLooping: ({ timeToSeek }: {
11
+ prewarmIteratorForLooping: ({ timeToSeek, maximumTimestamp, }: {
12
12
  timeToSeek: number;
13
+ maximumTimestamp: number;
13
14
  }) => void;
14
- makeIteratorOrUsePrewarmed: (timeToSeek: number) => AsyncGenerator<WrappedAudioBuffer, void, unknown>;
15
+ makeIteratorOrUsePrewarmed: (timeToSeek: number, maximumTimestamp: number) => AsyncGenerator<WrappedAudioBuffer, void, unknown>;
15
16
  destroy: () => void;
16
17
  };
17
18
  export type PrewarmedAudioIteratorCache = ReturnType<typeof makePrewarmedAudioIteratorCache>;
@@ -0,0 +1,11 @@
1
+ export declare const ALLOWED_GLOBAL_TIME_ANCHOR_SHIFT = 0.1;
2
+ export declare const setGlobalTimeAnchor: ({ audioContext, audioSyncAnchor, absoluteTimeInSeconds, globalPlaybackRate, debugAudioScheduling, logLevel, }: {
3
+ audioContext: AudioContext;
4
+ audioSyncAnchor: {
5
+ value: number;
6
+ };
7
+ absoluteTimeInSeconds: number;
8
+ globalPlaybackRate: number;
9
+ debugAudioScheduling: boolean;
10
+ logLevel: "error" | "info" | "trace" | "verbose" | "warn";
11
+ }) => void;
@@ -0,0 +1,8 @@
1
+ import type { ScheduleAudioNodeOptions, ScheduleAudioNodeResult } from 'remotion';
2
+ export type SharedAudioContextForMediaPlayer = {
3
+ audioContext: AudioContext;
4
+ audioSyncAnchor: {
5
+ value: number;
6
+ };
7
+ scheduleAudioNode: (options: ScheduleAudioNodeOptions) => ScheduleAudioNodeResult;
8
+ };
@@ -0,0 +1,32 @@
1
+ import type React from 'react';
2
+ import type { MediaPlayer } from './media-player';
3
+ export declare const useCommonEffects: ({ mediaPlayerRef, mediaPlayerReady, currentTimeRef, playing, isPlayerBuffering, frame, trimBefore, trimAfter, effectiveMuted, userPreferredVolume, playbackRate, globalPlaybackRate, fps, sequenceOffset, loop, debugAudioScheduling, durationInFrames, isPremounting, isPostmounting, currentTime, logLevel, sharedAudioContext, label, }: {
4
+ readonly mediaPlayerRef: React.RefObject<MediaPlayer | null>;
5
+ readonly mediaPlayerReady: boolean;
6
+ readonly currentTimeRef: React.RefObject<number>;
7
+ readonly playing: boolean;
8
+ readonly isPlayerBuffering: boolean;
9
+ readonly frame: number;
10
+ readonly trimBefore: number | undefined;
11
+ readonly trimAfter: number | undefined;
12
+ readonly effectiveMuted: boolean;
13
+ readonly userPreferredVolume: number;
14
+ readonly playbackRate: number;
15
+ readonly globalPlaybackRate: number;
16
+ readonly fps: number;
17
+ readonly sequenceOffset: number;
18
+ readonly loop: boolean;
19
+ readonly debugAudioScheduling: boolean;
20
+ readonly durationInFrames: number;
21
+ readonly isPremounting: boolean;
22
+ readonly isPostmounting: boolean;
23
+ readonly currentTime: number;
24
+ readonly logLevel: "error" | "info" | "trace" | "verbose" | "warn";
25
+ readonly sharedAudioContext: {
26
+ readonly audioContext: AudioContext | null;
27
+ readonly audioSyncAnchor: {
28
+ value: number;
29
+ };
30
+ } | null;
31
+ readonly label: string;
32
+ }) => void;
@@ -45,6 +45,7 @@ type OptionalVideoProps = {
45
45
  toneFrequency: number;
46
46
  showInTimeline: boolean;
47
47
  debugOverlay: boolean;
48
+ debugAudioScheduling: boolean;
48
49
  headless: boolean;
49
50
  onError: MediaOnError | undefined;
50
51
  };
@@ -22,6 +22,7 @@ type VideoForPreviewProps = {
22
22
  readonly fallbackOffthreadVideoProps: FallbackOffthreadVideoProps;
23
23
  readonly audioStreamIndex: number;
24
24
  readonly debugOverlay: boolean;
25
+ readonly debugAudioScheduling: boolean;
25
26
  readonly headless: boolean;
26
27
  readonly onError: MediaOnError | undefined;
27
28
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remotion/media",
3
- "version": "4.0.430",
3
+ "version": "4.0.432",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "module": "dist/esm/index.mjs",
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "mediabunny": "1.35.1",
26
- "remotion": "4.0.429",
26
+ "remotion": "4.0.432",
27
27
  "zod": "4.3.6"
28
28
  },
29
29
  "peerDependencies": {
@@ -31,14 +31,14 @@
31
31
  "react-dom": ">=16.8.0"
32
32
  },
33
33
  "devDependencies": {
34
- "@remotion/eslint-config-internal": "4.0.429",
34
+ "@remotion/eslint-config-internal": "4.0.432",
35
35
  "@vitest/browser-webdriverio": "4.0.9",
36
36
  "eslint": "9.19.0",
37
37
  "react": "19.2.3",
38
38
  "react-dom": "19.2.3",
39
39
  "vitest": "4.0.9",
40
40
  "webdriverio": "9.19.2",
41
- "@typescript/native-preview": "7.0.0-dev.20260217.1"
41
+ "@typescript/native-preview": "7.0.0-dev.20260301.1"
42
42
  },
43
43
  "keywords": [],
44
44
  "publishConfig": {
@@ -1,6 +0,0 @@
1
- import type { WrappedAudioBuffer } from 'mediabunny';
2
- export type AllowWait = {
3
- type: 'allow-wait';
4
- waitCallback: () => () => void;
5
- };
6
- export declare const allowWaitRoutine: (next: Promise<IteratorResult<WrappedAudioBuffer, void>>, waitFn: AllowWait) => Promise<IteratorResult<WrappedAudioBuffer, void>>;
@@ -1,15 +0,0 @@
1
- export const allowWaitRoutine = async (next, waitFn) => {
2
- const result = await Promise.race([
3
- next,
4
- new Promise((resolve) => {
5
- Promise.resolve().then(() => resolve());
6
- }),
7
- ]);
8
- if (!result) {
9
- const unblock = waitFn.waitCallback();
10
- const newRes = await next;
11
- unblock();
12
- return newRes;
13
- }
14
- return result;
15
- };
@@ -1,304 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { useContext, useEffect, useLayoutEffect, useMemo, useRef, useState, } from 'react';
3
- import { Internals, Audio as RemotionAudio, useBufferState, useCurrentFrame, useVideoConfig, } from 'remotion';
4
- import { getTimeInSeconds } from '../get-time-in-seconds';
5
- import { MediaPlayer } from '../media-player';
6
- import { useLoopDisplay } from '../show-in-timeline';
7
- import { useMediaInTimeline } from '../use-media-in-timeline';
8
- const { useUnsafeVideoConfig, Timeline, SharedAudioContext, useMediaMutedState, useMediaVolumeState, useFrameForVolumeProp, evaluateVolume, warnAboutTooHighVolume, usePreload, SequenceContext, } = Internals;
9
- const AudioForPreviewAssertedShowing = ({ src, playbackRate, logLevel, muted, volume, loopVolumeCurveBehavior, loop, trimAfter, trimBefore, name, showInTimeline, stack, disallowFallbackToHtml5Audio, toneFrequency, audioStreamIndex, fallbackHtml5AudioProps, }) => {
10
- const videoConfig = useUnsafeVideoConfig();
11
- const frame = useCurrentFrame();
12
- const mediaPlayerRef = useRef(null);
13
- const initialTrimBeforeRef = useRef(trimBefore);
14
- const initialTrimAfterRef = useRef(trimAfter);
15
- const [mediaPlayerReady, setMediaPlayerReady] = useState(false);
16
- const [shouldFallbackToNativeAudio, setShouldFallbackToNativeAudio] = useState(false);
17
- const [playing] = Timeline.usePlayingState();
18
- const timelineContext = useContext(Internals.TimelineContext);
19
- const globalPlaybackRate = timelineContext.playbackRate;
20
- const sharedAudioContext = useContext(SharedAudioContext);
21
- const buffer = useBufferState();
22
- const [mediaMuted] = useMediaMutedState();
23
- const [mediaVolume] = useMediaVolumeState();
24
- const [mediaDurationInSeconds, setMediaDurationInSeconds] = useState(null);
25
- const volumePropFrame = useFrameForVolumeProp(loopVolumeCurveBehavior ?? 'repeat');
26
- const userPreferredVolume = evaluateVolume({
27
- frame: volumePropFrame,
28
- volume,
29
- mediaVolume,
30
- });
31
- warnAboutTooHighVolume(userPreferredVolume);
32
- if (!videoConfig) {
33
- throw new Error('No video config found');
34
- }
35
- if (!src) {
36
- throw new TypeError('No `src` was passed to <NewAudioForPreview>.');
37
- }
38
- const currentTime = frame / videoConfig.fps;
39
- const currentTimeRef = useRef(currentTime);
40
- currentTimeRef.current = currentTime;
41
- const preloadedSrc = usePreload(src);
42
- const parentSequence = useContext(SequenceContext);
43
- const isPremounting = Boolean(parentSequence?.premounting);
44
- const isPostmounting = Boolean(parentSequence?.postmounting);
45
- const loopDisplay = useLoopDisplay({
46
- loop,
47
- mediaDurationInSeconds,
48
- playbackRate,
49
- trimAfter,
50
- trimBefore,
51
- });
52
- useMediaInTimeline({
53
- volume,
54
- mediaVolume,
55
- mediaType: 'audio',
56
- src,
57
- playbackRate,
58
- displayName: name ?? null,
59
- stack,
60
- showInTimeline,
61
- premountDisplay: parentSequence?.premountDisplay ?? null,
62
- postmountDisplay: parentSequence?.postmountDisplay ?? null,
63
- loopDisplay,
64
- trimAfter,
65
- trimBefore,
66
- });
67
- const bufferingContext = useContext(Internals.BufferingContextReact);
68
- if (!bufferingContext) {
69
- throw new Error('useMediaPlayback must be used inside a <BufferingContext>');
70
- }
71
- const isPlayerBuffering = Internals.useIsPlayerBuffering(bufferingContext);
72
- const initialPlaying = useRef(playing && !isPlayerBuffering);
73
- const initialIsPremounting = useRef(isPremounting);
74
- const initialIsPostmounting = useRef(isPostmounting);
75
- const initialGlobalPlaybackRate = useRef(globalPlaybackRate);
76
- const initialPlaybackRate = useRef(playbackRate);
77
- useEffect(() => {
78
- if (!sharedAudioContext)
79
- return;
80
- if (!sharedAudioContext.audioContext)
81
- return;
82
- try {
83
- const player = new MediaPlayer({
84
- src: preloadedSrc,
85
- logLevel,
86
- sharedAudioContext: sharedAudioContext.audioContext,
87
- loop,
88
- trimAfter: initialTrimAfterRef.current,
89
- trimBefore: initialTrimBeforeRef.current,
90
- fps: videoConfig.fps,
91
- canvas: null,
92
- playbackRate: initialPlaybackRate.current,
93
- audioStreamIndex: audioStreamIndex ?? 0,
94
- debugOverlay: false,
95
- bufferState: buffer,
96
- isPostmounting: initialIsPostmounting.current,
97
- isPremounting: initialIsPremounting.current,
98
- globalPlaybackRate: initialGlobalPlaybackRate.current,
99
- onVideoFrameCallback: null,
100
- playing: initialPlaying.current,
101
- });
102
- mediaPlayerRef.current = player;
103
- player
104
- .initialize(currentTimeRef.current)
105
- .then((result) => {
106
- if (result.type === 'disposed') {
107
- return;
108
- }
109
- if (result.type === 'unknown-container-format') {
110
- if (disallowFallbackToHtml5Audio) {
111
- throw new Error(`Unknown container format ${preloadedSrc}, and 'disallowFallbackToHtml5Audio' was set.`);
112
- }
113
- Internals.Log.warn({ logLevel, tag: '@remotion/media' }, `Unknown container format for ${preloadedSrc} (Supported formats: https://www.remotion.dev/docs/mediabunny/formats), falling back to <Html5Audio>`);
114
- setShouldFallbackToNativeAudio(true);
115
- return;
116
- }
117
- if (result.type === 'network-error') {
118
- if (disallowFallbackToHtml5Audio) {
119
- throw new Error(`Network error fetching ${preloadedSrc}, and 'disallowFallbackToHtml5Audio' was set.`);
120
- }
121
- Internals.Log.warn({ logLevel, tag: '@remotion/media' }, `Network error fetching ${preloadedSrc}, falling back to <Html5Audio>`);
122
- setShouldFallbackToNativeAudio(true);
123
- return;
124
- }
125
- if (result.type === 'cannot-decode') {
126
- if (disallowFallbackToHtml5Audio) {
127
- throw new Error(`Cannot decode ${preloadedSrc}, and 'disallowFallbackToHtml5Audio' was set.`);
128
- }
129
- Internals.Log.warn({ logLevel, tag: '@remotion/media' }, `Cannot decode ${preloadedSrc}, falling back to <Html5Audio>`);
130
- setShouldFallbackToNativeAudio(true);
131
- return;
132
- }
133
- if (result.type === 'no-tracks') {
134
- if (disallowFallbackToHtml5Audio) {
135
- throw new Error(`No video or audio tracks found for ${preloadedSrc}, and 'disallowFallbackToHtml5Audio' was set.`);
136
- }
137
- Internals.Log.warn({ logLevel, tag: '@remotion/media' }, `No video or audio tracks found for ${preloadedSrc}, falling back to <Html5Audio>`);
138
- setShouldFallbackToNativeAudio(true);
139
- return;
140
- }
141
- if (result.type === 'success') {
142
- setMediaPlayerReady(true);
143
- setMediaDurationInSeconds(result.durationInSeconds);
144
- Internals.Log.trace({ logLevel, tag: '@remotion/media' }, `[AudioForPreview] MediaPlayer initialized successfully`);
145
- }
146
- })
147
- .catch((error) => {
148
- Internals.Log.error({ logLevel, tag: '@remotion/media' }, '[AudioForPreview] Failed to initialize MediaPlayer', error);
149
- setShouldFallbackToNativeAudio(true);
150
- });
151
- }
152
- catch (error) {
153
- Internals.Log.error({ logLevel, tag: '@remotion/media' }, '[AudioForPreview] MediaPlayer initialization failed', error);
154
- setShouldFallbackToNativeAudio(true);
155
- }
156
- return () => {
157
- if (mediaPlayerRef.current) {
158
- Internals.Log.trace({ logLevel, tag: '@remotion/media' }, `[AudioForPreview] Disposing MediaPlayer`);
159
- mediaPlayerRef.current.dispose();
160
- mediaPlayerRef.current = null;
161
- }
162
- setMediaPlayerReady(false);
163
- setShouldFallbackToNativeAudio(false);
164
- };
165
- }, [
166
- preloadedSrc,
167
- logLevel,
168
- sharedAudioContext,
169
- currentTimeRef,
170
- loop,
171
- videoConfig.fps,
172
- audioStreamIndex,
173
- disallowFallbackToHtml5Audio,
174
- buffer,
175
- ]);
176
- useLayoutEffect(() => {
177
- const audioPlayer = mediaPlayerRef.current;
178
- if (!audioPlayer)
179
- return;
180
- if (playing && !isPlayerBuffering) {
181
- audioPlayer.play(currentTimeRef.current);
182
- }
183
- else {
184
- audioPlayer.pause();
185
- }
186
- }, [isPlayerBuffering, logLevel, playing]);
187
- useLayoutEffect(() => {
188
- const mediaPlayer = mediaPlayerRef.current;
189
- if (!mediaPlayer || !mediaPlayerReady) {
190
- return;
191
- }
192
- mediaPlayer.setTrimBefore(trimBefore, currentTimeRef.current);
193
- }, [trimBefore, mediaPlayerReady]);
194
- useLayoutEffect(() => {
195
- const mediaPlayer = mediaPlayerRef.current;
196
- if (!mediaPlayer || !mediaPlayerReady) {
197
- return;
198
- }
199
- mediaPlayer.setTrimAfter(trimAfter, currentTimeRef.current);
200
- }, [trimAfter, mediaPlayerReady]);
201
- const effectiveMuted = muted || mediaMuted || userPreferredVolume <= 0;
202
- useLayoutEffect(() => {
203
- const audioPlayer = mediaPlayerRef.current;
204
- if (!audioPlayer || !mediaPlayerReady)
205
- return;
206
- audioPlayer.setMuted(effectiveMuted);
207
- }, [effectiveMuted, mediaPlayerReady]);
208
- useEffect(() => {
209
- const audioPlayer = mediaPlayerRef.current;
210
- if (!audioPlayer || !mediaPlayerReady) {
211
- return;
212
- }
213
- audioPlayer.setVolume(userPreferredVolume);
214
- }, [userPreferredVolume, mediaPlayerReady]);
215
- useEffect(() => {
216
- const audioPlayer = mediaPlayerRef.current;
217
- if (!audioPlayer || !mediaPlayerReady) {
218
- return;
219
- }
220
- audioPlayer.setPlaybackRate(playbackRate);
221
- }, [playbackRate, mediaPlayerReady]);
222
- useLayoutEffect(() => {
223
- const audioPlayer = mediaPlayerRef.current;
224
- if (!audioPlayer || !mediaPlayerReady) {
225
- return;
226
- }
227
- audioPlayer.setGlobalPlaybackRate(globalPlaybackRate);
228
- }, [globalPlaybackRate, mediaPlayerReady]);
229
- useLayoutEffect(() => {
230
- const audioPlayer = mediaPlayerRef.current;
231
- if (!audioPlayer || !mediaPlayerReady) {
232
- return;
233
- }
234
- audioPlayer.setFps(videoConfig.fps);
235
- }, [videoConfig.fps, mediaPlayerReady]);
236
- useLayoutEffect(() => {
237
- const mediaPlayer = mediaPlayerRef.current;
238
- if (!mediaPlayer || !mediaPlayerReady) {
239
- return;
240
- }
241
- mediaPlayer.setLoop(loop);
242
- }, [loop, mediaPlayerReady]);
243
- useLayoutEffect(() => {
244
- const mediaPlayer = mediaPlayerRef.current;
245
- if (!mediaPlayer || !mediaPlayerReady) {
246
- return;
247
- }
248
- mediaPlayer.setIsPremounting(isPremounting);
249
- }, [isPremounting, mediaPlayerReady]);
250
- useLayoutEffect(() => {
251
- const mediaPlayer = mediaPlayerRef.current;
252
- if (!mediaPlayer || !mediaPlayerReady) {
253
- return;
254
- }
255
- mediaPlayer.setIsPostmounting(isPostmounting);
256
- }, [isPostmounting, mediaPlayerReady]);
257
- useLayoutEffect(() => {
258
- const audioPlayer = mediaPlayerRef.current;
259
- if (!audioPlayer || !mediaPlayerReady)
260
- return;
261
- audioPlayer.seekTo(currentTime).catch(() => {
262
- // Might be disposed
263
- });
264
- Internals.Log.trace({ logLevel, tag: '@remotion/media' }, `[AudioForPreview] Updating target time to ${currentTime.toFixed(3)}s`);
265
- }, [currentTime, logLevel, mediaPlayerReady]);
266
- if (shouldFallbackToNativeAudio && !disallowFallbackToHtml5Audio) {
267
- return (_jsx(RemotionAudio, { src: src, muted: muted, volume: volume, startFrom: trimBefore, endAt: trimAfter, playbackRate: playbackRate, loopVolumeCurveBehavior: loopVolumeCurveBehavior, name: name, loop: loop, showInTimeline: showInTimeline, stack: stack ?? undefined, toneFrequency: toneFrequency, audioStreamIndex: audioStreamIndex, pauseWhenBuffering: fallbackHtml5AudioProps?.pauseWhenBuffering, crossOrigin: fallbackHtml5AudioProps?.crossOrigin, ...fallbackHtml5AudioProps }));
268
- }
269
- return null;
270
- };
271
- export const AudioForPreview = ({ loop, src, logLevel, muted, name, volume, loopVolumeCurveBehavior, playbackRate, trimAfter, trimBefore, showInTimeline, stack, disallowFallbackToHtml5Audio, toneFrequency, audioStreamIndex, fallbackHtml5AudioProps, }) => {
272
- const preloadedSrc = usePreload(src);
273
- const frame = useCurrentFrame();
274
- const videoConfig = useVideoConfig();
275
- const currentTime = frame / videoConfig.fps;
276
- const showShow = useMemo(() => {
277
- return (getTimeInSeconds({
278
- unloopedTimeInSeconds: currentTime,
279
- playbackRate: playbackRate ?? 1,
280
- loop: loop ?? false,
281
- trimBefore,
282
- trimAfter,
283
- mediaDurationInSeconds: Infinity,
284
- fps: videoConfig.fps,
285
- ifNoMediaDuration: 'infinity',
286
- src,
287
- }) !== null);
288
- }, [
289
- currentTime,
290
- loop,
291
- playbackRate,
292
- src,
293
- trimAfter,
294
- trimBefore,
295
- videoConfig.fps,
296
- ]);
297
- if (!showShow) {
298
- return null;
299
- }
300
- return (_jsx(AudioForPreviewAssertedShowing, { audioStreamIndex: audioStreamIndex ?? 0, src: preloadedSrc, playbackRate: playbackRate ?? 1, logLevel: logLevel ??
301
- (typeof window !== 'undefined'
302
- ? (window.remotion_logLevel ?? 'info')
303
- : 'info'), muted: muted ?? false, volume: volume ?? 1, loopVolumeCurveBehavior: loopVolumeCurveBehavior ?? 'repeat', loop: loop ?? false, trimAfter: trimAfter, trimBefore: trimBefore, name: name, showInTimeline: showInTimeline ?? true, stack: stack, disallowFallbackToHtml5Audio: disallowFallbackToHtml5Audio ?? false, toneFrequency: toneFrequency, fallbackHtml5AudioProps: fallbackHtml5AudioProps }));
304
- };