shiveshnavin commited on
Commit
8bdc503
·
1 Parent(s): a97b6c8

Backup before bye bye to frame based resumable

Browse files
.gitignore CHANGED
@@ -18,4 +18,5 @@ functions/*.log
18
  uploads/
19
  uploads/**
20
  audit_log_creds.json
21
- build/
 
 
18
  uploads/
19
  uploads/**
20
  audit_log_creds.json
21
+ build/
22
+ frames/
package.json CHANGED
@@ -10,6 +10,8 @@
10
  "submodule": "git submodule init && git submodule update",
11
  "ci": "echo Runnin on CI",
12
  "start": "node server.js",
 
 
13
  "extract32": "set MODIFY_FILES=1 && node app.js",
14
  "extract": "MODIFY_FILES=1 && node app.js",
15
  "preview": "remotion studio --log=verbose",
 
10
  "submodule": "git submodule init && git submodule update",
11
  "ci": "echo Runnin on CI",
12
  "start": "node server.js",
13
+ "bundle": "echo -n | remotion bundle",
14
+ "skip-font-warn": "sed -E -i \"s/\\bfontsLoaded[[:space:]]*>[[:space:]]*20\\b/fontsLoaded > 20000/g\" build/bundle.js",
15
  "extract32": "set MODIFY_FILES=1 && node app.js",
16
  "extract": "MODIFY_FILES=1 && node app.js",
17
  "preview": "remotion studio --log=verbose",
src/common/Error.tsx CHANGED
@@ -2,7 +2,10 @@ import * as Montserrat from "@remotion/google-fonts/Montserrat";
2
 
3
  export function ErrorMsg(props: { error?: string, children?: any }) {
4
 
5
- const { fontFamily } = Montserrat.loadFont("normal", { weights: ["500"] });
 
 
 
6
  const baseStyle = {
7
  borderColor: "transparent",
8
  borderRadius: "2rem",
 
2
 
3
  export function ErrorMsg(props: { error?: string, children?: any }) {
4
 
5
+ const { fontFamily } = Montserrat.loadFont("normal", {
6
+ weights: ["500"],
7
+ ignoreTooManyRequestsWarning: true
8
+ });
9
  const baseStyle = {
10
  borderColor: "transparent",
11
  borderRadius: "2rem",
src/common/PosterSingleTextWithBG.tsx CHANGED
@@ -38,7 +38,10 @@ export const PosterSingleTextWithBG: React.FC<Transcript> = (item) => {
38
  padding: "0.2rem 1.5rem",
39
  };
40
 
41
- const { fontFamily } = Montserrat.loadFont("normal", { weights: ["400"] });
 
 
 
42
  let curZoom = 1.5
43
  let lines = audioCaption?.words || [{
44
  word: text
 
38
  padding: "0.2rem 1.5rem",
39
  };
40
 
41
+ const { fontFamily } = Montserrat.loadFont("normal", {
42
+ weights: ["400"],
43
+ ignoreTooManyRequestsWarning: true
44
+ });
45
  let curZoom = 1.5
46
  let lines = audioCaption?.words || [{
47
  word: text
src/ig-reel/IG2LineMotivationalScene.tsx CHANGED
@@ -13,7 +13,10 @@ export default function IG2LineMotivationalScene(props: { meta: Meta; item: Tran
13
  const media = mediaAbsPaths[0];
14
  const watermark = mediaAbsPaths[1];
15
  const bgMusicPath = RenderUtils.tryStaticFile(audioFullPath);
16
- const { fontFamily } = Montserrat.loadFont("normal", { weights: ["400"] });
 
 
 
17
  const frame = useCurrentFrame();
18
 
19
 
 
13
  const media = mediaAbsPaths[0];
14
  const watermark = mediaAbsPaths[1];
15
  const bgMusicPath = RenderUtils.tryStaticFile(audioFullPath);
16
+ const { fontFamily } = Montserrat.loadFont("normal", {
17
+ weights: ["400"],
18
+ ignoreTooManyRequestsWarning: true
19
+ });
20
  const frame = useCurrentFrame();
21
 
22
 
src/ig-reel/IGReelComposition.tsx CHANGED
@@ -21,7 +21,9 @@ import { wipe } from "@remotion/transitions/wipe";
21
  import { TransitionAnims } from '../anims/transitions';
22
 
23
  export const IGReelComposition: React.FC = (props: OriginalManuscript) => {
24
- const { fontFamily } = loadFont();
 
 
25
  let { meta, bgMusic, bgMusicDuration, bgMusicVolume } = props
26
  let transcripts: Transcript[] = props.contents
27
  let fps = meta.fps
 
21
  import { TransitionAnims } from '../anims/transitions';
22
 
23
  export const IGReelComposition: React.FC = (props: OriginalManuscript) => {
24
+ const { fontFamily } = loadFont("normal", {
25
+ ignoreTooManyRequestsWarning: true
26
+ });
27
  let { meta, bgMusic, bgMusicDuration, bgMusicVolume } = props
28
  let transcripts: Transcript[] = props.contents
29
  let fps = meta.fps
src/linkedin-video/LinkedinFullSysDesignComposition.tsx CHANGED
@@ -13,7 +13,9 @@ import { AnimGraphScene } from './AnimGraphScene';
13
  import GeneralSubtitles from '../subtitles/general_Subtitles';
14
 
15
  export const LinkedinFullSysDesignComposition: React.FC = (props: OriginalManuscript) => {
16
- const { fontFamily } = loadFont();
 
 
17
  let { meta, bgMusic, bgMusicDuration, bgMusicVolume } = props
18
  let transcripts: Transcript[] = props.contents
19
  let fps = meta.fps
 
13
  import GeneralSubtitles from '../subtitles/general_Subtitles';
14
 
15
  export const LinkedinFullSysDesignComposition: React.FC = (props: OriginalManuscript) => {
16
+ const { fontFamily } = loadFont("normal", {
17
+ ignoreTooManyRequestsWarning: true
18
+ });
19
  let { meta, bgMusic, bgMusicDuration, bgMusicVolume } = props
20
  let transcripts: Transcript[] = props.contents
21
  let fps = meta.fps
src/subtitles/general_Subtitles.tsx CHANGED
@@ -15,7 +15,8 @@ const GeneralSubtitles: React.FC<{ group: Group, word: Word, position: 'start' |
15
  fontSize = '6em',
16
  position = 'end' }) => {
17
 
18
- let { fontFamily } = SubtitleFont.loadFont("normal", {
 
19
  weights: ['900']
20
  })
21
 
 
15
  fontSize = '6em',
16
  position = 'end' }) => {
17
 
18
+ let { fontFamily } = SubtitleFont.loadFont("normal", {
19
+ ignoreTooManyRequestsWarning: true,
20
  weights: ['900']
21
  })
22
 
src/subtitles/motivational_Subtitles.tsx CHANGED
@@ -8,7 +8,8 @@ import _ from 'lodash'
8
  const MotivationalSubtitles: React.FC<{ group: Group, word: Word, position: 'top' | 'center' | 'bottom' }> = ({ group, word: curWord, position = 'center' }) => {
9
 
10
  let { fontFamily } = Montserrat.loadFont("normal", {
11
- weights: ['900']
 
12
  })
13
 
14
  const frame = useCurrentFrame();
 
8
  const MotivationalSubtitles: React.FC<{ group: Group, word: Word, position: 'top' | 'center' | 'bottom' }> = ({ group, word: curWord, position = 'center' }) => {
9
 
10
  let { fontFamily } = Montserrat.loadFont("normal", {
11
+ weights: ['900'],
12
+ ignoreTooManyRequestsWarning: true
13
  })
14
 
15
  const frame = useCurrentFrame();
src/youtube/SectionTextWithBG.tsx CHANGED
@@ -34,7 +34,9 @@ export const SectionTextWithBG: React.FC<SequentialSceneData> = (props: Transcri
34
 
35
  const videoConfig = useVideoConfig();
36
  const { fps, width, height } = useVideoConfig();
37
- const { fontFamily } = loadFont();
 
 
38
  const frame = useCurrentFrame();
39
 
40
  let textBgColor = textColor;
 
34
 
35
  const videoConfig = useVideoConfig();
36
  const { fps, width, height } = useVideoConfig();
37
+ const { fontFamily } = loadFont("normal", {
38
+ ignoreTooManyRequestsWarning: true
39
+ });
40
  const frame = useCurrentFrame();
41
 
42
  let textBgColor = textColor;
src/youtube/SingleTextWithBG.tsx CHANGED
@@ -28,7 +28,9 @@ function adjustFontSize(text: string, fullFont: number, minFontSizeDef): number
28
  export const SingleTextWithBG: React.FC<SequentialSceneData> = ({ text, textColor = '#fff', duration, direction = 'left', bgImagePath, audioPath, emphasisOnImage }) => {
29
  const videoConfig = useVideoConfig();
30
  const { fps, width, height } = useVideoConfig();
31
- const { fontFamily } = loadFont();
 
 
32
 
33
  let textBgColor = textColor;
34
  let textFontColor = "#fff";
 
28
  export const SingleTextWithBG: React.FC<SequentialSceneData> = ({ text, textColor = '#fff', duration, direction = 'left', bgImagePath, audioPath, emphasisOnImage }) => {
29
  const videoConfig = useVideoConfig();
30
  const { fps, width, height } = useVideoConfig();
31
+ const { fontFamily } = loadFont("normal", {
32
+ ignoreTooManyRequestsWarning: true
33
+ });
34
 
35
  let textBgColor = textColor;
36
  let textFontColor = "#fff";
test-render.cjs CHANGED
@@ -1,4 +1,4 @@
1
- const { renderFrames, renderStill } = require('@remotion/renderer');
2
  const { bundle } = require('@remotion/bundler');
3
  const path = require('path');
4
  const fs = require('fs');
@@ -10,12 +10,28 @@ const { GenerateScript } = require('./src/GenerateScript.cjs')
10
  const entry = path.join(process.cwd(), 'src/index.ts'); // your Remotion entry file
11
  const originalManuScriptPath = path.join(process.cwd(), 'public/original_manuscript.json');
12
  const compositionId = 'IGReelComposition';
 
13
  const outputDir = path.join(process.cwd(), 'out');
14
  const bundleLocation = path.join(process.cwd(), 'build');
15
- (async () => {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  const ScriptStr = fs.readFileSync(originalManuScriptPath);
17
  const ScriptInput = JSON.parse(ScriptStr);
18
- const {
19
  duration,
20
  Script,
21
  contents,
@@ -29,7 +45,7 @@ const bundleLocation = path.join(process.cwd(), 'build');
29
  fps: Script.meta.fps,
30
  height: Script.meta?.resolution?.height,
31
  width: Script.meta?.resolution?.width,
32
- durationInFrames: 1,
33
  defaultProps: Object.assign(Script, {
34
  bgMusic: RenderUtils.getFileName(Script.bgMusic),
35
  contents: contents,
@@ -44,8 +60,95 @@ const bundleLocation = path.join(process.cwd(), 'build');
44
  }),
45
  },
46
  serveUrl: bundleLocation,
47
- output: path.join(outputDir, 'output.jpg')
 
 
 
 
 
 
 
 
 
 
 
 
48
  }
49
- // await renderStill(renderConfig);
50
- await renderFrames(renderConfig)
51
- })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const { renderFrames, renderStill, stitchFramesToVideo } = require('@remotion/renderer');
2
  const { bundle } = require('@remotion/bundler');
3
  const path = require('path');
4
  const fs = require('fs');
 
10
  const entry = path.join(process.cwd(), 'src/index.ts'); // your Remotion entry file
11
  const originalManuScriptPath = path.join(process.cwd(), 'public/original_manuscript.json');
12
  const compositionId = 'IGReelComposition';
13
+ const frameOutputDir = path.join(process.cwd(), 'frames');
14
  const outputDir = path.join(process.cwd(), 'out');
15
  const bundleLocation = path.join(process.cwd(), 'build');
16
+ const assetsInfoFile = path.join(process.cwd(), 'public/assetsInfo.json');
17
+
18
+ function readAssetInfo() {
19
+ if (!fs.existsSync(assetsInfoFile)) {
20
+ return undefined
21
+ }
22
+ let assetsInfoStr = fs.readFileSync(assetsInfoFile)
23
+ let assetsInfo = JSON.parse(assetsInfoStr);
24
+ return assetsInfo
25
+ }
26
+
27
+ function updateAssetInfo(assetInfoNew) {
28
+ fs.writeFileSync(assetsInfoFile, JSON.stringify(assetInfoNew))
29
+ }
30
+
31
+ export const renderSSR = async (frameRange) => {
32
  const ScriptStr = fs.readFileSync(originalManuScriptPath);
33
  const ScriptInput = JSON.parse(ScriptStr);
34
+ let {
35
  duration,
36
  Script,
37
  contents,
 
45
  fps: Script.meta.fps,
46
  height: Script.meta?.resolution?.height,
47
  width: Script.meta?.resolution?.width,
48
+ durationInFrames: duration,
49
  defaultProps: Object.assign(Script, {
50
  bgMusic: RenderUtils.getFileName(Script.bgMusic),
51
  contents: contents,
 
60
  }),
61
  },
62
  serveUrl: bundleLocation,
63
+ output: path.join(frameOutputDir, 'output.jpg'),
64
+ // additional renderer options
65
+ audioCodec: 'mp3',
66
+ imageFormat: 'jpeg',
67
+ enableMultiProcessOnLinux: true,
68
+ jpegQuality: 70,
69
+ timeoutInMilliseconds: 60000,
70
+ concurrency: 1,
71
+ gl: 'angle'
72
+ }
73
+ const fps = Script.meta?.fps;
74
+ if (!fs.existsSync(frameOutputDir)) {
75
+ fs.mkdirSync(frameOutputDir, { recursive: true });
76
  }
77
+
78
+ const files = fs.readdirSync(frameOutputDir);
79
+ const frameNamePattern = 'frame-[frame].[ext]';
80
+ const frameNamedRe = /frame-(\d+)\.(png|jpg|jpeg)$/i;
81
+ let lastIndex = -1;
82
+ for (const f of files) {
83
+ const m = f.match(frameNamedRe);
84
+ if (m) {
85
+ const idx = Number(m[1]);
86
+ if (!Number.isNaN(idx) && idx > lastIndex) lastIndex = idx;
87
+ }
88
+ }
89
+
90
+ //-------DEBUG--------//
91
+ duration = 5 * fps;
92
+ let startFrame = Math.min(duration - 1, Math.max(0, lastIndex + 1));
93
+ startFrame = 0;
94
+ //-------DEBUG--------//
95
+ if (lastIndex >= 0) {
96
+ console.log(`Found last rendered frame index ${lastIndex}, resuming from ${startFrame}`);
97
+ } else {
98
+ console.log('No existing frame-*.png found, starting from frame 0');
99
+ }
100
+
101
+ const formatMsToETA = (ms) => {
102
+ const totalSeconds = Math.ceil(ms / 1000);
103
+ const hours = Math.floor(totalSeconds / 3600);
104
+ const minutes = Math.floor((totalSeconds % 3600) / 60);
105
+ const seconds = totalSeconds % 60;
106
+ const parts = [];
107
+ if (hours) parts.push(`${hours}h`);
108
+ if (minutes) parts.push(`${minutes}min`);
109
+ if (seconds || parts.length === 0) parts.push(`${seconds}sec`);
110
+ return parts.join(' ');
111
+ };
112
+
113
+ let result = await renderFrames({
114
+ ...renderConfig,
115
+ onBrowserLog: (info) => {
116
+ console.log(`${info.type}: ${info.text}`);
117
+ console.log(
118
+ info.stackTrace
119
+ .map((stack) => {
120
+ return ` ${stack.url}:${stack.lineNumber}:${stack.columnNumber}`;
121
+ })
122
+ .join('\n'),
123
+ );
124
+ },
125
+ imageSequencePattern: frameNamePattern,
126
+ outputDir: frameOutputDir,
127
+ frameRange: frameRange ?? [0, duration - 1],
128
+ onFrameUpdate: (rendered, frameIndex, timeTakenPerFrameMs) => {
129
+
130
+ if (rendered % 10 !== 0 && frameIndex !== duration - 1) return;
131
+ const remainingFrames = Math.max(0, duration - frameIndex);
132
+ const estimatedMsLeft = remainingFrames * (timeTakenPerFrameMs || 0);
133
+ const timeLeftSeconds = formatMsToETA(estimatedMsLeft);
134
+ console.log(`Rendered ${frameIndex} of ${duration} in ${timeTakenPerFrameMs?.toFixed(0)}ms Time left ${timeLeftSeconds}`);
135
+ }
136
+ });
137
+
138
+ if (!fs.existsSync(outputDir)) {
139
+ fs.mkdirSync(outputDir, { recursive: true });
140
+ }
141
+
142
+ const resultVideo = await stitchFramesToVideo({
143
+ assetsInfo: result.assetsInfo,
144
+ ...renderConfig,
145
+ ...renderConfig.composition,
146
+ audioCodec: 'mp3',
147
+ outputLocation: 'D:\\code\\node_projects\\semibit-media-render-farm\\out\\video.mp4',
148
+ verbose: true
149
+ })
150
+
151
+ console.log('resultVideo', resultVideo)
152
+
153
+
154
+ }