shiveshnavin commited on
Commit
403f72c
·
1 Parent(s): a0ea7ba

Cleanup reels code

Browse files
src/RenderUtils.ts CHANGED
@@ -19,7 +19,72 @@ function levenshteinDistance(str1: string, str2: string) {
19
  }
20
  export class RenderUtils {
21
 
22
- public static randomElement<T>(arr: T[], seed: number): T {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  return arr[Math.floor(random(seed || 1) * arr.length)];
24
  }
25
 
 
19
  }
20
  export class RenderUtils {
21
 
22
+ public static splitWordsIntoGroups(words) {
23
+ const groups = [];
24
+ let currentGroup = [];
25
+
26
+ for (const word of words) {
27
+ if (currentGroup.length === 0) {
28
+ currentGroup.push(word);
29
+ } else if (word.sentence_end) {
30
+ currentGroup.push(word);
31
+ groups.push(currentGroup);
32
+ currentGroup = [];
33
+ } else if (currentGroup.length < 5) {
34
+ currentGroup.push(word);
35
+ } else {
36
+ groups.push(currentGroup);
37
+ currentGroup = [word];
38
+ }
39
+ }
40
+
41
+ if (currentGroup.length > 0) {
42
+ groups.push(currentGroup);
43
+ }
44
+
45
+ // Ensure each group has a maximum of 5 words
46
+ const finalGroups = [];
47
+ for (const group of groups) {
48
+ while (group.length > 5) {
49
+ finalGroups.push(group.slice(0, 5));
50
+ group.splice(0, 5);
51
+ }
52
+ finalGroups.push(group);
53
+ }
54
+
55
+ return finalGroups?.map(group => {
56
+ return {
57
+ words: group
58
+ }
59
+ });
60
+ }
61
+
62
+
63
+ public static findCurrentGroupByTime(timeSec: Number, groups) {
64
+ var t = timeSec;
65
+ let wds = groups
66
+ for (let i = 0; i < wds.length; i++) {
67
+ const x = wds[i];
68
+ if (x.start != undefined && x.end != undefined && (t >= x.start && t < x.end)) {
69
+ return x
70
+ }
71
+ }
72
+ }
73
+
74
+
75
+ public static findCurrentWord(timeSec, frames) {
76
+ var t = timeSec;
77
+ let wds = frames
78
+ for (let i = 0; i < wds.length; i++) {
79
+ const x = wds[i];
80
+ if (x.start && x.end && (t >= x.start && t < x.end)) {
81
+ return x
82
+ }
83
+ }
84
+ }
85
+
86
+
87
+ public static randomElement<T>(arr: T[], seed: string): T {
88
  return arr[Math.floor(random(seed || 1) * arr.length)];
89
  }
90
 
src/examples/SampleComposition.tsx CHANGED
@@ -1,7 +1,7 @@
1
  import { AbsoluteFill } from 'remotion';
2
  import { Logo } from './Logo';
3
- import { Subtitle } from '../Subtitle';
4
- import { Title } from '../Title';
5
  import { z } from 'zod';
6
  import { zColor } from '@remotion/zod-types';
7
 
 
1
  import { AbsoluteFill } from 'remotion';
2
  import { Logo } from './Logo';
3
+ import { Subtitle } from './Subtitle';
4
+ import { Title } from './Title';
5
  import { z } from 'zod';
6
  import { zColor } from '@remotion/zod-types';
7
 
src/ig-reel/IGMediaRender.tsx CHANGED
@@ -1,10 +1,10 @@
1
- import { AbsoluteFill, Easing, Img, Video, interpolate, staticFile, useCurrentFrame } from "remotion";
 
2
  import { DisplayMedia } from "./IGSimpleScene";
3
 
4
 
5
  export function IGMediaRender(props) {
6
  let displayMedia: DisplayMedia = props.displayMedia
7
- let frame = useCurrentFrame()
8
  let bgMediaPath = staticFile(displayMedia?.path || '')
9
  let curZoom = props.curZoom
10
 
 
1
+ //@ts-nocheck
2
+ import { Img, Video, staticFile } from "remotion";
3
  import { DisplayMedia } from "./IGSimpleScene";
4
 
5
 
6
  export function IGMediaRender(props) {
7
  let displayMedia: DisplayMedia = props.displayMedia
 
8
  let bgMediaPath = staticFile(displayMedia?.path || '')
9
  let curZoom = props.curZoom
10
 
src/ig-reel/IGReelComposition.tsx CHANGED
@@ -7,8 +7,6 @@ import { IGScene } from './IGSimpleScene';
7
  import { OriginalManuscript, Transcript } from '../models/OriginalManuscriptModel';
8
  import TransitionSeries from 'remotion-transition-series';
9
 
10
-
11
-
12
  export const IGReelComposition: React.FC = (props: OriginalManuscript) => {
13
  const { fontFamily } = loadFont();
14
  let { meta, bgMusic, bgMusicDuration } = props
@@ -51,12 +49,4 @@ export const IGReelComposition: React.FC = (props: OriginalManuscript) => {
51
 
52
  </AbsoluteFill >
53
  );
54
- };
55
-
56
-
57
- const Title: React.FC<{ title?: string, color: string }> = ({ title = "test", color }) => {
58
-
59
- return (
60
- <div style={{ backgroundColor: color, textAlign: "center", fontSize: "7em" }}>{title}</div>
61
- );
62
  };
 
7
  import { OriginalManuscript, Transcript } from '../models/OriginalManuscriptModel';
8
  import TransitionSeries from 'remotion-transition-series';
9
 
 
 
10
  export const IGReelComposition: React.FC = (props: OriginalManuscript) => {
11
  const { fontFamily } = loadFont();
12
  let { meta, bgMusic, bgMusicDuration } = props
 
49
 
50
  </AbsoluteFill >
51
  );
 
 
 
 
 
 
 
 
52
  };
src/ig-reel/IGSimpleScene.tsx CHANGED
@@ -1,12 +1,9 @@
1
  //@ts-nocheck
2
- import { AbsoluteFill, interpolate, Img, staticFile, Audio, useCurrentFrame, Video, Easing, random } from 'remotion';
3
  import React, { useEffect, useState } from 'react'
4
- import { loadFont } from "@remotion/google-fonts/MontserratAlternates";
5
- import { Series, Sequence } from "remotion";
6
  import { RenderUtils } from '../RenderUtils';
7
  import { Transcript, SectionMedia } from '../models/OriginalManuscriptModel'
8
  import axios from 'axios';
9
- import GeneralSubtitles from '../subtitles/general_Subtitles';
10
  import ExcitedSubtitles from '../subtitles/excited_Subtitles';
11
  import _ from 'lodash';
12
  import './styles.module.css'
@@ -17,8 +14,6 @@ import { Slide } from '../anims/Slide';
17
  import { Pan } from '../anims/Pan';
18
  import { Dissolve } from '../anims/Dissolve';
19
  import { SlidingDoors } from '../anims/SlidingDoors';
20
- import { Plate } from '../anims/Plate';
21
- import { GlowingStroke } from '../anims/GlowingStrike';
22
  import { IGMediaRender } from './IGMediaRender';
23
  import { Group } from '../models/Types';
24
 
@@ -29,16 +24,15 @@ export const IGScene: React.FC<any> = (props: {
29
  script: any,
30
  item: Transcript
31
  }) => {
32
- const { fontFamily } = loadFont();
33
  const [subtitles, setSubtitles] = useState(undefined)
34
  const [groups, setGroups] = useState(undefined)
35
- const [averageCharsPs, setAverageCps] = useState(undefined)
36
  const item = props.item
37
- let { title, subtitle_file, durationInSeconds } = item
38
  const { script } = props
39
  const { meta } = script
40
  const { fps } = meta
41
  const frame = useCurrentFrame();
 
42
 
43
  useEffect(() => {
44
  const subFile = staticFile(RenderUtils.getFileName(subtitle_file))
@@ -47,10 +41,7 @@ export const IGScene: React.FC<any> = (props: {
47
  if (subtitles?.default) {
48
  subtitles = subtitles.default
49
  }
50
- // let subtitles = SUBTITLES
51
- let subtitlesClone = subtitles
52
  let subs = subtitles.words
53
-
54
  let noOfCharacters = 0
55
  let groupDuration = 0
56
  for (let i = 0; i < subs.length; i++) {
@@ -87,15 +78,13 @@ export const IGScene: React.FC<any> = (props: {
87
  }
88
  }
89
  }
90
- setAverageCps(avgCps)
91
  setSubtitles(subs)
92
 
93
 
94
  let arr = subs
95
- let chunkSize = 4;
96
  let groups = [];
97
 
98
- groups = splitWordsIntoGroups(arr)
99
  groups.forEach((group) => {
100
  let words = group.words;
101
  group.start = words[0]?.start
@@ -111,7 +100,6 @@ export const IGScene: React.FC<any> = (props: {
111
  return (<></>)
112
  }
113
 
114
-
115
  let itemDurationInFrames = item.durationInSeconds * fps
116
  console.log('scriptItem.offset', frame, itemDurationInFrames)
117
 
@@ -123,11 +111,10 @@ export const IGScene: React.FC<any> = (props: {
123
 
124
 
125
  let curSecond: Number = frame / fps
126
- let word = findCurrentWord(curSecond, subtitles)
127
- let group: Group = findCurrentGroupByTime(curSecond, groups)
128
 
129
  let currentDisplayMedia: DisplayMedia = (item?.imageAbsPaths || [])[0]
130
- let transitioning = false
131
 
132
  if (!_.isEmpty(item?.imageAbsPaths)) {
133
  let frameOffest = 0
@@ -151,24 +138,8 @@ export const IGScene: React.FC<any> = (props: {
151
 
152
  }
153
 
154
- let audioPath = RenderUtils.getFileName(item?.audioFullPath)
155
-
156
- let transition = {
157
- file: 'assets/overlay.webm',
158
- durationSec: 2,
159
- durationFrames: 2 * fps,
160
- }
161
-
162
 
163
- function randomElement<T>(arr: T[], seed: number): T {
164
- let i = Math.floor(random(seed) * arr.length)
165
- let rand = arr[i];
166
- return rand
167
- }
168
-
169
-
170
-
171
- let chunks = (item?.imageAbsPaths?.map((displayMedia: DisplayMedia, i) => {
172
  let chunk = []
173
  let easeInOutExp = Easing.inOut(Easing.bezier(0.8, 0.22, 0.96, 0.65));
174
  easeInOutExp = Easing.ease
@@ -183,7 +154,7 @@ export const IGScene: React.FC<any> = (props: {
183
  // .fill(CircularWipe)
184
  let Anim = anims[frame % 9]
185
  let seed = i * displayMedia.idx
186
- Anim = randomElement(anims, `x-${seed}`)
187
  const easeInOutExp = Easing.inOut(Easing.bezier(0.8, 0.22, 0.96, 0.65));
188
  chunk.push((
189
  <TransitionSeries.Transition
@@ -198,12 +169,14 @@ export const IGScene: React.FC<any> = (props: {
198
  }
199
  return chunk
200
  }))
 
 
201
  return (
202
  <AbsoluteFill style={{
203
  width: '100%',
204
  height: '100%',
205
  }} className='relative'>
206
- <Audio volume={1} src={staticFile(audioPath)} />
207
  <TransitionSeries>
208
  {
209
  ...chunks
@@ -231,104 +204,5 @@ export const IGScene: React.FC<any> = (props: {
231
  };
232
 
233
 
234
- function splitWordsIntoGroups(words) {
235
- const groups = [];
236
- let currentGroup = [];
237
-
238
- for (const word of words) {
239
- if (currentGroup.length === 0) {
240
- currentGroup.push(word);
241
- } else if (word.sentence_end) {
242
- currentGroup.push(word);
243
- groups.push(currentGroup);
244
- currentGroup = [];
245
- } else if (currentGroup.length < 5) {
246
- currentGroup.push(word);
247
- } else {
248
- groups.push(currentGroup);
249
- currentGroup = [word];
250
- }
251
- }
252
-
253
- if (currentGroup.length > 0) {
254
- groups.push(currentGroup);
255
- }
256
-
257
- // Ensure each group has a maximum of 5 words
258
- const finalGroups = [];
259
- for (const group of groups) {
260
- while (group.length > 5) {
261
- finalGroups.push(group.slice(0, 5));
262
- group.splice(0, 5);
263
- }
264
- finalGroups.push(group);
265
- }
266
-
267
- return finalGroups?.map(group => {
268
- return {
269
- words: group
270
- }
271
- });
272
- }
273
-
274
- function findCurrentGroupByWord(wod: String, group) {
275
- if (!wod) {
276
- return
277
- }
278
- for (let i = 0; i < group.length; i++) {
279
-
280
- let cgroup = group[i]?.words
281
-
282
- for (let j = 0; j < cgroup.length; j++) {
283
- let cwod = cgroup[j]
284
- if (cwod.idx == wod.idx) {
285
- return cgroup
286
- }
287
- }
288
- }
289
- }
290
-
291
- function findCurrentGroupByTime(timeSec: Number, groups) {
292
- var t = timeSec;
293
- let wds = groups
294
- for (let i = 0; i < wds.length; i++) {
295
- const x = wds[i];
296
- if (x.start != undefined && x.end != undefined && (t >= x.start && t < x.end)) {
297
- return x
298
- }
299
- }
300
- }
301
-
302
 
303
- function findCurrentWord(timeSec, frames) {
304
- var t = timeSec;
305
- let wds = frames
306
- for (let i = 0; i < wds.length; i++) {
307
- const x = wds[i];
308
- if (x.start && x.end && (t >= x.start && t < x.end)) {
309
- return x
310
- }
311
- }
312
- }
313
-
314
- function getGroupDuration(group, avgCps) {
315
- let groupDuration = 0
316
- for (let i = 0; i < group.length; i++) {
317
- let frame = group[i]
318
- if (frame.end && frame.start) {
319
- groupDuration += frame.end - frame.start
320
- } else {
321
- let noOfCharacters = frame.endOffset - frame.startOffset
322
- groupDuration += noOfCharacters * avgCps
323
- }
324
- }
325
- return groupDuration
326
- }
327
-
328
- const Title: React.FC<{ title?: string, color?: string }> = ({ title = "test", color = "#fff" }) => {
329
-
330
- return (
331
- <div style={{ backgroundColor: color, textAlign: "center", fontSize: "7em" }}>{title}</div>
332
- );
333
- };
334
 
 
1
  //@ts-nocheck
2
+ import { AbsoluteFill, interpolate, staticFile, Audio, useCurrentFrame, Easing } from 'remotion';
3
  import React, { useEffect, useState } from 'react'
 
 
4
  import { RenderUtils } from '../RenderUtils';
5
  import { Transcript, SectionMedia } from '../models/OriginalManuscriptModel'
6
  import axios from 'axios';
 
7
  import ExcitedSubtitles from '../subtitles/excited_Subtitles';
8
  import _ from 'lodash';
9
  import './styles.module.css'
 
14
  import { Pan } from '../anims/Pan';
15
  import { Dissolve } from '../anims/Dissolve';
16
  import { SlidingDoors } from '../anims/SlidingDoors';
 
 
17
  import { IGMediaRender } from './IGMediaRender';
18
  import { Group } from '../models/Types';
19
 
 
24
  script: any,
25
  item: Transcript
26
  }) => {
 
27
  const [subtitles, setSubtitles] = useState(undefined)
28
  const [groups, setGroups] = useState(undefined)
 
29
  const item = props.item
30
+ let { subtitle_file, durationInSeconds } = item
31
  const { script } = props
32
  const { meta } = script
33
  const { fps } = meta
34
  const frame = useCurrentFrame();
35
+ let speechPath = RenderUtils.getFileName(item?.audioFullPath)
36
 
37
  useEffect(() => {
38
  const subFile = staticFile(RenderUtils.getFileName(subtitle_file))
 
41
  if (subtitles?.default) {
42
  subtitles = subtitles.default
43
  }
 
 
44
  let subs = subtitles.words
 
45
  let noOfCharacters = 0
46
  let groupDuration = 0
47
  for (let i = 0; i < subs.length; i++) {
 
78
  }
79
  }
80
  }
 
81
  setSubtitles(subs)
82
 
83
 
84
  let arr = subs
 
85
  let groups = [];
86
 
87
+ groups = RenderUtils.splitWordsIntoGroups(arr)
88
  groups.forEach((group) => {
89
  let words = group.words;
90
  group.start = words[0]?.start
 
100
  return (<></>)
101
  }
102
 
 
103
  let itemDurationInFrames = item.durationInSeconds * fps
104
  console.log('scriptItem.offset', frame, itemDurationInFrames)
105
 
 
111
 
112
 
113
  let curSecond: Number = frame / fps
114
+ let word = RenderUtils.findCurrentWord(curSecond, subtitles)
115
+ let group: Group = RenderUtils.findCurrentGroupByTime(curSecond, groups)
116
 
117
  let currentDisplayMedia: DisplayMedia = (item?.imageAbsPaths || [])[0]
 
118
 
119
  if (!_.isEmpty(item?.imageAbsPaths)) {
120
  let frameOffest = 0
 
138
 
139
  }
140
 
 
 
 
 
 
 
 
 
141
 
142
+ let chunks: React.ReactNode[] = (item?.imageAbsPaths?.map((displayMedia: DisplayMedia, i) => {
 
 
 
 
 
 
 
 
143
  let chunk = []
144
  let easeInOutExp = Easing.inOut(Easing.bezier(0.8, 0.22, 0.96, 0.65));
145
  easeInOutExp = Easing.ease
 
154
  // .fill(CircularWipe)
155
  let Anim = anims[frame % 9]
156
  let seed = i * displayMedia.idx
157
+ Anim = RenderUtils.randomElement(anims, `x-${seed}`)
158
  const easeInOutExp = Easing.inOut(Easing.bezier(0.8, 0.22, 0.96, 0.65));
159
  chunk.push((
160
  <TransitionSeries.Transition
 
169
  }
170
  return chunk
171
  }))
172
+
173
+
174
  return (
175
  <AbsoluteFill style={{
176
  width: '100%',
177
  height: '100%',
178
  }} className='relative'>
179
+ <Audio volume={1} src={staticFile(speechPath)} />
180
  <TransitionSeries>
181
  {
182
  ...chunks
 
204
  };
205
 
206
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
207
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
 
src/models/OriginalManuscriptModel.ts CHANGED
@@ -20,6 +20,7 @@ export interface Transcript {
20
  title: string
21
  text: string
22
  pointers: string[]
 
23
  imageText: string[]
24
  videoText: string[]
25
  dialog: string[]
 
20
  title: string
21
  text: string
22
  pointers: string[]
23
+ subtitle_file: string
24
  imageText: string[]
25
  videoText: string[]
26
  dialog: string[]