remotion 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/README.md +0 -1
- package/dist/cjs/Img.js +14 -5
- package/dist/cjs/RemotionRoot.d.ts +1 -0
- package/dist/cjs/RemotionRoot.js +2 -2
- package/dist/cjs/Sequence.js +3 -4
- package/dist/cjs/SequenceManager.d.ts +10 -5
- package/dist/cjs/SequenceManager.js +50 -18
- package/dist/cjs/TimelineContext.d.ts +1 -0
- package/dist/cjs/TimelineContext.js +15 -2
- package/dist/cjs/audio/shared-audio-tags.d.ts +20 -1
- package/dist/cjs/audio/shared-audio-tags.js +73 -0
- package/dist/cjs/get-effective-visual-mode-value.d.ts +7 -0
- package/dist/cjs/get-effective-visual-mode-value.js +19 -0
- package/dist/cjs/internals.d.ts +21 -3
- package/dist/cjs/internals.js +7 -1
- package/dist/cjs/sequence-field-schema.d.ts +3 -2
- package/dist/cjs/sequence-stack-traces.d.ts +0 -4
- package/dist/cjs/sequence-stack-traces.js +1 -4
- package/dist/cjs/timeline-position-state.d.ts +1 -0
- package/dist/cjs/timeline-position-state.js +11 -3
- package/dist/cjs/use-schema.d.ts +9 -2
- package/dist/cjs/use-schema.js +43 -14
- package/dist/cjs/use-sequence-control-override.js +1 -1
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/index.mjs +256 -77
- package/dist/esm/version.mjs +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
[](https://remotion.dev/discord)
|
|
11
11
|
[](https://www.npmjs.org/package/remotion)
|
|
12
12
|
[](https://npmcharts.com/compare/remotion?minimal=true)
|
|
13
|
-
[](https://github.com/remotion-dev/remotion/issues?q=is%3Aopen+label%3A%22%F0%9F%92%8E+Bounty%22+sort%3Aupdated-desc)
|
|
14
13
|
<a href="https://twitter.com/remotion"><img src="https://img.shields.io/twitter/follow/remotion?label=Twitter&color=black" alt="Twitter"></a>
|
|
15
14
|
|
|
16
15
|
Remotion is a framework for **creating videos programmatically using React.**
|
package/dist/cjs/Img.js
CHANGED
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Img = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const react_1 = require("react");
|
|
6
|
-
const cancel_render_js_1 = require("./cancel-render.js");
|
|
7
6
|
const get_cross_origin_value_js_1 = require("./get-cross-origin-value.js");
|
|
8
7
|
const prefetch_js_1 = require("./prefetch.js");
|
|
9
8
|
const SequenceContext_js_1 = require("./SequenceContext.js");
|
|
@@ -49,6 +48,7 @@ const ImgRefForwarding = ({ onError, maxRetries = 2, src, pauseWhenLoading, dela
|
|
|
49
48
|
imageRef.current.setAttribute('src', newSrc);
|
|
50
49
|
}, timeout);
|
|
51
50
|
}, []);
|
|
51
|
+
const { delayRender, continueRender, cancelRender } = (0, use_delay_render_js_1.useDelayRender)();
|
|
52
52
|
const didGetError = (0, react_1.useCallback)((e) => {
|
|
53
53
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
54
54
|
if (!errors.current) {
|
|
@@ -68,9 +68,14 @@ const ImgRefForwarding = ({ onError, maxRetries = 2, src, pauseWhenLoading, dela
|
|
|
68
68
|
retryIn(backoff);
|
|
69
69
|
return;
|
|
70
70
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
try {
|
|
72
|
+
cancelRender('Error loading image with src: ' + ((_l = imageRef.current) === null || _l === void 0 ? void 0 : _l.src));
|
|
73
|
+
}
|
|
74
|
+
catch (_m) {
|
|
75
|
+
// cancelRender() intentionally throws after storing the error in scope.
|
|
76
|
+
// In async image callbacks, we rely on the stored error for renderer propagation.
|
|
77
|
+
}
|
|
78
|
+
}, [cancelRender, maxRetries, onError, retryIn]);
|
|
74
79
|
if (typeof window !== 'undefined') {
|
|
75
80
|
const isPremounting = Boolean(sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.premounting);
|
|
76
81
|
const isPostmounting = Boolean(sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.postmounting);
|
|
@@ -125,7 +130,11 @@ const ImgRefForwarding = ({ onError, maxRetries = 2, src, pauseWhenLoading, dela
|
|
|
125
130
|
// fall back to onload event if decode() fails
|
|
126
131
|
// eslint-disable-next-line no-console
|
|
127
132
|
console.warn(err);
|
|
128
|
-
|
|
133
|
+
// HTMLImageElement.complete is also true for broken images (e.g. 404),
|
|
134
|
+
// so only treat it as loaded if intrinsic dimensions are available.
|
|
135
|
+
if (current.complete &&
|
|
136
|
+
current.naturalWidth > 0 &&
|
|
137
|
+
current.naturalHeight > 0) {
|
|
129
138
|
onComplete();
|
|
130
139
|
}
|
|
131
140
|
else {
|
package/dist/cjs/RemotionRoot.js
CHANGED
|
@@ -13,7 +13,7 @@ const SequenceManager_js_1 = require("./SequenceManager.js");
|
|
|
13
13
|
const TimelineContext_js_1 = require("./TimelineContext.js");
|
|
14
14
|
const use_media_enabled_js_1 = require("./use-media-enabled.js");
|
|
15
15
|
const duration_state_js_1 = require("./video/duration-state.js");
|
|
16
|
-
const RemotionRootContexts = ({ children, numberOfAudioTags, logLevel, audioLatencyHint, videoEnabled, audioEnabled, frameState, nonceContextSeed, }) => {
|
|
16
|
+
const RemotionRootContexts = ({ children, numberOfAudioTags, logLevel, audioLatencyHint, videoEnabled, audioEnabled, frameState, nonceContextSeed, visualModeEnabled, }) => {
|
|
17
17
|
const nonceContext = (0, react_1.useMemo)(() => {
|
|
18
18
|
let counter = 0;
|
|
19
19
|
return {
|
|
@@ -24,6 +24,6 @@ const RemotionRootContexts = ({ children, numberOfAudioTags, logLevel, audioLate
|
|
|
24
24
|
const logging = (0, react_1.useMemo)(() => {
|
|
25
25
|
return { logLevel, mountTime: Date.now() };
|
|
26
26
|
}, [logLevel]);
|
|
27
|
-
return ((0, jsx_runtime_1.jsx)(log_level_context_js_1.LogLevelContext.Provider, { value: logging, children: (0, jsx_runtime_1.jsx)(nonce_js_1.NonceContext.Provider, { value: nonceContext, children: (0, jsx_runtime_1.jsx)(TimelineContext_js_1.TimelineContextProvider, { frameState: frameState, children: (0, jsx_runtime_1.jsx)(use_media_enabled_js_1.MediaEnabledProvider, { videoEnabled: videoEnabled, audioEnabled: audioEnabled, children: (0, jsx_runtime_1.jsx)(EditorProps_js_1.EditorPropsProvider, { children: (0, jsx_runtime_1.jsx)(prefetch_state_js_1.PrefetchProvider, { children: (0, jsx_runtime_1.jsx)(SequenceManager_js_1.SequenceManagerProvider, { children: (0, jsx_runtime_1.jsx)(shared_audio_tags_js_1.SharedAudioContextProvider, { numberOfAudioTags: numberOfAudioTags, audioLatencyHint: audioLatencyHint, audioEnabled: audioEnabled, children: (0, jsx_runtime_1.jsx)(duration_state_js_1.DurationsContextProvider, { children: (0, jsx_runtime_1.jsx)(buffering_js_1.BufferingProvider, { children: children }) }) }) }) }) }) }) }) }) }));
|
|
27
|
+
return ((0, jsx_runtime_1.jsx)(log_level_context_js_1.LogLevelContext.Provider, { value: logging, children: (0, jsx_runtime_1.jsx)(nonce_js_1.NonceContext.Provider, { value: nonceContext, children: (0, jsx_runtime_1.jsx)(TimelineContext_js_1.TimelineContextProvider, { frameState: frameState, children: (0, jsx_runtime_1.jsx)(use_media_enabled_js_1.MediaEnabledProvider, { videoEnabled: videoEnabled, audioEnabled: audioEnabled, children: (0, jsx_runtime_1.jsx)(EditorProps_js_1.EditorPropsProvider, { children: (0, jsx_runtime_1.jsx)(prefetch_state_js_1.PrefetchProvider, { children: (0, jsx_runtime_1.jsx)(SequenceManager_js_1.SequenceManagerProvider, { visualModeEnabled: visualModeEnabled, children: (0, jsx_runtime_1.jsx)(shared_audio_tags_js_1.SharedAudioContextProvider, { numberOfAudioTags: numberOfAudioTags, audioLatencyHint: audioLatencyHint, audioEnabled: audioEnabled, children: (0, jsx_runtime_1.jsx)(duration_state_js_1.DurationsContextProvider, { children: (0, jsx_runtime_1.jsx)(buffering_js_1.BufferingProvider, { children: children }) }) }) }) }) }) }) }) }) }));
|
|
28
28
|
};
|
|
29
29
|
exports.RemotionRootContexts = RemotionRootContexts;
|
package/dist/cjs/Sequence.js
CHANGED
|
@@ -169,7 +169,8 @@ const RegularSequenceRefForwardingFunction = ({ from = 0, durationInFrames = Inf
|
|
|
169
169
|
};
|
|
170
170
|
const RegularSequence = (0, react_1.forwardRef)(RegularSequenceRefForwardingFunction);
|
|
171
171
|
const PremountedPostmountedSequenceRefForwardingFunction = (props, ref) => {
|
|
172
|
-
const
|
|
172
|
+
const parentPremountContext = (0, react_1.useContext)(PremountContext_js_1.PremountContext);
|
|
173
|
+
const frame = (0, use_current_frame_1.useCurrentFrame)() - parentPremountContext.premountFramesRemaining;
|
|
173
174
|
if (props.layout === 'none') {
|
|
174
175
|
throw new Error('`<Sequence>` with `premountFor` and `postmountFor` props does not support layout="none"');
|
|
175
176
|
}
|
|
@@ -202,10 +203,8 @@ const PremountedPostmountedSequenceRefForwardingFunction = (props, ref) => {
|
|
|
202
203
|
styleWhilePremounted,
|
|
203
204
|
styleWhilePostmounted,
|
|
204
205
|
]);
|
|
205
|
-
const parentPremountContext = (0, react_1.useContext)(PremountContext_js_1.PremountContext);
|
|
206
206
|
const { playing } = (0, react_1.useContext)(TimelineContext_js_1.TimelineContext);
|
|
207
|
-
const premountFramesRemaining =
|
|
208
|
-
(premountingActive ? from - frame : 0);
|
|
207
|
+
const premountFramesRemaining = premountingActive ? from - frame : 0;
|
|
209
208
|
const premountContextValue = (0, react_1.useMemo)(() => {
|
|
210
209
|
return {
|
|
211
210
|
premountFramesRemaining,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { TSequence } from './CompositionManager.js';
|
|
3
|
+
import type { CanUpdateSequencePropStatus } from './use-schema.js';
|
|
3
4
|
export type SequenceManagerContext = {
|
|
4
5
|
registerSequence: (seq: TSequence) => void;
|
|
5
6
|
unregisterSequence: (id: string) => void;
|
|
@@ -11,12 +12,16 @@ export type SequenceVisibilityToggleState = {
|
|
|
11
12
|
setHidden: React.Dispatch<React.SetStateAction<Record<string, boolean>>>;
|
|
12
13
|
};
|
|
13
14
|
export declare const SequenceVisibilityToggleContext: React.Context<SequenceVisibilityToggleState>;
|
|
14
|
-
export type
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
export type VisualModeOverrides = {
|
|
16
|
+
visualModeEnabled: boolean;
|
|
17
|
+
dragOverrides: Record<string, Record<string, unknown>>;
|
|
18
|
+
setDragOverrides: (sequenceId: string, key: string, value: unknown) => void;
|
|
19
|
+
clearDragOverrides: (sequenceId: string) => void;
|
|
20
|
+
codeValues: Record<string, Record<string, CanUpdateSequencePropStatus>>;
|
|
21
|
+
setCodeValues: (sequenceId: string, values: Record<string, CanUpdateSequencePropStatus> | null) => void;
|
|
18
22
|
};
|
|
19
|
-
export declare const
|
|
23
|
+
export declare const VisualModeOverridesContext: React.Context<VisualModeOverrides>;
|
|
20
24
|
export declare const SequenceManagerProvider: React.FC<{
|
|
21
25
|
readonly children: React.ReactNode;
|
|
26
|
+
readonly visualModeEnabled: boolean;
|
|
22
27
|
}>;
|
|
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.SequenceManagerProvider = exports.
|
|
36
|
+
exports.SequenceManagerProvider = exports.VisualModeOverridesContext = exports.SequenceVisibilityToggleContext = exports.SequenceManager = void 0;
|
|
37
37
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
38
38
|
const react_1 = __importStar(require("react"));
|
|
39
39
|
exports.SequenceManager = react_1.default.createContext({
|
|
@@ -51,22 +51,28 @@ exports.SequenceVisibilityToggleContext = react_1.default.createContext({
|
|
|
51
51
|
throw new Error('SequenceVisibilityToggle not initialized');
|
|
52
52
|
},
|
|
53
53
|
});
|
|
54
|
-
exports.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
throw new Error('
|
|
54
|
+
exports.VisualModeOverridesContext = react_1.default.createContext({
|
|
55
|
+
dragOverrides: {},
|
|
56
|
+
setDragOverrides: () => {
|
|
57
|
+
throw new Error('VisualModeOverridesContext not initialized');
|
|
58
58
|
},
|
|
59
|
-
|
|
60
|
-
throw new Error('
|
|
59
|
+
clearDragOverrides: () => {
|
|
60
|
+
throw new Error('VisualModeOverridesContext not initialized');
|
|
61
61
|
},
|
|
62
|
+
codeValues: {},
|
|
63
|
+
setCodeValues: () => {
|
|
64
|
+
throw new Error('VisualModeOverridesContext not initialized');
|
|
65
|
+
},
|
|
66
|
+
visualModeEnabled: false,
|
|
62
67
|
});
|
|
63
|
-
const SequenceManagerProvider = ({ children }) => {
|
|
68
|
+
const SequenceManagerProvider = ({ children, visualModeEnabled }) => {
|
|
64
69
|
const [sequences, setSequences] = (0, react_1.useState)([]);
|
|
65
70
|
const [hidden, setHidden] = (0, react_1.useState)({});
|
|
66
|
-
const [
|
|
67
|
-
const controlOverridesRef = (0, react_1.useRef)(
|
|
68
|
-
controlOverridesRef.current =
|
|
69
|
-
const
|
|
71
|
+
const [dragOverrides, setControlOverrides] = (0, react_1.useState)({});
|
|
72
|
+
const controlOverridesRef = (0, react_1.useRef)(dragOverrides);
|
|
73
|
+
controlOverridesRef.current = dragOverrides;
|
|
74
|
+
const [codeValues, setCodeValuesMapState] = (0, react_1.useState)({});
|
|
75
|
+
const setDragOverrides = (0, react_1.useCallback)((sequenceId, key, value) => {
|
|
70
76
|
setControlOverrides((prev) => ({
|
|
71
77
|
...prev,
|
|
72
78
|
[sequenceId]: {
|
|
@@ -75,7 +81,7 @@ const SequenceManagerProvider = ({ children }) => {
|
|
|
75
81
|
},
|
|
76
82
|
}));
|
|
77
83
|
}, []);
|
|
78
|
-
const
|
|
84
|
+
const clearDragOverrides = (0, react_1.useCallback)((sequenceId) => {
|
|
79
85
|
setControlOverrides((prev) => {
|
|
80
86
|
if (!prev[sequenceId]) {
|
|
81
87
|
return prev;
|
|
@@ -85,6 +91,22 @@ const SequenceManagerProvider = ({ children }) => {
|
|
|
85
91
|
return next;
|
|
86
92
|
});
|
|
87
93
|
}, []);
|
|
94
|
+
const setCodeValues = (0, react_1.useCallback)((sequenceId, values) => {
|
|
95
|
+
setCodeValuesMapState((prev) => {
|
|
96
|
+
if (prev[sequenceId] === values) {
|
|
97
|
+
return prev;
|
|
98
|
+
}
|
|
99
|
+
if (values === null) {
|
|
100
|
+
if (!(sequenceId in prev)) {
|
|
101
|
+
return prev;
|
|
102
|
+
}
|
|
103
|
+
const next = { ...prev };
|
|
104
|
+
delete next[sequenceId];
|
|
105
|
+
return next;
|
|
106
|
+
}
|
|
107
|
+
return { ...prev, [sequenceId]: values };
|
|
108
|
+
});
|
|
109
|
+
}, []);
|
|
88
110
|
const registerSequence = (0, react_1.useCallback)((seq) => {
|
|
89
111
|
setSequences((seqs) => {
|
|
90
112
|
return [...seqs, seq];
|
|
@@ -108,11 +130,21 @@ const SequenceManagerProvider = ({ children }) => {
|
|
|
108
130
|
}, [hidden]);
|
|
109
131
|
const overrideContext = (0, react_1.useMemo)(() => {
|
|
110
132
|
return {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
133
|
+
visualModeEnabled,
|
|
134
|
+
dragOverrides,
|
|
135
|
+
setDragOverrides,
|
|
136
|
+
clearDragOverrides,
|
|
137
|
+
codeValues,
|
|
138
|
+
setCodeValues,
|
|
114
139
|
};
|
|
115
|
-
}, [
|
|
116
|
-
|
|
140
|
+
}, [
|
|
141
|
+
visualModeEnabled,
|
|
142
|
+
dragOverrides,
|
|
143
|
+
setDragOverrides,
|
|
144
|
+
clearDragOverrides,
|
|
145
|
+
codeValues,
|
|
146
|
+
setCodeValues,
|
|
147
|
+
]);
|
|
148
|
+
return ((0, jsx_runtime_1.jsx)(exports.SequenceManager.Provider, { value: sequenceContext, children: (0, jsx_runtime_1.jsx)(exports.SequenceVisibilityToggleContext.Provider, { value: hiddenContext, children: (0, jsx_runtime_1.jsx)(exports.VisualModeOverridesContext.Provider, { value: overrideContext, children: children }) }) }));
|
|
117
149
|
};
|
|
118
150
|
exports.SequenceManagerProvider = SequenceManagerProvider;
|
|
@@ -16,6 +16,7 @@ export type SetTimelineContextValue = {
|
|
|
16
16
|
};
|
|
17
17
|
export declare const SetTimelineContext: React.Context<SetTimelineContextValue>;
|
|
18
18
|
export declare const TimelineContext: React.Context<TimelineContextValue>;
|
|
19
|
+
export declare const AbsoluteTimeContext: React.Context<TimelineContextValue>;
|
|
19
20
|
export declare const TimelineContextProvider: React.FC<{
|
|
20
21
|
readonly children: React.ReactNode;
|
|
21
22
|
readonly frameState: Record<string, number> | null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TimelineContextProvider = exports.TimelineContext = exports.SetTimelineContext = void 0;
|
|
3
|
+
exports.TimelineContextProvider = exports.AbsoluteTimeContext = exports.TimelineContext = exports.SetTimelineContext = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const react_1 = require("react");
|
|
6
6
|
const random_1 = require("./random");
|
|
@@ -27,6 +27,19 @@ exports.TimelineContext = (0, react_1.createContext)({
|
|
|
27
27
|
},
|
|
28
28
|
audioAndVideoTags: { current: [] },
|
|
29
29
|
});
|
|
30
|
+
exports.AbsoluteTimeContext = (0, react_1.createContext)({
|
|
31
|
+
frame: {},
|
|
32
|
+
playing: false,
|
|
33
|
+
playbackRate: 1,
|
|
34
|
+
rootId: '',
|
|
35
|
+
imperativePlaying: {
|
|
36
|
+
current: false,
|
|
37
|
+
},
|
|
38
|
+
setPlaybackRate: () => {
|
|
39
|
+
throw new Error('default');
|
|
40
|
+
},
|
|
41
|
+
audioAndVideoTags: { current: [] },
|
|
42
|
+
});
|
|
30
43
|
const TimelineContextProvider = ({ children, frameState }) => {
|
|
31
44
|
const [playing, setPlaying] = (0, react_1.useState)(false);
|
|
32
45
|
const imperativePlaying = (0, react_1.useRef)(false);
|
|
@@ -84,6 +97,6 @@ const TimelineContextProvider = ({ children, frameState }) => {
|
|
|
84
97
|
setPlaying,
|
|
85
98
|
};
|
|
86
99
|
}, []);
|
|
87
|
-
return ((0, jsx_runtime_1.jsx)(exports.TimelineContext.Provider, { value: timelineContextValue, children: (0, jsx_runtime_1.jsx)(exports.SetTimelineContext.Provider, { value: setTimelineContextValue, children: children }) }));
|
|
100
|
+
return ((0, jsx_runtime_1.jsx)(exports.AbsoluteTimeContext.Provider, { value: timelineContextValue, children: (0, jsx_runtime_1.jsx)(exports.TimelineContext.Provider, { value: timelineContextValue, children: (0, jsx_runtime_1.jsx)(exports.SetTimelineContext.Provider, { value: setTimelineContextValue, children: children }) }) }));
|
|
88
101
|
};
|
|
89
102
|
exports.TimelineContextProvider = TimelineContextProvider;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type AudioHTMLAttributes } from 'react';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import type { SharedElementSourceNode } from './shared-element-source-node.js';
|
|
4
4
|
/**
|
|
@@ -23,6 +23,21 @@ type AudioElem = {
|
|
|
23
23
|
audioMounted: boolean;
|
|
24
24
|
cleanupOnMediaTagUnmount: () => void;
|
|
25
25
|
};
|
|
26
|
+
export type ScheduleAudioNodeResult = {
|
|
27
|
+
type: 'started';
|
|
28
|
+
scheduledTime: number;
|
|
29
|
+
} | {
|
|
30
|
+
type: 'not-started';
|
|
31
|
+
};
|
|
32
|
+
export type ScheduleAudioNodeOptions = {
|
|
33
|
+
readonly node: AudioBufferSourceNode;
|
|
34
|
+
readonly targetTime: number;
|
|
35
|
+
readonly mediaTimestamp: number;
|
|
36
|
+
readonly currentTime: number;
|
|
37
|
+
readonly sequenceEndTime: number;
|
|
38
|
+
readonly sequenceStartTime: number;
|
|
39
|
+
readonly debugAudioScheduling: boolean;
|
|
40
|
+
};
|
|
26
41
|
type SharedContext = {
|
|
27
42
|
registerAudio: (options: {
|
|
28
43
|
aud: AudioHTMLAttributes<HTMLAudioElement>;
|
|
@@ -41,6 +56,10 @@ type SharedContext = {
|
|
|
41
56
|
playAllAudios: () => void;
|
|
42
57
|
numberOfAudioTags: number;
|
|
43
58
|
audioContext: AudioContext | null;
|
|
59
|
+
audioSyncAnchor: {
|
|
60
|
+
value: number;
|
|
61
|
+
};
|
|
62
|
+
scheduleAudioNode: (options: ScheduleAudioNodeOptions) => ScheduleAudioNodeResult;
|
|
44
63
|
};
|
|
45
64
|
export declare const SharedAudioContext: React.Context<SharedContext | null>;
|
|
46
65
|
export declare const SharedAudioContextProvider: React.FC<{
|
|
@@ -37,6 +37,7 @@ exports.useSharedAudio = exports.SharedAudioContextProvider = exports.SharedAudi
|
|
|
37
37
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
38
38
|
const react_1 = __importStar(require("react"));
|
|
39
39
|
const log_level_context_js_1 = require("../log-level-context.js");
|
|
40
|
+
const log_js_1 = require("../log.js");
|
|
40
41
|
const play_and_handle_not_allowed_error_js_1 = require("../play-and-handle-not-allowed-error.js");
|
|
41
42
|
const use_remotion_environment_js_1 = require("../use-remotion-environment.js");
|
|
42
43
|
const shared_element_source_node_js_1 = require("./shared-element-source-node.js");
|
|
@@ -87,6 +88,74 @@ const SharedAudioContextProvider = ({ children, numberOfAudioTags, audioLatencyH
|
|
|
87
88
|
latencyHint: audioLatencyHint,
|
|
88
89
|
audioEnabled,
|
|
89
90
|
});
|
|
91
|
+
const audioSyncAnchor = (0, react_1.useMemo)(() => ({ value: 0 }), []);
|
|
92
|
+
const prevEndTimes = (0, react_1.useRef)({ scheduledEndTime: null, mediaEndTime: null });
|
|
93
|
+
const scheduleAudioNode = (0, react_1.useMemo)(() => {
|
|
94
|
+
return ({ node, mediaTimestamp, targetTime, currentTime, sequenceEndTime, sequenceStartTime, debugAudioScheduling, }) => {
|
|
95
|
+
var _a, _b;
|
|
96
|
+
if (!audioContext) {
|
|
97
|
+
throw new Error('Audio context not found');
|
|
98
|
+
}
|
|
99
|
+
const bufferDuration = (_b = (_a = node.buffer) === null || _a === void 0 ? void 0 : _a.duration) !== null && _b !== void 0 ? _b : 0;
|
|
100
|
+
const unclampedMediaEndTime = mediaTimestamp + bufferDuration;
|
|
101
|
+
const needsTrimEnd = unclampedMediaEndTime > sequenceEndTime;
|
|
102
|
+
const needsTrimStart = mediaTimestamp < sequenceStartTime;
|
|
103
|
+
const offsetBecauseOfTrim = needsTrimStart
|
|
104
|
+
? sequenceStartTime - mediaTimestamp
|
|
105
|
+
: 0;
|
|
106
|
+
const offsetBecauseOfTooLate = targetTime < 0 ? -targetTime : 0;
|
|
107
|
+
const offset = offsetBecauseOfTrim + offsetBecauseOfTooLate;
|
|
108
|
+
const duration = needsTrimEnd
|
|
109
|
+
? bufferDuration -
|
|
110
|
+
Math.max(0, unclampedMediaEndTime - sequenceEndTime) -
|
|
111
|
+
offset
|
|
112
|
+
: bufferDuration - offset;
|
|
113
|
+
const scheduledTime = targetTime + currentTime + offset;
|
|
114
|
+
if (offset < 0) {
|
|
115
|
+
throw new Error('offset < 0: ' +
|
|
116
|
+
JSON.stringify({
|
|
117
|
+
offset,
|
|
118
|
+
targetTime,
|
|
119
|
+
currentTime,
|
|
120
|
+
offsetBecauseOfTrim,
|
|
121
|
+
offsetBecauseOfTooLate,
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
if (duration > 0) {
|
|
125
|
+
node.start(scheduledTime, offset, duration);
|
|
126
|
+
}
|
|
127
|
+
const scheduledEndTime = scheduledTime + duration / node.playbackRate.value;
|
|
128
|
+
const mediaTime = mediaTimestamp + offset;
|
|
129
|
+
const mediaEndTime = mediaTime + duration;
|
|
130
|
+
const latency = audioContext.baseLatency + audioContext.outputLatency;
|
|
131
|
+
const timeDiff = scheduledTime - currentTime - latency;
|
|
132
|
+
const prev = prevEndTimes.current;
|
|
133
|
+
const scheduledMismatch = prev.scheduledEndTime !== null &&
|
|
134
|
+
Math.abs(scheduledTime - prev.scheduledEndTime) > 0.001;
|
|
135
|
+
const mediaMismatch = prev.mediaEndTime !== null &&
|
|
136
|
+
Math.abs(mediaTime - prev.mediaEndTime) > 0.001;
|
|
137
|
+
if (debugAudioScheduling) {
|
|
138
|
+
log_js_1.Log.info({ logLevel, tag: 'audio-scheduling' }, 'scheduled %c%s%c %s %c%s%c %s %c%s%c %s %s %s', scheduledMismatch ? 'color: red; font-weight: bold' : '', scheduledTime.toFixed(4), '', scheduledEndTime.toFixed(4), mediaMismatch ? 'color: red; font-weight: bold' : '', mediaTime.toFixed(4), '', mediaEndTime.toFixed(4), duration < 0
|
|
139
|
+
? 'color: red; font-weight: bold'
|
|
140
|
+
: timeDiff < 0
|
|
141
|
+
? 'color: red; font-weight: bold'
|
|
142
|
+
: 'color: blue; font-weight: bold', duration < 0
|
|
143
|
+
? 'missed ' + Math.abs(offset).toFixed(2) + 's'
|
|
144
|
+
: Math.abs(timeDiff).toFixed(2) +
|
|
145
|
+
(timeDiff < 0 ? ' delay' : ' ahead'), '', 'current=' + currentTime.toFixed(4), 'offset=' + offset.toFixed(4), 'latency=' + latency.toFixed(4), 'state=' + audioContext.state);
|
|
146
|
+
}
|
|
147
|
+
prev.scheduledEndTime = scheduledEndTime;
|
|
148
|
+
prev.mediaEndTime = mediaEndTime;
|
|
149
|
+
return duration > 0
|
|
150
|
+
? {
|
|
151
|
+
type: 'started',
|
|
152
|
+
scheduledTime,
|
|
153
|
+
}
|
|
154
|
+
: {
|
|
155
|
+
type: 'not-started',
|
|
156
|
+
};
|
|
157
|
+
};
|
|
158
|
+
}, [audioContext, logLevel]);
|
|
90
159
|
const refs = (0, react_1.useMemo)(() => {
|
|
91
160
|
return new Array(numberOfAudioTags).fill(true).map(() => {
|
|
92
161
|
const ref = (0, react_1.createRef)();
|
|
@@ -253,6 +322,8 @@ const SharedAudioContextProvider = ({ children, numberOfAudioTags, audioLatencyH
|
|
|
253
322
|
playAllAudios,
|
|
254
323
|
numberOfAudioTags,
|
|
255
324
|
audioContext,
|
|
325
|
+
audioSyncAnchor,
|
|
326
|
+
scheduleAudioNode,
|
|
256
327
|
};
|
|
257
328
|
}, [
|
|
258
329
|
numberOfAudioTags,
|
|
@@ -261,6 +332,8 @@ const SharedAudioContextProvider = ({ children, numberOfAudioTags, audioLatencyH
|
|
|
261
332
|
unregisterAudio,
|
|
262
333
|
updateAudio,
|
|
263
334
|
audioContext,
|
|
335
|
+
audioSyncAnchor,
|
|
336
|
+
scheduleAudioNode,
|
|
264
337
|
]);
|
|
265
338
|
return ((0, jsx_runtime_1.jsxs)(exports.SharedAudioContext.Provider, { value: value, children: [refs.map(({ id, ref }) => {
|
|
266
339
|
return (
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CanUpdateSequencePropStatus } from './use-schema';
|
|
2
|
+
export declare const getEffectiveVisualModeValue: ({ codeValue, runtimeValue, dragOverrideValue, defaultValue, }: {
|
|
3
|
+
codeValue: CanUpdateSequencePropStatus | null;
|
|
4
|
+
runtimeValue: unknown;
|
|
5
|
+
dragOverrideValue: unknown;
|
|
6
|
+
defaultValue: unknown;
|
|
7
|
+
}) => unknown;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getEffectiveVisualModeValue = void 0;
|
|
4
|
+
const getEffectiveVisualModeValue = ({ codeValue, runtimeValue, dragOverrideValue, defaultValue, }) => {
|
|
5
|
+
if (dragOverrideValue !== undefined) {
|
|
6
|
+
return dragOverrideValue;
|
|
7
|
+
}
|
|
8
|
+
if (!codeValue) {
|
|
9
|
+
return runtimeValue;
|
|
10
|
+
}
|
|
11
|
+
if (!codeValue.canUpdate) {
|
|
12
|
+
return runtimeValue;
|
|
13
|
+
}
|
|
14
|
+
if (codeValue.codeValue === undefined) {
|
|
15
|
+
return defaultValue;
|
|
16
|
+
}
|
|
17
|
+
return codeValue.codeValue;
|
|
18
|
+
};
|
|
19
|
+
exports.getEffectiveVisualModeValue = getEffectiveVisualModeValue;
|
package/dist/cjs/internals.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { ScheduleAudioNodeResult } from './audio/shared-audio-tags.js';
|
|
2
|
+
import { type ScheduleAudioNodeOptions } from './audio/shared-audio-tags.js';
|
|
1
3
|
import { type CompProps } from './Composition.js';
|
|
2
4
|
import type { TCompMetadata, TComposition, TRenderAsset, TSequence } from './CompositionManager.js';
|
|
3
5
|
import type { CompositionManagerContext } from './CompositionManagerContext.js';
|
|
@@ -6,9 +8,11 @@ import type { SerializedJSONWithCustomFields } from './input-props-serialization
|
|
|
6
8
|
import type { LoggingContextValue } from './log-level-context.js';
|
|
7
9
|
import type { RemotionEnvironment } from './remotion-environment-context.js';
|
|
8
10
|
import type { SequenceFieldSchema, SequenceSchema } from './sequence-field-schema.js';
|
|
11
|
+
import type { ResolvedStackLocation } from './sequence-stack-traces.js';
|
|
9
12
|
import * as TimelinePosition from './timeline-position-state.js';
|
|
10
13
|
import { type SetTimelineContextValue, type TimelineContextValue } from './TimelineContext.js';
|
|
11
14
|
import { truthy } from './truthy.js';
|
|
15
|
+
import type { CanUpdateSequencePropStatus } from './use-schema.js';
|
|
12
16
|
import type { MediaVolumeContextValue, SetMediaVolumeContextValue } from './volume-position-state.js';
|
|
13
17
|
import type { WatchRemotionStaticFilesPayload } from './watch-static-file.js';
|
|
14
18
|
import { useRemotionContexts } from './wrap-remotion-context.js';
|
|
@@ -17,6 +21,7 @@ export declare const Internals: {
|
|
|
17
21
|
readonly useUnsafeVideoConfig: () => import("./video-config.js").VideoConfig | null;
|
|
18
22
|
readonly useFrameForVolumeProp: (behavior: import("./audio/use-audio-frame.js").LoopVolumeCurveBehavior) => number;
|
|
19
23
|
readonly useTimelinePosition: () => number;
|
|
24
|
+
readonly useAbsoluteTimelinePosition: () => number;
|
|
20
25
|
readonly evaluateVolume: ({ frame, volume, mediaVolume, }: {
|
|
21
26
|
frame: number;
|
|
22
27
|
volume: import("./volume-prop.js").VolumeProp | undefined;
|
|
@@ -71,10 +76,11 @@ export declare const Internals: {
|
|
|
71
76
|
}, "ref"> & import("react").RefAttributes<HTMLVideoElement>>;
|
|
72
77
|
readonly CompositionManager: import("react").Context<CompositionManagerContext>;
|
|
73
78
|
readonly CompositionSetters: import("react").Context<import("./CompositionManagerContext.js").CompositionManagerSetters>;
|
|
74
|
-
readonly
|
|
79
|
+
readonly VisualModeOverridesContext: import("react").Context<import("./SequenceManager.js").VisualModeOverrides>;
|
|
75
80
|
readonly SequenceManager: import("react").Context<import("./SequenceManager.js").SequenceManagerContext>;
|
|
81
|
+
readonly SequenceStackTracesUpdateContext: import("react").Context<import("./sequence-stack-traces.js").UpdateResolvedStackTraceFn>;
|
|
76
82
|
readonly SequenceVisibilityToggleContext: import("react").Context<import("./SequenceManager.js").SequenceVisibilityToggleState>;
|
|
77
|
-
readonly useSchema: <T extends
|
|
83
|
+
readonly useSchema: <S extends SequenceSchema, T extends import("./sequence-field-schema.js").SchemaKeysRecord<S>>(schema: S | null, currentValue: (T & Record<Exclude<keyof T, keyof S>, never>) | null) => {
|
|
78
84
|
controls: import("./CompositionManager.js").SequenceControls | undefined;
|
|
79
85
|
values: T;
|
|
80
86
|
};
|
|
@@ -88,6 +94,7 @@ export declare const Internals: {
|
|
|
88
94
|
readonly audioEnabled: boolean;
|
|
89
95
|
readonly frameState: Record<string, number> | null;
|
|
90
96
|
readonly nonceContextSeed: number;
|
|
97
|
+
readonly visualModeEnabled: boolean;
|
|
91
98
|
}>;
|
|
92
99
|
readonly CompositionManagerProvider: ({ children, onlyRenderComposition, currentCompositionMetadata, initialCompositions, initialCanvasContent, }: {
|
|
93
100
|
readonly children: React.ReactNode;
|
|
@@ -161,6 +168,10 @@ export declare const Internals: {
|
|
|
161
168
|
playAllAudios: () => void;
|
|
162
169
|
numberOfAudioTags: number;
|
|
163
170
|
audioContext: AudioContext | null;
|
|
171
|
+
audioSyncAnchor: {
|
|
172
|
+
value: number;
|
|
173
|
+
};
|
|
174
|
+
scheduleAudioNode: (options: ScheduleAudioNodeOptions) => ScheduleAudioNodeResult;
|
|
164
175
|
} | null>;
|
|
165
176
|
readonly SharedAudioContextProvider: import("react").FC<{
|
|
166
177
|
readonly numberOfAudioTags: number;
|
|
@@ -422,9 +433,16 @@ export declare const Internals: {
|
|
|
422
433
|
readonly TimelinePosition: typeof TimelinePosition;
|
|
423
434
|
readonly DelayRenderContextType: import("react").Context<import("./delay-render.js").DelayRenderScope | null>;
|
|
424
435
|
readonly TimelineContext: import("react").Context<TimelineContextValue>;
|
|
436
|
+
readonly AbsoluteTimeContext: import("react").Context<TimelineContextValue>;
|
|
425
437
|
readonly RenderAssetManagerProvider: import("react").FC<{
|
|
426
438
|
children: React.ReactNode;
|
|
427
439
|
collectAssets: null | React.RefObject<import("./RenderAssetManager.js").CollectAssetsRef | null>;
|
|
428
440
|
}>;
|
|
441
|
+
readonly getEffectiveVisualModeValue: ({ codeValue, runtimeValue, dragOverrideValue, defaultValue, }: {
|
|
442
|
+
codeValue: CanUpdateSequencePropStatus | null;
|
|
443
|
+
runtimeValue: unknown;
|
|
444
|
+
dragOverrideValue: unknown;
|
|
445
|
+
defaultValue: unknown;
|
|
446
|
+
}) => unknown;
|
|
429
447
|
};
|
|
430
|
-
export type { CompositionManagerContext, CompProps, LoggingContextValue, MediaVolumeContextValue, RemotionEnvironment, SequenceFieldSchema, SequenceSchema, SerializedJSONWithCustomFields, SetMediaVolumeContextValue, SetTimelineContextValue, TCompMetadata, TComposition, TimelineContextValue, TRenderAsset, TSequence, WatchRemotionStaticFilesPayload, };
|
|
448
|
+
export type { CompositionManagerContext, ResolvedStackLocation, CompProps, LoggingContextValue, MediaVolumeContextValue, RemotionEnvironment, SequenceFieldSchema, SequenceSchema, SerializedJSONWithCustomFields, SetMediaVolumeContextValue, SetTimelineContextValue, TCompMetadata, TComposition, TimelineContextValue, TRenderAsset, TSequence, WatchRemotionStaticFilesPayload, ScheduleAudioNodeOptions, CanUpdateSequencePropStatus, ScheduleAudioNodeResult, };
|
package/dist/cjs/internals.js
CHANGED
|
@@ -49,6 +49,7 @@ const CSSUtils = __importStar(require("./default-css.js"));
|
|
|
49
49
|
const default_css_js_1 = require("./default-css.js");
|
|
50
50
|
const EditorProps_js_1 = require("./EditorProps.js");
|
|
51
51
|
const enable_sequence_stack_traces_js_1 = require("./enable-sequence-stack-traces.js");
|
|
52
|
+
const get_effective_visual_mode_value_js_1 = require("./get-effective-visual-mode-value.js");
|
|
52
53
|
const get_preview_dom_element_js_1 = require("./get-preview-dom-element.js");
|
|
53
54
|
const get_remotion_environment_js_1 = require("./get-remotion-environment.js");
|
|
54
55
|
const input_props_override_js_1 = require("./input-props-override.js");
|
|
@@ -68,6 +69,7 @@ const RemotionRoot_js_1 = require("./RemotionRoot.js");
|
|
|
68
69
|
const RenderAssetManager_js_1 = require("./RenderAssetManager.js");
|
|
69
70
|
const resolve_video_config_js_1 = require("./resolve-video-config.js");
|
|
70
71
|
const ResolveCompositionConfig_js_1 = require("./ResolveCompositionConfig.js");
|
|
72
|
+
const sequence_stack_traces_js_1 = require("./sequence-stack-traces.js");
|
|
71
73
|
const SequenceContext_js_1 = require("./SequenceContext.js");
|
|
72
74
|
const SequenceManager_js_1 = require("./SequenceManager.js");
|
|
73
75
|
const setup_env_variables_js_1 = require("./setup-env-variables.js");
|
|
@@ -106,6 +108,7 @@ exports.Internals = {
|
|
|
106
108
|
useUnsafeVideoConfig: use_unsafe_video_config_js_1.useUnsafeVideoConfig,
|
|
107
109
|
useFrameForVolumeProp: use_audio_frame_js_1.useFrameForVolumeProp,
|
|
108
110
|
useTimelinePosition: TimelinePosition.useTimelinePosition,
|
|
111
|
+
useAbsoluteTimelinePosition: TimelinePosition.useAbsoluteTimelinePosition,
|
|
109
112
|
evaluateVolume: volume_prop_js_1.evaluateVolume,
|
|
110
113
|
getAbsoluteSrc: absolute_src_js_1.getAbsoluteSrc,
|
|
111
114
|
Timeline: TimelinePosition,
|
|
@@ -115,8 +118,9 @@ exports.Internals = {
|
|
|
115
118
|
VideoForPreview: VideoForPreview_js_1.VideoForPreview,
|
|
116
119
|
CompositionManager: CompositionManagerContext_js_1.CompositionManager,
|
|
117
120
|
CompositionSetters: CompositionManagerContext_js_1.CompositionSetters,
|
|
118
|
-
|
|
121
|
+
VisualModeOverridesContext: SequenceManager_js_1.VisualModeOverridesContext,
|
|
119
122
|
SequenceManager: SequenceManager_js_1.SequenceManager,
|
|
123
|
+
SequenceStackTracesUpdateContext: sequence_stack_traces_js_1.SequenceStackTracesUpdateContext,
|
|
120
124
|
SequenceVisibilityToggleContext: SequenceManager_js_1.SequenceVisibilityToggleContext,
|
|
121
125
|
useSchema: use_schema_js_1.useSchema,
|
|
122
126
|
useSequenceControlOverride: use_sequence_control_override_js_1.useSequenceControlOverride,
|
|
@@ -200,5 +204,7 @@ exports.Internals = {
|
|
|
200
204
|
TimelinePosition,
|
|
201
205
|
DelayRenderContextType: use_delay_render_js_1.DelayRenderContextType,
|
|
202
206
|
TimelineContext: TimelineContext_js_1.TimelineContext,
|
|
207
|
+
AbsoluteTimeContext: TimelineContext_js_1.AbsoluteTimeContext,
|
|
203
208
|
RenderAssetManagerProvider: RenderAssetManager_js_1.RenderAssetManagerProvider,
|
|
209
|
+
getEffectiveVisualModeValue: get_effective_visual_mode_value_js_1.getEffectiveVisualModeValue,
|
|
204
210
|
};
|
|
@@ -3,13 +3,14 @@ export type NumberFieldSchema = {
|
|
|
3
3
|
min?: number;
|
|
4
4
|
max?: number;
|
|
5
5
|
step?: number;
|
|
6
|
-
default
|
|
6
|
+
default: number | undefined;
|
|
7
7
|
description?: string;
|
|
8
8
|
};
|
|
9
9
|
export type BooleanFieldSchema = {
|
|
10
10
|
type: 'boolean';
|
|
11
|
-
default
|
|
11
|
+
default: boolean;
|
|
12
12
|
description?: string;
|
|
13
13
|
};
|
|
14
14
|
export type SequenceFieldSchema = NumberFieldSchema | BooleanFieldSchema;
|
|
15
15
|
export type SequenceSchema = Record<string, SequenceFieldSchema>;
|
|
16
|
+
export type SchemaKeysRecord<S extends SequenceSchema> = Record<keyof S, unknown>;
|
|
@@ -4,9 +4,5 @@ export type ResolvedStackLocation = {
|
|
|
4
4
|
column: number | null;
|
|
5
5
|
source: string | null;
|
|
6
6
|
};
|
|
7
|
-
export type SequenceStackTracesContextType = {
|
|
8
|
-
resolvedStacks: Record<string, ResolvedStackLocation | null>;
|
|
9
|
-
};
|
|
10
|
-
export declare const SequenceStackTracesContext: React.Context<SequenceStackTracesContextType>;
|
|
11
7
|
export type UpdateResolvedStackTraceFn = (stack: string, location: ResolvedStackLocation | null) => void;
|
|
12
8
|
export declare const SequenceStackTracesUpdateContext: React.Context<UpdateResolvedStackTraceFn>;
|
|
@@ -3,9 +3,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.SequenceStackTracesUpdateContext =
|
|
6
|
+
exports.SequenceStackTracesUpdateContext = void 0;
|
|
7
7
|
const react_1 = __importDefault(require("react"));
|
|
8
|
-
exports.SequenceStackTracesContext = react_1.default.createContext({
|
|
9
|
-
resolvedStacks: {},
|
|
10
|
-
});
|
|
11
8
|
exports.SequenceStackTracesUpdateContext = react_1.default.createContext(() => { });
|
|
@@ -8,6 +8,7 @@ export declare const persistCurrentFrame: (time: CurrentTimePerComposition) => v
|
|
|
8
8
|
export declare const getInitialFrameState: () => CurrentTimePerComposition;
|
|
9
9
|
export declare const getFrameForComposition: (composition: string) => number;
|
|
10
10
|
export declare const useTimelinePosition: () => number;
|
|
11
|
+
export declare const useAbsoluteTimelinePosition: () => number;
|
|
11
12
|
export declare const useTimelineSetFrame: () => ((u: React.SetStateAction<Record<string, number>>) => void);
|
|
12
13
|
type PlayingReturnType = readonly [
|
|
13
14
|
boolean,
|