Dynamic length and minimal customization
Browse files
App/Editor/Schema.py
CHANGED
@@ -8,6 +8,13 @@ class LinkInfo(BaseModel):
|
|
8 |
link: HttpUrl
|
9 |
|
10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
class Assets(BaseModel):
|
12 |
type: str
|
13 |
sequence: List[dict]
|
@@ -22,6 +29,7 @@ class Assets(BaseModel):
|
|
22 |
class EditorRequest(BaseModel):
|
23 |
links: Optional[List[LinkInfo]] # List of LinkInfo objects
|
24 |
assets: List[Assets]
|
|
|
25 |
|
26 |
|
27 |
class TaskInfo(BaseModel):
|
|
|
8 |
link: HttpUrl
|
9 |
|
10 |
|
11 |
+
class Constants(BaseModel):
|
12 |
+
duration: Optional[int]
|
13 |
+
height: Optional[int]
|
14 |
+
width: Optional[int]
|
15 |
+
text: Optional[dict]
|
16 |
+
|
17 |
+
|
18 |
class Assets(BaseModel):
|
19 |
type: str
|
20 |
sequence: List[dict]
|
|
|
29 |
class EditorRequest(BaseModel):
|
30 |
links: Optional[List[LinkInfo]] # List of LinkInfo objects
|
31 |
assets: List[Assets]
|
32 |
+
constants: Optional[Constants]
|
33 |
|
34 |
|
35 |
class TaskInfo(BaseModel):
|
App/Worker.py
CHANGED
@@ -4,7 +4,7 @@ import uuid
|
|
4 |
from urllib.parse import urlparse
|
5 |
from App import celery_config, bot
|
6 |
from typing import List
|
7 |
-
from App.Editor.Schema import EditorRequest, LinkInfo, Assets
|
8 |
from celery.signals import worker_process_init
|
9 |
from asgiref.sync import async_to_sync
|
10 |
import json
|
@@ -33,6 +33,14 @@ def create_json_file(assets: List[Assets], asset_dir: str):
|
|
33 |
f.write(json_string)
|
34 |
|
35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
def create_symlink(source_dir, target_dir, symlink_name):
|
37 |
source_path = os.path.join(source_dir, symlink_name)
|
38 |
target_path = os.path.join(target_dir, symlink_name)
|
@@ -114,6 +122,7 @@ async def celery_task(video_task: EditorRequest):
|
|
114 |
|
115 |
copy_remotion_app(remotion_app_dir, temp_dir),
|
116 |
install_dependencies(temp_dir),
|
|
|
117 |
create_json_file(video_task.assets, assets_dir),
|
118 |
download_assets(video_task.links, temp_dir) if video_task.links else None,
|
119 |
render_video(temp_dir, output_dir),
|
|
|
4 |
from urllib.parse import urlparse
|
5 |
from App import celery_config, bot
|
6 |
from typing import List
|
7 |
+
from App.Editor.Schema import EditorRequest, LinkInfo, Assets, Constants
|
8 |
from celery.signals import worker_process_init
|
9 |
from asgiref.sync import async_to_sync
|
10 |
import json
|
|
|
33 |
f.write(json_string)
|
34 |
|
35 |
|
36 |
+
def create_constants_json_file(constants: Constants, asset_dir: str):
|
37 |
+
filename = "Constants.json"
|
38 |
+
json_string = json.dumps(constants.dict())
|
39 |
+
os.makedirs(asset_dir, exist_ok=True)
|
40 |
+
with open(os.path.join(asset_dir, filename), "w") as f:
|
41 |
+
f.write(json_string)
|
42 |
+
|
43 |
+
|
44 |
def create_symlink(source_dir, target_dir, symlink_name):
|
45 |
source_path = os.path.join(source_dir, symlink_name)
|
46 |
target_path = os.path.join(target_dir, symlink_name)
|
|
|
122 |
|
123 |
copy_remotion_app(remotion_app_dir, temp_dir),
|
124 |
install_dependencies(temp_dir),
|
125 |
+
create_constants_json_file(video_task.constants, assets_dir),
|
126 |
create_json_file(video_task.assets, assets_dir),
|
127 |
download_assets(video_task.links, temp_dir) if video_task.links else None,
|
128 |
render_video(temp_dir, output_dir),
|
Remotion-app/src/HelloWorld/Assets/Constants.json
ADDED
File without changes
|
Remotion-app/src/HelloWorld/TextStream.jsx
CHANGED
@@ -2,26 +2,40 @@ import React, {createElement} from 'react';
|
|
2 |
import {useVideoConfig, AbsoluteFill, TransitionSeries} from 'remotion';
|
3 |
import * as Fonts from '@remotion/google-fonts';
|
4 |
import transcriptData from './Assets/TextSequences.json';
|
5 |
-
import
|
6 |
import {TransitionSeries} from '@remotion/transitions';
|
7 |
|
8 |
-
const subtitle =
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
Fonts.getAvailableFonts()
|
23 |
.filter((font) => {
|
24 |
-
return font.fontFamily ===
|
25 |
})[0]
|
26 |
.load()
|
27 |
.then((font) => font.loadFont());
|
|
|
2 |
import {useVideoConfig, AbsoluteFill, TransitionSeries} from 'remotion';
|
3 |
import * as Fonts from '@remotion/google-fonts';
|
4 |
import transcriptData from './Assets/TextSequences.json';
|
5 |
+
import Constants from './Assets/Constants.json';
|
6 |
import {TransitionSeries} from '@remotion/transitions';
|
7 |
|
8 |
+
const subtitle = Constants?.text
|
9 |
+
? {
|
10 |
+
...Constants.text,
|
11 |
+
fontFamily: 'Luckiest Guy',
|
12 |
+
fontSize: 120,
|
13 |
+
textAlign: 'center',
|
14 |
+
textShadow:
|
15 |
+
'-10px -10px 0 #000, 0 -10px 0 #000, 10px -10px 0 #000, 10px 0 0 #000, 10px 10px 0 #000, 0 10px 0 #000, -10px 10px 0 #000, -10px 0 0 #000',
|
16 |
+
position: 'fixed',
|
17 |
+
fontWeight: 'bolder',
|
18 |
+
color: 'yellow',
|
19 |
+
bottom: '30vh',
|
20 |
+
height: 'fit-content',
|
21 |
+
width: '100%',
|
22 |
+
}
|
23 |
+
: {
|
24 |
+
fontFamily: 'Luckiest Guy',
|
25 |
+
fontSize: 120,
|
26 |
+
textAlign: 'center',
|
27 |
+
textShadow:
|
28 |
+
'-10px -10px 0 #000, 0 -10px 0 #000, 10px -10px 0 #000, 10px 0 0 #000, 10px 10px 0 #000, 0 10px 0 #000, -10px 10px 0 #000, -10px 0 0 #000',
|
29 |
+
position: 'fixed',
|
30 |
+
fontWeight: 'bolder',
|
31 |
+
color: 'yellow',
|
32 |
+
bottom: '30vh',
|
33 |
+
height: 'fit-content',
|
34 |
+
width: '100%',
|
35 |
+
};
|
36 |
Fonts.getAvailableFonts()
|
37 |
.filter((font) => {
|
38 |
+
return font.fontFamily === subtitle.fontFamily;
|
39 |
})[0]
|
40 |
.load()
|
41 |
.then((font) => font.loadFont());
|
Remotion-app/src/Root.jsx
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
import {Composition} from 'remotion';
|
2 |
import {HelloWorld} from './HelloWorld';
|
3 |
-
import
|
4 |
import './index.css';
|
5 |
export const RemotionRoot = () => {
|
6 |
return (
|
@@ -8,10 +8,10 @@ export const RemotionRoot = () => {
|
|
8 |
<Composition
|
9 |
id="HelloWorld"
|
10 |
component={HelloWorld}
|
11 |
-
durationInFrames={
|
12 |
fps={30}
|
13 |
-
height={1920}
|
14 |
-
width={1080}
|
15 |
/>
|
16 |
</>
|
17 |
);
|
|
|
1 |
import {Composition} from 'remotion';
|
2 |
import {HelloWorld} from './HelloWorld';
|
3 |
+
import Constants from './HelloWorld/Assets/Constants.json';
|
4 |
import './index.css';
|
5 |
export const RemotionRoot = () => {
|
6 |
return (
|
|
|
8 |
<Composition
|
9 |
id="HelloWorld"
|
10 |
component={HelloWorld}
|
11 |
+
durationInFrames={Constants?.dutaion ? Constants.duration : 60 * 30}
|
12 |
fps={30}
|
13 |
+
height={Constants?.height ? Constants.height : 1920}
|
14 |
+
width={Constants?.width ? Constants.width : 1080}
|
15 |
/>
|
16 |
</>
|
17 |
);
|