remotion 3.2.8 → 3.2.11
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/.turbo/turbo-build.log +5 -5
- package/dist/CompositionManager.d.ts +3 -0
- package/dist/CompositionManager.js +9 -3
- package/dist/Sequence.js +12 -16
- package/dist/audio/AudioForRendering.js +5 -2
- package/dist/config.d.ts +6 -0
- package/dist/index.d.ts +5 -0
- package/dist/internals.d.ts +12 -1
- package/dist/use-media-in-timeline.js +8 -5
- package/dist/use-video.d.ts +13 -1
- package/dist/use-video.js +16 -3
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/video/OffthreadVideoForRendering.js +4 -2
- package/dist/video/VideoForRendering.js +4 -2
- package/package.json +2 -2
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
[
|
|
2
|
-
[
|
|
3
|
-
[
|
|
4
|
-
[
|
|
5
|
-
[
|
|
1
|
+
[33mremotion:build: [0mcache hit, replaying output [2m4d866b4a1e0f5d2c[0m
|
|
2
|
+
[33mremotion:build: [0m
|
|
3
|
+
[33mremotion:build: [0m> remotion@3.2.10 build /Users/jonathanburger/remotion/packages/core
|
|
4
|
+
[33mremotion:build: [0m> tsc -d
|
|
5
|
+
[33mremotion:build: [0m
|
|
@@ -50,6 +50,7 @@ export declare type TAsset = {
|
|
|
50
50
|
mediaFrame: number;
|
|
51
51
|
playbackRate: number;
|
|
52
52
|
};
|
|
53
|
+
declare type BaseMetadata = Pick<TCompMetadata, 'durationInFrames' | 'fps' | 'defaultProps' | 'height' | 'width'>;
|
|
53
54
|
export declare type CompositionManagerContext = {
|
|
54
55
|
compositions: TComposition[];
|
|
55
56
|
registerComposition: <T>(comp: TComposition<T>) => void;
|
|
@@ -58,6 +59,8 @@ export declare type CompositionManagerContext = {
|
|
|
58
59
|
unregisterFolder: (name: string, parent: string | null) => void;
|
|
59
60
|
currentComposition: string | null;
|
|
60
61
|
setCurrentComposition: (curr: string) => void;
|
|
62
|
+
setCurrentCompositionMetadata: (metadata: BaseMetadata) => void;
|
|
63
|
+
currentCompositionMetadata: BaseMetadata | null;
|
|
61
64
|
registerSequence: (seq: TSequence) => void;
|
|
62
65
|
unregisterSequence: (id: string) => void;
|
|
63
66
|
registerAsset: (asset: TAsset) => void;
|
|
@@ -34,6 +34,7 @@ exports.CompositionManager = (0, react_1.createContext)({
|
|
|
34
34
|
unregisterFolder: () => undefined,
|
|
35
35
|
currentComposition: null,
|
|
36
36
|
setCurrentComposition: () => undefined,
|
|
37
|
+
setCurrentCompositionMetadata: () => undefined,
|
|
37
38
|
registerSequence: () => undefined,
|
|
38
39
|
unregisterSequence: () => undefined,
|
|
39
40
|
registerAsset: () => undefined,
|
|
@@ -41,6 +42,7 @@ exports.CompositionManager = (0, react_1.createContext)({
|
|
|
41
42
|
sequences: [],
|
|
42
43
|
assets: [],
|
|
43
44
|
folders: [],
|
|
45
|
+
currentCompositionMetadata: null,
|
|
44
46
|
});
|
|
45
47
|
exports.compositionsRef = react_1.default.createRef();
|
|
46
48
|
const CompositionManagerProvider = ({ children }) => {
|
|
@@ -51,6 +53,7 @@ const CompositionManagerProvider = ({ children }) => {
|
|
|
51
53
|
const [assets, setAssets] = (0, react_1.useState)([]);
|
|
52
54
|
const [folders, setFolders] = (0, react_1.useState)([]);
|
|
53
55
|
const [sequences, setSequences] = (0, react_1.useState)([]);
|
|
56
|
+
const [currentCompositionMetadata, setCurrentCompositionMetadata] = (0, react_1.useState)(null);
|
|
54
57
|
const registerComposition = (0, react_1.useCallback)((comp) => {
|
|
55
58
|
setCompositions((comps) => {
|
|
56
59
|
if (comps.find((c) => c.id === comp.id)) {
|
|
@@ -127,21 +130,24 @@ const CompositionManagerProvider = ({ children }) => {
|
|
|
127
130
|
folders,
|
|
128
131
|
registerFolder,
|
|
129
132
|
unregisterFolder,
|
|
133
|
+
currentCompositionMetadata,
|
|
134
|
+
setCurrentCompositionMetadata,
|
|
130
135
|
};
|
|
131
136
|
}, [
|
|
132
137
|
compositions,
|
|
133
|
-
currentComposition,
|
|
134
138
|
registerComposition,
|
|
135
|
-
registerSequence,
|
|
136
139
|
unregisterComposition,
|
|
140
|
+
currentComposition,
|
|
141
|
+
registerSequence,
|
|
137
142
|
unregisterSequence,
|
|
138
143
|
registerAsset,
|
|
139
144
|
unregisterAsset,
|
|
140
145
|
sequences,
|
|
141
146
|
assets,
|
|
147
|
+
folders,
|
|
142
148
|
registerFolder,
|
|
143
149
|
unregisterFolder,
|
|
144
|
-
|
|
150
|
+
currentCompositionMetadata,
|
|
145
151
|
]);
|
|
146
152
|
return ((0, jsx_runtime_1.jsx)(exports.CompositionManager.Provider, { value: contextValue, children: children }));
|
|
147
153
|
};
|
package/dist/Sequence.js
CHANGED
|
@@ -5,10 +5,11 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
5
5
|
const react_1 = require("react");
|
|
6
6
|
const AbsoluteFill_1 = require("./AbsoluteFill");
|
|
7
7
|
const CompositionManager_1 = require("./CompositionManager");
|
|
8
|
+
const get_environment_1 = require("./get-environment");
|
|
8
9
|
const get_timeline_clip_name_1 = require("./get-timeline-clip-name");
|
|
9
10
|
const nonce_1 = require("./nonce");
|
|
10
11
|
const timeline_position_state_1 = require("./timeline-position-state");
|
|
11
|
-
const
|
|
12
|
+
const use_video_config_1 = require("./use-video-config");
|
|
12
13
|
exports.SequenceContext = (0, react_1.createContext)(null);
|
|
13
14
|
const Sequence = ({ from, durationInFrames = Infinity, children, name, showInTimeline = true, showLoopTimesInTimeline, ...other }) => {
|
|
14
15
|
const { layout = 'absolute-fill' } = other;
|
|
@@ -18,7 +19,6 @@ const Sequence = ({ from, durationInFrames = Infinity, children, name, showInTim
|
|
|
18
19
|
const cumulatedFrom = parentSequence
|
|
19
20
|
? parentSequence.cumulatedFrom + parentSequence.relativeFrom
|
|
20
21
|
: 0;
|
|
21
|
-
const actualFrom = cumulatedFrom + from;
|
|
22
22
|
const nonce = (0, nonce_1.useNonce)();
|
|
23
23
|
if (layout !== 'absolute-fill' && layout !== 'none') {
|
|
24
24
|
throw new TypeError(`The layout prop of <Sequence /> expects either "absolute-fill" or "none", but you passed: ${layout}`);
|
|
@@ -44,15 +44,11 @@ const Sequence = ({ from, durationInFrames = Infinity, children, name, showInTim
|
|
|
44
44
|
throw new TypeError(`The "from" prop of a sequence must be an integer, but got ${from}.`);
|
|
45
45
|
}
|
|
46
46
|
const absoluteFrame = (0, timeline_position_state_1.useTimelinePosition)();
|
|
47
|
-
const
|
|
48
|
-
const
|
|
49
|
-
?
|
|
50
|
-
:
|
|
51
|
-
const actualDurationInFrames = Math.min(
|
|
52
|
-
? Math.min(parentSequence.durationInFrames +
|
|
53
|
-
(parentSequence.cumulatedFrom + parentSequence.relativeFrom) -
|
|
54
|
-
actualFrom, durationInFrames)
|
|
55
|
-
: durationInFrames);
|
|
47
|
+
const videoConfig = (0, use_video_config_1.useVideoConfig)();
|
|
48
|
+
const parentSequenceDuration = parentSequence
|
|
49
|
+
? Math.min(parentSequence.durationInFrames - from, durationInFrames)
|
|
50
|
+
: durationInFrames;
|
|
51
|
+
const actualDurationInFrames = Math.max(0, Math.min(videoConfig.durationInFrames - from, parentSequenceDuration));
|
|
56
52
|
const { registerSequence, unregisterSequence } = (0, react_1.useContext)(CompositionManager_1.CompositionManager);
|
|
57
53
|
const contextValue = (0, react_1.useMemo)(() => {
|
|
58
54
|
var _a;
|
|
@@ -75,6 +71,9 @@ const Sequence = ({ from, durationInFrames = Infinity, children, name, showInTim
|
|
|
75
71
|
}, [children, name]);
|
|
76
72
|
(0, react_1.useEffect)(() => {
|
|
77
73
|
var _a;
|
|
74
|
+
if ((0, get_environment_1.getRemotionEnvironment)() !== 'preview') {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
78
77
|
registerSequence({
|
|
79
78
|
from,
|
|
80
79
|
duration: actualDurationInFrames,
|
|
@@ -92,7 +91,6 @@ const Sequence = ({ from, durationInFrames = Infinity, children, name, showInTim
|
|
|
92
91
|
};
|
|
93
92
|
}, [
|
|
94
93
|
durationInFrames,
|
|
95
|
-
actualFrom,
|
|
96
94
|
id,
|
|
97
95
|
name,
|
|
98
96
|
registerSequence,
|
|
@@ -106,10 +104,8 @@ const Sequence = ({ from, durationInFrames = Infinity, children, name, showInTim
|
|
|
106
104
|
nonce,
|
|
107
105
|
showLoopTimesInTimeline,
|
|
108
106
|
]);
|
|
109
|
-
const endThreshold =
|
|
110
|
-
|
|
111
|
-
})();
|
|
112
|
-
const content = absoluteFrame < actualFrom
|
|
107
|
+
const endThreshold = cumulatedFrom + from + durationInFrames - 1;
|
|
108
|
+
const content = absoluteFrame < cumulatedFrom + from
|
|
113
109
|
? null
|
|
114
110
|
: absoluteFrame > endThreshold
|
|
115
111
|
? null
|
|
@@ -22,8 +22,8 @@ const AudioForRenderingRefForwardingFunction = (props, ref) => {
|
|
|
22
22
|
// but at the same time the same on all threads
|
|
23
23
|
const id = (0, react_1.useMemo)(() => {
|
|
24
24
|
var _a;
|
|
25
|
-
return `audio-${(0, random_1.random)((_a = props.src) !== null && _a !== void 0 ? _a : '')}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.relativeFrom}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.cumulatedFrom}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.durationInFrames}
|
|
26
|
-
}, [props.
|
|
25
|
+
return `audio-${(0, random_1.random)((_a = props.src) !== null && _a !== void 0 ? _a : '')}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.relativeFrom}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.cumulatedFrom}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.durationInFrames}`;
|
|
26
|
+
}, [props.src, sequenceContext]);
|
|
27
27
|
const { volume: volumeProp, playbackRate, ...nativeProps } = props;
|
|
28
28
|
const volume = (0, volume_prop_1.evaluateVolume)({
|
|
29
29
|
volume: volumeProp,
|
|
@@ -44,6 +44,9 @@ const AudioForRenderingRefForwardingFunction = (props, ref) => {
|
|
|
44
44
|
if (props.muted) {
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
|
+
if (volume <= 0) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
47
50
|
registerAsset({
|
|
48
51
|
type: 'audio',
|
|
49
52
|
src: (0, absolute_src_1.getAbsoluteSrc)(props.src),
|
package/dist/config.d.ts
CHANGED
|
@@ -20,6 +20,12 @@ export declare type ConfigType = {
|
|
|
20
20
|
* @default 15
|
|
21
21
|
*/
|
|
22
22
|
readonly setMaxTimelineTracks: (maxTracks: number) => void;
|
|
23
|
+
/**
|
|
24
|
+
* Enable Keyboard shortcuts in the Remotion Preview.
|
|
25
|
+
* @param enabled Boolean whether to enable the keyboard shortcuts
|
|
26
|
+
* @default true
|
|
27
|
+
*/
|
|
28
|
+
readonly setKeyboardShortcutsEnabled: (enableShortcuts: boolean) => void;
|
|
23
29
|
};
|
|
24
30
|
readonly Bundling: {
|
|
25
31
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -34,6 +34,11 @@ export declare type BundleState = {
|
|
|
34
34
|
} | {
|
|
35
35
|
type: 'composition';
|
|
36
36
|
compositionName: string;
|
|
37
|
+
compositionDefaultProps: unknown;
|
|
38
|
+
compositionHeight: number;
|
|
39
|
+
compositionDurationInFrames: number;
|
|
40
|
+
compositionWidth: number;
|
|
41
|
+
compositionFps: number;
|
|
37
42
|
};
|
|
38
43
|
export * from './AbsoluteFill';
|
|
39
44
|
export * from './audio';
|
package/dist/internals.d.ts
CHANGED
|
@@ -17,7 +17,18 @@ export declare const Internals: {
|
|
|
17
17
|
RemotionRoot: import("react").FC<{
|
|
18
18
|
children: import("react").ReactNode;
|
|
19
19
|
}>;
|
|
20
|
-
useVideo: () =>
|
|
20
|
+
useVideo: () => {
|
|
21
|
+
height: number;
|
|
22
|
+
width: number;
|
|
23
|
+
fps: number;
|
|
24
|
+
durationInFrames: number;
|
|
25
|
+
defaultProps: unknown;
|
|
26
|
+
id: string;
|
|
27
|
+
folderName: string | null;
|
|
28
|
+
parentFolderName: string | null;
|
|
29
|
+
component: import("react").LazyExoticComponent<import("react").ComponentType<unknown>>;
|
|
30
|
+
nonce: number;
|
|
31
|
+
} | null;
|
|
21
32
|
getRoot: () => import("react").FC<{}> | null;
|
|
22
33
|
useMediaVolumeState: () => readonly [number, (u: number) => void];
|
|
23
34
|
useMediaMutedState: () => readonly [boolean, (u: import("react").SetStateAction<boolean>) => void];
|
|
@@ -5,6 +5,7 @@ const react_1 = require("react");
|
|
|
5
5
|
const use_audio_frame_1 = require("./audio/use-audio-frame");
|
|
6
6
|
const CompositionManager_1 = require("./CompositionManager");
|
|
7
7
|
const get_asset_file_name_1 = require("./get-asset-file-name");
|
|
8
|
+
const get_environment_1 = require("./get-environment");
|
|
8
9
|
const nonce_1 = require("./nonce");
|
|
9
10
|
const play_and_handle_not_allowed_error_1 = require("./play-and-handle-not-allowed-error");
|
|
10
11
|
const Sequence_1 = require("./Sequence");
|
|
@@ -32,11 +33,9 @@ const useMediaInTimeline = ({ volume, mediaVolume, mediaRef, src, mediaType, })
|
|
|
32
33
|
const [id] = (0, react_1.useState)(() => String(Math.random()));
|
|
33
34
|
const [initialVolume] = (0, react_1.useState)(() => volume);
|
|
34
35
|
const nonce = (0, nonce_1.useNonce)();
|
|
35
|
-
const duration =
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
: videoConfig.durationInFrames;
|
|
39
|
-
})();
|
|
36
|
+
const duration = parentSequence
|
|
37
|
+
? Math.min(parentSequence.durationInFrames, videoConfig.durationInFrames)
|
|
38
|
+
: videoConfig.durationInFrames;
|
|
40
39
|
const doesVolumeChange = typeof volume === 'function';
|
|
41
40
|
const volumes = (0, react_1.useMemo)(() => {
|
|
42
41
|
if (typeof volume === 'number') {
|
|
@@ -66,6 +65,10 @@ const useMediaInTimeline = ({ volume, mediaVolume, mediaRef, src, mediaType, })
|
|
|
66
65
|
if (!src) {
|
|
67
66
|
throw new Error('No src passed');
|
|
68
67
|
}
|
|
68
|
+
if ((0, get_environment_1.getRemotionEnvironment)() !== 'preview' &&
|
|
69
|
+
process.env.NODE_ENV !== 'test') {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
69
72
|
registerSequence({
|
|
70
73
|
type: mediaType,
|
|
71
74
|
src,
|
package/dist/use-video.d.ts
CHANGED
|
@@ -1 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
export declare const useVideo: () => {
|
|
3
|
+
height: number;
|
|
4
|
+
width: number;
|
|
5
|
+
fps: number;
|
|
6
|
+
durationInFrames: number;
|
|
7
|
+
defaultProps: unknown;
|
|
8
|
+
id: string;
|
|
9
|
+
folderName: string | null;
|
|
10
|
+
parentFolderName: string | null;
|
|
11
|
+
component: import("react").LazyExoticComponent<import("react").ComponentType<unknown>>;
|
|
12
|
+
nonce: number;
|
|
13
|
+
} | null;
|
package/dist/use-video.js
CHANGED
|
@@ -7,9 +7,22 @@ const useVideo = () => {
|
|
|
7
7
|
const context = (0, react_1.useContext)(CompositionManager_1.CompositionManager);
|
|
8
8
|
return (0, react_1.useMemo)(() => {
|
|
9
9
|
var _a;
|
|
10
|
-
|
|
10
|
+
const selected = context.compositions.find((c) => {
|
|
11
11
|
return c.id === context.currentComposition;
|
|
12
|
-
})
|
|
13
|
-
|
|
12
|
+
});
|
|
13
|
+
if (selected) {
|
|
14
|
+
return {
|
|
15
|
+
...selected,
|
|
16
|
+
// We override the selected metadata with the metadata that was passed to renderMedia(),
|
|
17
|
+
// and don't allow it to be changed during render anymore
|
|
18
|
+
...((_a = context.currentCompositionMetadata) !== null && _a !== void 0 ? _a : {}),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}, [
|
|
23
|
+
context.compositions,
|
|
24
|
+
context.currentComposition,
|
|
25
|
+
context.currentCompositionMetadata,
|
|
26
|
+
]);
|
|
14
27
|
};
|
|
15
28
|
exports.useVideo = useVideo;
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "3.2.
|
|
1
|
+
export declare const VERSION = "3.2.11";
|
package/dist/version.js
CHANGED
|
@@ -30,9 +30,8 @@ const OffthreadVideoForRendering = ({ onError, volume: volumeProp, playbackRate,
|
|
|
30
30
|
}
|
|
31
31
|
// Generate a string that's as unique as possible for this asset
|
|
32
32
|
// but at the same time the same on all threads
|
|
33
|
-
const id = (0, react_1.useMemo)(() => `
|
|
33
|
+
const id = (0, react_1.useMemo)(() => `offthreadvideo-${(0, random_1.random)(src !== null && src !== void 0 ? src : '')}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.cumulatedFrom}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.relativeFrom}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.durationInFrames}`, [
|
|
34
34
|
src,
|
|
35
|
-
muted,
|
|
36
35
|
sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.cumulatedFrom,
|
|
37
36
|
sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.relativeFrom,
|
|
38
37
|
sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.durationInFrames,
|
|
@@ -55,6 +54,9 @@ const OffthreadVideoForRendering = ({ onError, volume: volumeProp, playbackRate,
|
|
|
55
54
|
if (muted) {
|
|
56
55
|
return;
|
|
57
56
|
}
|
|
57
|
+
if (volume <= 0) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
58
60
|
registerAsset({
|
|
59
61
|
type: 'video',
|
|
60
62
|
src: (0, absolute_src_1.getAbsoluteSrc)(src),
|
|
@@ -29,10 +29,9 @@ const VideoForRenderingForwardFunction = ({ onError, volume: volumeProp, playbac
|
|
|
29
29
|
// but at the same time the same on all threads
|
|
30
30
|
const id = (0, react_1.useMemo)(() => {
|
|
31
31
|
var _a;
|
|
32
|
-
return `video-${(0, random_1.random)((_a = props.src) !== null && _a !== void 0 ? _a : '')}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.cumulatedFrom}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.relativeFrom}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.durationInFrames}
|
|
32
|
+
return `video-${(0, random_1.random)((_a = props.src) !== null && _a !== void 0 ? _a : '')}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.cumulatedFrom}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.relativeFrom}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.durationInFrames}`;
|
|
33
33
|
}, [
|
|
34
34
|
props.src,
|
|
35
|
-
props.muted,
|
|
36
35
|
sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.cumulatedFrom,
|
|
37
36
|
sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.relativeFrom,
|
|
38
37
|
sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.durationInFrames,
|
|
@@ -52,6 +51,9 @@ const VideoForRenderingForwardFunction = ({ onError, volume: volumeProp, playbac
|
|
|
52
51
|
if (props.muted) {
|
|
53
52
|
return;
|
|
54
53
|
}
|
|
54
|
+
if (volume <= 0) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
55
57
|
if (!window.remotion_audioEnabled) {
|
|
56
58
|
return;
|
|
57
59
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "remotion",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.11",
|
|
4
4
|
"description": "Render videos in React",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -54,5 +54,5 @@
|
|
|
54
54
|
"publishConfig": {
|
|
55
55
|
"access": "public"
|
|
56
56
|
},
|
|
57
|
-
"gitHead": "
|
|
57
|
+
"gitHead": "43d44e718e41200aea544719e9963482f9a65120"
|
|
58
58
|
}
|