shiveshnavin commited on
Commit
ec03fd1
·
1 Parent(s): 81e47ab

Added subs

Browse files
src/{Utils.ts → RenderUtils.ts} RENAMED
@@ -16,7 +16,45 @@ function levenshteinDistance(str1: string, str2: string) {
16
 
17
  return dp[str1.length][str2.length];
18
  }
19
- export class Utils {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
  public static findMostSimilarString(inputString: string, stringArray: string[]) {
22
  let minDistance = Number.MAX_SAFE_INTEGER;
 
16
 
17
  return dp[str1.length][str2.length];
18
  }
19
+ export class RenderUtils {
20
+
21
+ public static splitArrayIntoChunks(arr, chunkSize) {
22
+ const chunkedArr = [];
23
+ for (let i = 0; i < arr.length; i += chunkSize) {
24
+ chunkedArr.push(arr.slice(i, i + chunkSize));
25
+ }
26
+ return chunkedArr;
27
+ }
28
+
29
+ public static splitArray(arr, pieces) {
30
+ let result = [];
31
+ let chunkSize = Math.ceil(arr.length / pieces);
32
+ for (let i = 0, j = arr.length; i < j; i += chunkSize) {
33
+ result.push(arr.slice(i, i + chunkSize));
34
+ }
35
+ return result;
36
+ }
37
+
38
+ public static getFileName(filePath: string, subdirpath?: string): string | undefined {
39
+ if (!filePath)
40
+ return undefined
41
+ if (filePath.startsWith("http"))
42
+ return filePath
43
+ const slashCount = (filePath.replace("./", "").split("/").length - 1);
44
+ if (slashCount > 0) {
45
+ let pub = filePath.replace("./", "")
46
+ return pub
47
+ }
48
+
49
+ const match = filePath.match(/([^\/\\]+)$/);
50
+ let folmat = match ? match[1] : '';
51
+ if (subdirpath) {
52
+ return subdirpath + "/" + folmat
53
+ }
54
+ else {
55
+ return folmat
56
+ }
57
+ }
58
 
59
  public static findMostSimilarString(inputString: string, stringArray: string[]) {
60
  let minDistance = Number.MAX_SAFE_INTEGER;
src/ig-reel/IGReelComposition.tsx ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { AbsoluteFill, Img, staticFile } from 'remotion';
2
+ import React from 'react'
3
+ import { loadFont } from "@remotion/google-fonts/MontserratAlternates";
4
+ import { Series } from "remotion";
5
+ import { IGScene } from './IGScene';
6
+
7
+
8
+ export const IGReelComposition: React.FC = (props) => {
9
+ const { fontFamily } = loadFont();
10
+ let { contents, meta } = props
11
+
12
+
13
+ return (
14
+ <AbsoluteFill>
15
+
16
+ <Series>
17
+ {
18
+ contents.map((scriptItem, i) => {
19
+ let { durationInSeconds } = scriptItem
20
+ let durationInFrames = meta.fps * durationInSeconds
21
+ return (
22
+ <Series.Sequence durationInFrames={durationInFrames}>
23
+ <IGScene script={props} item={scriptItem} />
24
+ </Series.Sequence>
25
+ )
26
+ })
27
+ }
28
+ </Series>
29
+
30
+
31
+ </AbsoluteFill >
32
+ );
33
+ };
34
+
35
+
36
+ const Title: React.FC<{ title?: string, color: string }> = ({ title = "test", color }) => {
37
+
38
+ return (
39
+ <div style={{ backgroundColor: color, textAlign: "center", fontSize: "7em" }}>{title}</div>
40
+ );
41
+ };
src/ig-reel/IGScene.tsx ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //@ts-nocheck
2
+ import { AbsoluteFill, Img, staticFile, Audio, useCurrentFrame } from 'remotion';
3
+ import React, { useEffect, useState } from 'react'
4
+ import { loadFont } from "@remotion/google-fonts/MontserratAlternates";
5
+ import { Series } from "remotion";
6
+ import { RenderUtils } from '../RenderUtils';
7
+
8
+ export const IGScene: React.FC<any> = (props: { script: any, item: any }) => {
9
+ const { fontFamily } = loadFont();
10
+ const [subtitles, setSubtitles] = useState(undefined)
11
+ const [subtitleGroups, setSubtitleGroups] = useState(undefined)
12
+ const [averageCharsPs, setAverageCps] = useState(undefined)
13
+ const item = props.item
14
+ let { title, subtitle_file } = item
15
+ const { script } = props
16
+ const { meta } = script
17
+ const { fps } = meta
18
+ const audioPath = RenderUtils.getFileName(item.audioFullPath)
19
+ const frame = useCurrentFrame();
20
+
21
+ useEffect(() => {
22
+ let file = RenderUtils.getFileName(subtitle_file)
23
+ let subtitles = require('../../public/' + file)
24
+ let subtitlesClone = subtitles
25
+ let subs = subtitles.words
26
+
27
+
28
+ let noOfCharacters = 0
29
+ let groupDuration = 0
30
+ for (let i = 0; i < subs.length; i++) {
31
+ let frame = subs[i]
32
+ frame.idx = i
33
+ if (frame.end && frame.start) {
34
+ noOfCharacters += frame.endOffset - frame.startOffset
35
+ groupDuration += frame.end - frame.start
36
+ }
37
+ }
38
+ let avgCps = groupDuration / noOfCharacters
39
+
40
+ // Fill start and end for missing frames
41
+ for (let i = 0; i < subs.length; i++) {
42
+ let frame = subs[i]
43
+ let prevFrame = subs[i - 1]
44
+ let nextFrame = subs[i + 1]
45
+ if (!frame.end || !frame.start) {
46
+ let noOfCharacters = frame.endOffset - frame.startOffset
47
+ let frameDuration = noOfCharacters * avgCps
48
+ frame.start = prevFrame?.end || 0
49
+ frame.end = (frame.start + frameDuration)
50
+ // frame.end = nextFrame?.start || (frame.start + frameDuration)
51
+ if (nextFrame?.start < frame.end) {
52
+ let next2next = subs[i + 2]
53
+ if (next2next && next2next.start) {
54
+ nextFrame.end = next2next.start
55
+ }
56
+ }
57
+ }
58
+ }
59
+ setAverageCps(avgCps)
60
+ setSubtitles(subs)
61
+
62
+
63
+ let arr = subs
64
+ let chunkSize = 4;
65
+ const groups = [];
66
+ for (let i = 0; i < arr.length; i += chunkSize) {
67
+ let curGroup = arr.slice(i, i + chunkSize)
68
+ let grpDur = getGroupDuration(curGroup, avgCps)
69
+ let grpDurFrames = grpDur * meta.fps
70
+ groups.push({
71
+ duration: grpDur,
72
+ durationFrames: grpDurFrames,
73
+ frames: arr.slice(i, i + chunkSize)
74
+ });
75
+ }
76
+ setSubtitleGroups(groups)
77
+
78
+
79
+ }, [])
80
+
81
+ if (!subtitleGroups) {
82
+ return (<></>)
83
+ }
84
+
85
+ let curSecond = frame / fps
86
+ let word = findCurrentWord(curSecond, subtitles)
87
+ return (
88
+ <AbsoluteFill>
89
+ <Audio volume={1.0} src={staticFile(audioPath)} />
90
+ {/* <Title title={curSecond}></Title>
91
+ <Title title={word?.start + ' --- ' + word?.end}></Title> */}
92
+
93
+ <Title title={(word?.word || '_____')}></Title>
94
+ {
95
+
96
+ }
97
+ {/* <Series>
98
+ {
99
+ subtitleGroups.map(curGroup => {
100
+ let groupDuration = 0
101
+ let group = curGroup.frames
102
+ for (let i = 0; i < group.length; i++) {
103
+ let frame = group[i]
104
+ if (frame.end && frame.start) {
105
+ groupDuration += frame.end - frame.start
106
+ } else {
107
+ let noOfCharacters = frame.endOffset - frame.startOffset
108
+ groupDuration += noOfCharacters * averageCharsPs
109
+ }
110
+ }
111
+ let groupDurationFps = meta.fps * groupDuration
112
+
113
+ return (
114
+ <Series.Sequence durationInFrames={groupDurationFps}>
115
+ <SubTitleFrameGroup frames={group} />
116
+ </Series.Sequence>
117
+ )
118
+ })
119
+ }
120
+ </Series> */}
121
+ </AbsoluteFill >
122
+ );
123
+ };
124
+
125
+ function findCurrentWord(timeSec, frames) {
126
+ var t = timeSec;
127
+ let wds = frames
128
+ // var hits = wds.filter(function (x) {
129
+ // return (t - x.start) > 0.0001 && (x.end - t) > 0.0001;
130
+ // }, wds);
131
+ // var currentWord = hits[0];
132
+ // return currentWord
133
+ for (let i = 0; i < wds.length; i++) {
134
+ const x = wds[i];
135
+ if (x.start && x.end && (t >= x.start && t < x.end)) {
136
+ return x
137
+ }
138
+ }
139
+ }
140
+
141
+ function getGroupDuration(group, avgCps) {
142
+ let groupDuration = 0
143
+ for (let i = 0; i < group.length; i++) {
144
+ let frame = group[i]
145
+ if (frame.end && frame.start) {
146
+ groupDuration += frame.end - frame.start
147
+ } else {
148
+ let noOfCharacters = frame.endOffset - frame.startOffset
149
+ groupDuration += noOfCharacters * avgCps
150
+ }
151
+ }
152
+ return groupDuration
153
+ }
154
+
155
+ const SubTitleFrameGroup: React.FC<{ title?: string, color: string }> = ({ frames }) => {
156
+
157
+
158
+ return (
159
+ <div style={{ display: 'block' }}>
160
+ {
161
+ frames.map((frame) => {
162
+ return <Title title={frame.word} color="#425211"></Title>
163
+ })
164
+ }
165
+ </div>
166
+ );
167
+ };
168
+
169
+ const Title: React.FC<{ title?: string, color?: string }> = ({ title = "test", color = "#fff" }) => {
170
+
171
+ return (
172
+ <div style={{ backgroundColor: color, textAlign: "center", fontSize: "7em" }}>{title}</div>
173
+ );
174
+ };
src/textWithBgImage/PosterSingleTextWithBG.tsx CHANGED
@@ -1,11 +1,7 @@
1
- import { AbsoluteFill, Audio, Img, spring, staticFile, useCurrentFrame, useVideoConfig } from 'remotion';
2
- import { MediaBackground } from './MediaBackground';
3
  import React from 'react'
4
- import TransitionSeries from 'remotion-transition-series/lib/TransitionSeries';
5
- import { GlowingStroke } from '../../anims/GlowingStrike';
6
  import { SequentialSceneData } from './SequentialScene';
7
  import { loadFont } from "@remotion/google-fonts/MontserratAlternates";
8
- import { ReactComponent as Logo } from '../../../public/assets/bg_transparent.svg';
9
 
10
  function adjustFontSize(text: string, fullFont?: number): number {
11
  if (!fullFont) {
 
1
+ import { AbsoluteFill, Img, staticFile } from 'remotion';
 
2
  import React from 'react'
 
 
3
  import { SequentialSceneData } from './SequentialScene';
4
  import { loadFont } from "@remotion/google-fonts/MontserratAlternates";
 
5
 
6
  function adjustFontSize(text: string, fullFont?: number): number {
7
  if (!fullFont) {
src/textWithBgImage/SemibitComposition.tsx CHANGED
@@ -8,28 +8,10 @@ import { YoutubeCategoriesConfig } from './Categories';
8
  import '../style.css';
9
  import { preloadImage, preloadVideo } from "@remotion/preload";
10
  import Transitions from '../../public/assets/transitions.json'
 
 
11
 
12
 
13
- function getFileName(filePath: string, subdirpath?: string): string {
14
- if (!filePath)
15
- return undefined
16
- if (filePath.startsWith("http"))
17
- return filePath
18
- const slashCount = (filePath.replace("./", "").split("/").length - 1);
19
- if (slashCount > 0) {
20
- let pub = filePath.replace("./", "")
21
- return pub
22
- }
23
-
24
- const match = filePath.match(/([^\/\\]+)$/);
25
- let folmat = match ? match[1] : '';
26
- if (subdirpath) {
27
- return subdirpath + "/" + folmat
28
- }
29
- else {
30
- return folmat
31
- }
32
- }
33
 
34
 
35
 
@@ -65,6 +47,7 @@ export const SemibitComposition: React.FC = () => {
65
 
66
  let contents: SequentialSceneData[] =
67
  Script.transcript
 
68
  // .slice(0, 2)
69
  .map((section) => {
70
  var { text, duration, offset, imageAbsPaths, audioFullPath, title, pointers } = section
@@ -98,19 +81,19 @@ export const SemibitComposition: React.FC = () => {
98
  }
99
  })
100
  let bgImagePaths = imageAbsPaths.map(p => {
101
- p.path = getFileName(p?.path)
102
  return p
103
  })
104
  let frame = Object.assign(section, {
105
  "commulativeDurationStartSec": commDuration,
106
  "text": text,
107
- "transition_file": getFileName(transitionFile),
108
  "durationInSecs": curDurSecs,
109
  "duration": Math.ceil(curDurSecs * fps),
110
  "offset": offset * fps,
111
  "direction": lastDirection ? 'left' : 'right',
112
  "bgImagePaths": bgImagePaths,
113
- "audioPath": getFileName(audioFullPath),
114
  "textColor": '#F44336',
115
  "emphasisOnImage": title?.length > 0 && pointers?.length > 0 || Script.meta.emphasisOnImage
116
  })
@@ -122,13 +105,13 @@ export const SemibitComposition: React.FC = () => {
122
  const intro = {
123
  durationInFrames: 0,
124
  durationInSec: 5.433,
125
- file: Script.meta.tenantVideoConfig ? getFileName(Script.meta.tenantVideoConfig.introFile, "assets") : 'assets/music_intro.mp4'
126
  }
127
  let ADJUST_END_DUR_SEC = 3
128
  const outro = {
129
  durationInFrames: 0,
130
  durationInSec: 8.034 - ADJUST_END_DUR_SEC,
131
- file: Script.meta.tenantVideoConfig ? getFileName(Script.meta.tenantVideoConfig.outroFile, "assets") : 'assets/music_outro.mp4'
132
  }
133
 
134
  if (intro) {
@@ -144,7 +127,7 @@ export const SemibitComposition: React.FC = () => {
144
  }
145
 
146
  // durationInSec = 3
147
- const duration = Math.ceil(durationInSec * fps)
148
  console.log("Total Video Duration", durationInSec)
149
 
150
  //@ts-ignore
@@ -160,7 +143,22 @@ export const SemibitComposition: React.FC = () => {
160
  width={Script.meta?.resolution?.width || 1920}
161
  height={Script.meta?.resolution?.height || 1080}
162
  defaultProps={{
163
- bgMusic: getFileName(Script.bgMusic, "mp3"),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  contents: contents,
165
  intro: intro,
166
  outro: outro,
@@ -176,7 +174,7 @@ export const SemibitComposition: React.FC = () => {
176
  defaultProps={{
177
  emphasisOnImage: Script.meta.emphasisOnImage,
178
  bgImagePath: (
179
- getFileName(Script.meta?.posterImage) ||
180
  ("assets/" + (playListsIDs[Script.meta?.platlistName] || "PLeT-Kik6WdhTHl_RxwavJ3FXBGiXlYIxq") + ".jpg")
181
  ),
182
  text: (Script.meta?.posterTitle || Script.meta?.title)?.trim(),
 
8
  import '../style.css';
9
  import { preloadImage, preloadVideo } from "@remotion/preload";
10
  import Transitions from '../../public/assets/transitions.json'
11
+ import { IGReelComposition } from '../ig-reel/IGReelComposition';
12
+ import { RenderUtils } from '../RenderUtils';
13
 
14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
 
17
 
 
47
 
48
  let contents: SequentialSceneData[] =
49
  Script.transcript
50
+ .filter(item => item.subtitle_file != undefined)
51
  // .slice(0, 2)
52
  .map((section) => {
53
  var { text, duration, offset, imageAbsPaths, audioFullPath, title, pointers } = section
 
81
  }
82
  })
83
  let bgImagePaths = imageAbsPaths.map(p => {
84
+ p.path = RenderUtils.getFileName(p?.path)
85
  return p
86
  })
87
  let frame = Object.assign(section, {
88
  "commulativeDurationStartSec": commDuration,
89
  "text": text,
90
+ "transition_file": RenderUtils.getFileName(transitionFile),
91
  "durationInSecs": curDurSecs,
92
  "duration": Math.ceil(curDurSecs * fps),
93
  "offset": offset * fps,
94
  "direction": lastDirection ? 'left' : 'right',
95
  "bgImagePaths": bgImagePaths,
96
+ "audioPath": RenderUtils.getFileName(audioFullPath),
97
  "textColor": '#F44336',
98
  "emphasisOnImage": title?.length > 0 && pointers?.length > 0 || Script.meta.emphasisOnImage
99
  })
 
105
  const intro = {
106
  durationInFrames: 0,
107
  durationInSec: 5.433,
108
+ file: Script.meta.tenantVideoConfig ? RenderUtils.getFileName(Script.meta.tenantVideoConfig.introFile, "assets") : 'assets/music_intro.mp4'
109
  }
110
  let ADJUST_END_DUR_SEC = 3
111
  const outro = {
112
  durationInFrames: 0,
113
  durationInSec: 8.034 - ADJUST_END_DUR_SEC,
114
+ file: Script.meta.tenantVideoConfig ? RenderUtils.getFileName(Script.meta.tenantVideoConfig.outroFile, "assets") : 'assets/music_outro.mp4'
115
  }
116
 
117
  if (intro) {
 
127
  }
128
 
129
  // durationInSec = 3
130
+ const duration = Math.ceil(34.753016 * fps)
131
  console.log("Total Video Duration", durationInSec)
132
 
133
  //@ts-ignore
 
143
  width={Script.meta?.resolution?.width || 1920}
144
  height={Script.meta?.resolution?.height || 1080}
145
  defaultProps={{
146
+ bgMusic: RenderUtils.getFileName(Script.bgMusic, "mp3"),
147
+ contents: contents,
148
+ intro: intro,
149
+ outro: outro,
150
+ meta: Script.meta
151
+ }}
152
+ />
153
+ <Composition
154
+ id='IGReelComposition'
155
+ component={IGReelComposition}
156
+ durationInFrames={duration}
157
+ fps={fps}
158
+ width={Script.meta?.resolution?.width || 1920}
159
+ height={Script.meta?.resolution?.height || 1080}
160
+ defaultProps={{
161
+ bgMusic: RenderUtils.getFileName(Script.bgMusic, "mp3"),
162
  contents: contents,
163
  intro: intro,
164
  outro: outro,
 
174
  defaultProps={{
175
  emphasisOnImage: Script.meta.emphasisOnImage,
176
  bgImagePath: (
177
+ RenderUtils.getFileName(Script.meta?.posterImage) ||
178
  ("assets/" + (playListsIDs[Script.meta?.platlistName] || "PLeT-Kik6WdhTHl_RxwavJ3FXBGiXlYIxq") + ".jpg")
179
  ),
180
  text: (Script.meta?.posterTitle || Script.meta?.title)?.trim(),