@revideo/create 0.5.11-alpha.1102 → 0.5.11-alpha.1104
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/examples/README.md +43 -0
- package/examples/avatar-with-background/package.json +27 -0
- package/examples/avatar-with-background/src/project.meta +31 -0
- package/examples/avatar-with-background/src/project.ts +6 -0
- package/examples/avatar-with-background/src/render.ts +14 -0
- package/examples/avatar-with-background/src/revideo.d.ts +1 -0
- package/examples/avatar-with-background/src/scenes/example.meta +5 -0
- package/examples/avatar-with-background/src/scenes/example.tsx +28 -0
- package/examples/avatar-with-background/tsconfig.json +9 -0
- package/examples/avatar-with-background/vite.config.ts +8 -0
- package/examples/default/README.md +19 -0
- package/examples/default/package.json +20 -0
- package/examples/default/src/project.tsx +56 -0
- package/examples/default/src/render.ts +15 -0
- package/examples/default/tsconfig.json +10 -0
- package/examples/github-stars-celebration/package-lock.json +3833 -0
- package/examples/github-stars-celebration/package.json +24 -0
- package/examples/github-stars-celebration/src/global.css +1 -0
- package/examples/github-stars-celebration/src/project.meta +28 -0
- package/examples/github-stars-celebration/src/project.ts +8 -0
- package/examples/github-stars-celebration/src/render.ts +15 -0
- package/examples/github-stars-celebration/src/revideo.d.ts +1 -0
- package/examples/github-stars-celebration/src/scenes/example.meta +5 -0
- package/examples/github-stars-celebration/src/scenes/example.tsx +51 -0
- package/examples/github-stars-celebration/tsconfig.json +9 -0
- package/examples/github-stars-celebration/vite.config.ts +8 -0
- package/examples/google-cloud-run-parallelized/README.md +127 -0
- package/examples/google-cloud-run-parallelized/render-orchestrator/Dockerfile +56 -0
- package/examples/google-cloud-run-parallelized/render-orchestrator/package.json +22 -0
- package/examples/google-cloud-run-parallelized/render-orchestrator/src/index.ts +72 -0
- package/examples/google-cloud-run-parallelized/render-orchestrator/src/revideo.d.ts +1 -0
- package/examples/google-cloud-run-parallelized/render-orchestrator/tsconfig.json +10 -0
- package/examples/google-cloud-run-parallelized/render-worker/.gcloudignore +17 -0
- package/examples/google-cloud-run-parallelized/render-worker/.puppeteerrc.cjs +9 -0
- package/examples/google-cloud-run-parallelized/render-worker/package.json +30 -0
- package/examples/google-cloud-run-parallelized/render-worker/src/index.ts +45 -0
- package/examples/google-cloud-run-parallelized/render-worker/src/project.meta +31 -0
- package/examples/google-cloud-run-parallelized/render-worker/src/project.ts +6 -0
- package/examples/google-cloud-run-parallelized/render-worker/src/render.ts +14 -0
- package/examples/google-cloud-run-parallelized/render-worker/src/revideo.d.ts +1 -0
- package/examples/google-cloud-run-parallelized/render-worker/src/scenes/example.tsx +30 -0
- package/examples/google-cloud-run-parallelized/render-worker/tsconfig.json +13 -0
- package/examples/google-cloud-run-parallelized/render-worker/vite.config.ts +9 -0
- package/examples/logo.svg +6 -0
- package/examples/logo_dark.svg +6 -0
- package/examples/marketing-templates/README.md +10 -0
- package/examples/marketing-templates/marketing-template/package.json +24 -0
- package/examples/marketing-templates/marketing-template/src/globals.css +0 -0
- package/examples/marketing-templates/marketing-template/src/project.meta +28 -0
- package/examples/marketing-templates/marketing-template/src/project.ts +9 -0
- package/examples/marketing-templates/marketing-template/src/render.ts +15 -0
- package/examples/marketing-templates/marketing-template/src/revideo.d.ts +1 -0
- package/examples/marketing-templates/marketing-template/src/scenes/example.meta +5 -0
- package/examples/marketing-templates/marketing-template/src/scenes/example.tsx +67 -0
- package/examples/marketing-templates/marketing-template/tsconfig.json +9 -0
- package/examples/marketing-templates/marketing-template/vite.config.ts +9 -0
- package/examples/marketing-templates/multiple-videos-in-one/package.json +24 -0
- package/examples/marketing-templates/multiple-videos-in-one/src/project.meta +28 -0
- package/examples/marketing-templates/multiple-videos-in-one/src/project.ts +9 -0
- package/examples/marketing-templates/multiple-videos-in-one/src/render.ts +15 -0
- package/examples/marketing-templates/multiple-videos-in-one/src/revideo.d.ts +1 -0
- package/examples/marketing-templates/multiple-videos-in-one/src/scenes/example.meta +5 -0
- package/examples/marketing-templates/multiple-videos-in-one/src/scenes/example.tsx +122 -0
- package/examples/marketing-templates/multiple-videos-in-one/tsconfig.json +9 -0
- package/examples/marketing-templates/multiple-videos-in-one/vite.config.ts +9 -0
- package/examples/minimal-drag-drop/README.md +29 -0
- package/examples/minimal-drag-drop/next/app/api/render/route.ts +22 -0
- package/examples/minimal-drag-drop/next/app/globals.css +3 -0
- package/examples/minimal-drag-drop/next/app/layout.tsx +25 -0
- package/examples/minimal-drag-drop/next/app/page.tsx +277 -0
- package/examples/minimal-drag-drop/next/next-env.d.ts +5 -0
- package/examples/minimal-drag-drop/next/next.config.mjs +4 -0
- package/examples/minimal-drag-drop/next/package-lock.json +5577 -0
- package/examples/minimal-drag-drop/next/package.json +35 -0
- package/examples/minimal-drag-drop/next/postcss.config.js +6 -0
- package/examples/minimal-drag-drop/next/public/favicon.ico +0 -0
- package/examples/minimal-drag-drop/next/public/next.svg +1 -0
- package/examples/minimal-drag-drop/next/public/vercel.svg +1 -0
- package/examples/minimal-drag-drop/next/tailwind.config.ts +30 -0
- package/examples/minimal-drag-drop/next/tsconfig.json +26 -0
- package/examples/minimal-drag-drop/next/utils/parse.ts +35 -0
- package/examples/minimal-drag-drop/revideo/package-lock.json +3771 -0
- package/examples/minimal-drag-drop/revideo/package.json +24 -0
- package/examples/minimal-drag-drop/revideo/src/global.css +1 -0
- package/examples/minimal-drag-drop/revideo/src/project.meta +28 -0
- package/examples/minimal-drag-drop/revideo/src/project.ts +9 -0
- package/examples/minimal-drag-drop/revideo/src/render.ts +15 -0
- package/examples/minimal-drag-drop/revideo/src/revideo.d.ts +1 -0
- package/examples/minimal-drag-drop/revideo/src/scenes/example.meta +5 -0
- package/examples/minimal-drag-drop/revideo/src/scenes/example.tsx +44 -0
- package/examples/minimal-drag-drop/revideo/tsconfig.json +9 -0
- package/examples/minimal-drag-drop/revideo/vite.config.ts +6 -0
- package/examples/parallelized-aws-lambda/.dockerignore +3 -0
- package/examples/parallelized-aws-lambda/Dockerfile +21 -0
- package/examples/parallelized-aws-lambda/Dockerfile.base +64 -0
- package/examples/parallelized-aws-lambda/README.md +197 -0
- package/examples/parallelized-aws-lambda/revideo-project/.puppeteerrc.cjs +9 -0
- package/examples/parallelized-aws-lambda/revideo-project/package-lock.json +4133 -0
- package/examples/parallelized-aws-lambda/revideo-project/package.json +28 -0
- package/examples/parallelized-aws-lambda/revideo-project/src/lambda.ts +157 -0
- package/examples/parallelized-aws-lambda/revideo-project/src/project.meta +28 -0
- package/examples/parallelized-aws-lambda/revideo-project/src/project.ts +7 -0
- package/examples/parallelized-aws-lambda/revideo-project/src/render.ts +17 -0
- package/examples/parallelized-aws-lambda/revideo-project/src/revideo.d.ts +1 -0
- package/examples/parallelized-aws-lambda/revideo-project/src/scenes/example.meta +5 -0
- package/examples/parallelized-aws-lambda/revideo-project/src/scenes/example.tsx +30 -0
- package/examples/parallelized-aws-lambda/revideo-project/tsconfig.json +10 -0
- package/examples/parallelized-aws-lambda/revideo-project/vite.config.ts +9 -0
- package/examples/reddit-post-video/README.md +84 -0
- package/examples/reddit-post-video/package-lock.json +2941 -0
- package/examples/reddit-post-video/package.json +27 -0
- package/examples/reddit-post-video/src/global.css +1 -0
- package/examples/reddit-post-video/src/metadata.json +576 -0
- package/examples/reddit-post-video/src/project.meta +31 -0
- package/examples/reddit-post-video/src/project.ts +9 -0
- package/examples/reddit-post-video/src/render.ts +157 -0
- package/examples/reddit-post-video/src/revideo.d.ts +1 -0
- package/examples/reddit-post-video/src/scenes/example.meta +5 -0
- package/examples/reddit-post-video/src/scenes/example.tsx +74 -0
- package/examples/reddit-post-video/tsconfig.json +9 -0
- package/examples/reddit-post-video/vite.config.ts +6 -0
- package/examples/rive-explanation-video/README.md +9 -0
- package/examples/rive-explanation-video/package.json +25 -0
- package/examples/rive-explanation-video/src/global.css +1 -0
- package/examples/rive-explanation-video/src/project.meta +31 -0
- package/examples/rive-explanation-video/src/project.ts +8 -0
- package/examples/rive-explanation-video/src/render.ts +15 -0
- package/examples/rive-explanation-video/src/revideo.d.ts +1 -0
- package/examples/rive-explanation-video/src/scenes/example.meta +5 -0
- package/examples/rive-explanation-video/src/scenes/example.tsx +218 -0
- package/examples/rive-explanation-video/tsconfig.json +9 -0
- package/examples/rive-explanation-video/vite.config.ts +8 -0
- package/examples/saas-template/.prettierrc +9 -0
- package/examples/saas-template/README.md +26 -0
- package/examples/saas-template/app/actions.tsx +114 -0
- package/examples/saas-template/app/api/render/route.ts +23 -0
- package/examples/saas-template/app/globals.css +3 -0
- package/examples/saas-template/app/layout.tsx +25 -0
- package/examples/saas-template/app/page.tsx +204 -0
- package/examples/saas-template/next.config.mjs +4 -0
- package/examples/saas-template/package.json +40 -0
- package/examples/saas-template/postcss.config.js +6 -0
- package/examples/saas-template/revideo/global.css +1 -0
- package/examples/saas-template/revideo/project.ts +9 -0
- package/examples/saas-template/revideo/scene.tsx +179 -0
- package/examples/saas-template/tailwind.config.ts +30 -0
- package/examples/saas-template/tsconfig.json +27 -0
- package/examples/saas-template/utils/parse.ts +35 -0
- package/examples/stitching-videos/README.md +7 -0
- package/examples/stitching-videos/package.json +23 -0
- package/examples/stitching-videos/src/project.meta +28 -0
- package/examples/stitching-videos/src/project.ts +20 -0
- package/examples/stitching-videos/src/render.ts +27 -0
- package/examples/stitching-videos/src/revideo.d.ts +1 -0
- package/examples/stitching-videos/src/scenes/example.tsx +30 -0
- package/examples/stitching-videos/tsconfig.json +9 -0
- package/examples/stitching-videos/vite.config.ts +8 -0
- package/examples/three-js-example/README.md +8 -0
- package/examples/three-js-example/package-lock.json +2753 -0
- package/examples/three-js-example/package.json +25 -0
- package/examples/three-js-example/src/components/Three.ts +166 -0
- package/examples/three-js-example/src/global.css +1 -0
- package/examples/three-js-example/src/project.meta +31 -0
- package/examples/three-js-example/src/project.ts +8 -0
- package/examples/three-js-example/src/render.ts +15 -0
- package/examples/three-js-example/src/revideo.d.ts +1 -0
- package/examples/three-js-example/src/scenes/basic3D.meta +5 -0
- package/examples/three-js-example/src/scenes/basic3D.tsx +89 -0
- package/examples/three-js-example/tsconfig.json +9 -0
- package/examples/three-js-example/vite.config.ts +6 -0
- package/examples/youtube-shorts/README.md +65 -0
- package/examples/youtube-shorts/package-lock.json +3881 -0
- package/examples/youtube-shorts/package.json +30 -0
- package/examples/youtube-shorts/src/get-assets.ts +34 -0
- package/examples/youtube-shorts/src/global.css +3 -0
- package/examples/youtube-shorts/src/metadata.json +635 -0
- package/examples/youtube-shorts/src/project.meta +28 -0
- package/examples/youtube-shorts/src/project.ts +9 -0
- package/examples/youtube-shorts/src/render.ts +12 -0
- package/examples/youtube-shorts/src/revideo.d.ts +1 -0
- package/examples/youtube-shorts/src/scenes/example.tsx +224 -0
- package/examples/youtube-shorts/src/utils.ts +123 -0
- package/examples/youtube-shorts/tsconfig.json +9 -0
- package/examples/youtube-shorts/vite.config.ts +8 -0
- package/package.json +9 -9
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "3d-testing",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"start": "vite",
|
|
7
|
+
"serve": "vite",
|
|
8
|
+
"build": "tsc && vite build",
|
|
9
|
+
"render": "tsc && node dist/render.js"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@revideo/2d": "0.5.10",
|
|
13
|
+
"@revideo/core": "0.5.10",
|
|
14
|
+
"@revideo/renderer": "0.5.10",
|
|
15
|
+
"@revideo/ffmpeg": "0.5.10",
|
|
16
|
+
"three": "^0.167.1"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@revideo/ui": "0.5.10",
|
|
20
|
+
"@revideo/vite-plugin": "0.5.10",
|
|
21
|
+
"@types/three": "^0.167.1",
|
|
22
|
+
"typescript": "5.5.4",
|
|
23
|
+
"vite": "^4.0.0"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { Layout, LayoutProps } from "@revideo/2d/lib/components";
|
|
2
|
+
import { computed, initial, signal } from "@revideo/2d/lib/decorators";
|
|
3
|
+
import { Vector2 } from "@revideo/core/lib/types";
|
|
4
|
+
import {
|
|
5
|
+
Camera,
|
|
6
|
+
Color,
|
|
7
|
+
OrthographicCamera,
|
|
8
|
+
PerspectiveCamera,
|
|
9
|
+
Scene,
|
|
10
|
+
WebGLRenderer,
|
|
11
|
+
} from "three";
|
|
12
|
+
import { SimpleSignal } from "@revideo/core/lib/signals";
|
|
13
|
+
|
|
14
|
+
interface RenderCallback {
|
|
15
|
+
(renderer: WebGLRenderer, scene: Scene, camera: Camera): void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ThreeProps extends LayoutProps {
|
|
19
|
+
scene?: Scene;
|
|
20
|
+
camera?: Camera;
|
|
21
|
+
quality?: number;
|
|
22
|
+
background?: string;
|
|
23
|
+
zoom?: number;
|
|
24
|
+
onRender?: RenderCallback;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class Three extends Layout {
|
|
28
|
+
@initial(1)
|
|
29
|
+
@signal()
|
|
30
|
+
public declare readonly quality: SimpleSignal<number, this>;
|
|
31
|
+
|
|
32
|
+
@initial(null)
|
|
33
|
+
@signal()
|
|
34
|
+
public declare readonly camera: SimpleSignal<Camera | null, this>;
|
|
35
|
+
|
|
36
|
+
@initial(null)
|
|
37
|
+
@signal()
|
|
38
|
+
public declare readonly scene: SimpleSignal<Scene | null, this>;
|
|
39
|
+
|
|
40
|
+
@initial(null)
|
|
41
|
+
@signal()
|
|
42
|
+
public declare readonly background: SimpleSignal<string | null, this>;
|
|
43
|
+
|
|
44
|
+
@initial(1)
|
|
45
|
+
@signal()
|
|
46
|
+
public declare readonly zoom: SimpleSignal<number, this>;
|
|
47
|
+
|
|
48
|
+
private readonly renderer: WebGLRenderer;
|
|
49
|
+
private readonly context: WebGLRenderingContext;
|
|
50
|
+
private readonly pixelSample = new Uint8Array(4);
|
|
51
|
+
public onRender: RenderCallback;
|
|
52
|
+
|
|
53
|
+
public constructor({ onRender, ...props }: ThreeProps) {
|
|
54
|
+
super(props);
|
|
55
|
+
this.renderer = borrow();
|
|
56
|
+
this.context = this.renderer.getContext();
|
|
57
|
+
this.onRender =
|
|
58
|
+
onRender ?? ((renderer, scene, camera) => renderer.render(scene, camera));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
protected override async draw(context: CanvasRenderingContext2D) {
|
|
62
|
+
const { width, height } = this.computedSize();
|
|
63
|
+
const quality = this.quality();
|
|
64
|
+
const scene = this.configuredScene();
|
|
65
|
+
const camera = this.configuredCamera();
|
|
66
|
+
const renderer = this.configuredRenderer();
|
|
67
|
+
|
|
68
|
+
if (width > 0 && height > 0) {
|
|
69
|
+
this.onRender(renderer, scene, camera);
|
|
70
|
+
context.imageSmoothingEnabled = false;
|
|
71
|
+
context.drawImage(
|
|
72
|
+
renderer.domElement,
|
|
73
|
+
0,
|
|
74
|
+
0,
|
|
75
|
+
quality * width,
|
|
76
|
+
quality * height,
|
|
77
|
+
width / -2,
|
|
78
|
+
height / -2,
|
|
79
|
+
width,
|
|
80
|
+
height,
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
super.draw(context);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@computed()
|
|
88
|
+
private configuredRenderer(): WebGLRenderer {
|
|
89
|
+
const size = this.computedSize();
|
|
90
|
+
const quality = this.quality();
|
|
91
|
+
|
|
92
|
+
this.renderer.setSize(size.width * quality, size.height * quality);
|
|
93
|
+
return this.renderer;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
@computed()
|
|
97
|
+
private configuredCamera(): Camera {
|
|
98
|
+
const size = this.computedSize();
|
|
99
|
+
const camera = this.camera();
|
|
100
|
+
const ratio = size.width / size.height;
|
|
101
|
+
const scale = this.zoom() / 2;
|
|
102
|
+
if (camera instanceof OrthographicCamera) {
|
|
103
|
+
camera.left = -ratio * scale;
|
|
104
|
+
camera.right = ratio * scale;
|
|
105
|
+
camera.bottom = -scale;
|
|
106
|
+
camera.top = scale;
|
|
107
|
+
camera.updateProjectionMatrix();
|
|
108
|
+
} else if (camera instanceof PerspectiveCamera) {
|
|
109
|
+
camera.aspect = ratio;
|
|
110
|
+
camera.updateProjectionMatrix();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return camera;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
@computed()
|
|
117
|
+
private configuredScene(): Scene | null {
|
|
118
|
+
const scene = this.scene();
|
|
119
|
+
const background = this.background();
|
|
120
|
+
if (scene) {
|
|
121
|
+
scene.background = background ? new Color(background) : null;
|
|
122
|
+
}
|
|
123
|
+
return scene;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
public getColorAtPoint(position: Vector2) {
|
|
127
|
+
const relativePosition = position.scale(this.quality());
|
|
128
|
+
this.context.readPixels(
|
|
129
|
+
relativePosition.x,
|
|
130
|
+
relativePosition.y,
|
|
131
|
+
1,
|
|
132
|
+
1,
|
|
133
|
+
this.context.RGBA,
|
|
134
|
+
this.context.UNSIGNED_BYTE,
|
|
135
|
+
this.pixelSample,
|
|
136
|
+
);
|
|
137
|
+
const color = new Color();
|
|
138
|
+
color.setRGB(
|
|
139
|
+
this.pixelSample[0] / 255,
|
|
140
|
+
this.pixelSample[1] / 255,
|
|
141
|
+
this.pixelSample[2] / 255,
|
|
142
|
+
);
|
|
143
|
+
return color;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
public dispose() {
|
|
147
|
+
dispose(this.renderer);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const pool: WebGLRenderer[] = [];
|
|
152
|
+
function borrow() {
|
|
153
|
+
if (pool.length) {
|
|
154
|
+
return pool.pop();
|
|
155
|
+
} else {
|
|
156
|
+
return new WebGLRenderer({
|
|
157
|
+
canvas: document.createElement("canvas"),
|
|
158
|
+
// antialias: true,
|
|
159
|
+
alpha: true,
|
|
160
|
+
stencil: true,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
function dispose(renderer: WebGLRenderer) {
|
|
165
|
+
pool.push(renderer);
|
|
166
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import url("https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=Lexend:wght@600&family=Noto+Color+Emoji&display=swap");
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 0,
|
|
3
|
+
"shared": {
|
|
4
|
+
"background": "rgb(255,255,255)",
|
|
5
|
+
"range": [
|
|
6
|
+
0,
|
|
7
|
+
null
|
|
8
|
+
],
|
|
9
|
+
"size": {
|
|
10
|
+
"x": 1920,
|
|
11
|
+
"y": 1080
|
|
12
|
+
},
|
|
13
|
+
"audioOffset": 0
|
|
14
|
+
},
|
|
15
|
+
"preview": {
|
|
16
|
+
"fps": 30,
|
|
17
|
+
"resolutionScale": 1
|
|
18
|
+
},
|
|
19
|
+
"rendering": {
|
|
20
|
+
"fps": 60,
|
|
21
|
+
"resolutionScale": 1,
|
|
22
|
+
"colorSpace": "srgb",
|
|
23
|
+
"exporter": {
|
|
24
|
+
"name": "@revideo/core/wasm",
|
|
25
|
+
"options": {
|
|
26
|
+
"fastStart": true,
|
|
27
|
+
"includeAudio": true
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {renderVideo} from '@revideo/renderer';
|
|
2
|
+
|
|
3
|
+
async function render() {
|
|
4
|
+
console.log('Rendering video...');
|
|
5
|
+
|
|
6
|
+
// This is the main function that renders the video
|
|
7
|
+
const file = await renderVideo({
|
|
8
|
+
projectFile: './src/project.ts',
|
|
9
|
+
settings: {logProgress: true},
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
console.log(`Rendered video to ${file}`);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
render();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="@revideo/core/project" />
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import {Three} from '../components/Three';
|
|
2
|
+
import { makeScene2D, Txt } from '@revideo/2d';
|
|
3
|
+
import { tween, waitFor, delay, createRef, all, chain, linear} from '@revideo/core';
|
|
4
|
+
import * as THREE from 'three';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
function setup3DScene() {
|
|
8
|
+
const threeScene = new THREE.Scene();
|
|
9
|
+
|
|
10
|
+
const geometry = new THREE.BoxGeometry( 0.2, 0.2, 0.2 );
|
|
11
|
+
const material = new THREE.MeshNormalMaterial();
|
|
12
|
+
|
|
13
|
+
const mesh = new THREE.Mesh( geometry, material );
|
|
14
|
+
threeScene.add(mesh);
|
|
15
|
+
|
|
16
|
+
const camera = new THREE.PerspectiveCamera(90);
|
|
17
|
+
|
|
18
|
+
mesh.position.set(0, 0, 0);
|
|
19
|
+
mesh.scale.set(1, 1, 1);
|
|
20
|
+
camera.rotation.set(0, 0, 0);
|
|
21
|
+
camera.position.set(0, 0, 0.5);
|
|
22
|
+
|
|
23
|
+
return {threeScene, camera, mesh};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default makeScene2D(function* (view) {
|
|
27
|
+
const {threeScene, camera, mesh} = setup3DScene();
|
|
28
|
+
|
|
29
|
+
const threeRef = createRef<Three>();
|
|
30
|
+
const txtRef = createRef<Txt>();
|
|
31
|
+
|
|
32
|
+
yield view.add(
|
|
33
|
+
<>
|
|
34
|
+
<Three
|
|
35
|
+
width={1920}
|
|
36
|
+
height={1080}
|
|
37
|
+
camera={camera}
|
|
38
|
+
scene={threeScene}
|
|
39
|
+
opacity={0}
|
|
40
|
+
fontWeight={900}
|
|
41
|
+
ref={threeRef}
|
|
42
|
+
/>
|
|
43
|
+
</>
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
yield view.add(<Txt fill={"black"} fontFamily={"Lexend"} ref={txtRef} fontSize={80}/>)
|
|
47
|
+
|
|
48
|
+
yield* chain(
|
|
49
|
+
txtRef().text("Revideo x 3D with Three.js", 1),
|
|
50
|
+
all(
|
|
51
|
+
txtRef().position.y(-300, 1),
|
|
52
|
+
delay(0.5, threeRef().opacity(1, 0.5))
|
|
53
|
+
)
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
yield tween(4, value => {
|
|
57
|
+
mesh.rotation.set(
|
|
58
|
+
0,
|
|
59
|
+
linear(value, 0, 2*3.14),
|
|
60
|
+
0
|
|
61
|
+
);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
yield* waitFor(2);
|
|
65
|
+
|
|
66
|
+
yield addRotatingCube(threeRef().scene(), 0.1, 0.3, -0.2, 0.1);
|
|
67
|
+
yield addRotatingCube(threeRef().scene(), 0.1, -0.3, -0.2, 0.1);
|
|
68
|
+
|
|
69
|
+
yield* waitFor(2);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
function* addRotatingCube(threeScene: THREE.Scene, size: number, x: number, y: number, z: number){
|
|
73
|
+
const geometry = new THREE.BoxGeometry( size, size, size );
|
|
74
|
+
const material = new THREE.MeshNormalMaterial();
|
|
75
|
+
const mesh = new THREE.Mesh( geometry, material );
|
|
76
|
+
|
|
77
|
+
mesh.position.set(x, y, z);
|
|
78
|
+
mesh.scale.set(1, 1, 1);
|
|
79
|
+
|
|
80
|
+
threeScene.add(mesh);
|
|
81
|
+
|
|
82
|
+
yield* tween(4, value => {
|
|
83
|
+
mesh.rotation.set(
|
|
84
|
+
0,
|
|
85
|
+
linear(value, 0, 2*3.14),
|
|
86
|
+
0
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Youtube Shorts with Subtitles
|
|
2
|
+
|
|
3
|
+
This example project lets you generate Youtube Shorts with AI.
|
|
4
|
+
|
|
5
|
+
https://github.com/redotvideo/revideo-examples/assets/122226645/98bc202d-6b7d-4b8a-9a7f-c41533d8c760
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
## Project Structure
|
|
9
|
+
|
|
10
|
+
There are three main files you should look at in this project:
|
|
11
|
+
|
|
12
|
+
- `src/scenes/example.tsx`: This file defines the flow of the video and its animations. It accepts variables such as a list of background images, a voiceover audio file, as well as a list of words along with their timestamps to display the video captions.
|
|
13
|
+
- `src/get-assets.ts`: This is a node.js process which generates assets (script, voiceover, etc.) using AI services and writes them to a json file storing your video variables
|
|
14
|
+
- `src/render.ts`: This code calls `renderVideo()` with variables from a metadata file to export the final video.
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## Getting Started
|
|
18
|
+
|
|
19
|
+
After cloning the repo, go inside the project folder and install all dependencies using `npm install`. Now you can preview an example video.
|
|
20
|
+
|
|
21
|
+
### Preview Video
|
|
22
|
+
|
|
23
|
+
You can start the editor using the following command:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
npm start
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The editor preview uses example assets (images and voiceovers) specified in `src/metadata.json` which are located in an AWS bucket we own. This way, you can test the template without having to generate your own assets. To render the video with the example asseets, click the render button in the UI or run `npm run render`.
|
|
30
|
+
|
|
31
|
+
When previewing the video in the editor, your browser will first have to load the assets, which can cause a bit of a lag - you might have to wait a few seconds.
|
|
32
|
+
|
|
33
|
+
## Rendering Videos with your own AI assets
|
|
34
|
+
If you want to render your own videos using ChatGPT, Dall-E and Elevenlabs voiceovers, you need to create a `.env` file in the project root directory and add the following environment variables:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
OPENAI_API_KEY=<your-openai-key>
|
|
38
|
+
ELEVEN_API_KEY=<your-elevenlabs-key>
|
|
39
|
+
DEEPGRAM_API_KEY=<your-deepgram-key>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Now you can run `tsc && node dist/get-assets.ts`, which will create a new metadata file that you can use in `render.ts` and `project.ts`.
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
## Animating Subtitles
|
|
46
|
+
|
|
47
|
+
This project has a heavy emphasis on animating subtitles. It provides the option to stream subtitles word-by-word, to highlight the currently spoken word, or to let words fade into the image as they appear. To play around with the different caption animation options, you can modify the `textSettings` object in `src/scenes/example.tsx`:
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
const textSettings: captionSettings = {
|
|
51
|
+
fontSize: 80,
|
|
52
|
+
numSimultaneousWords: 4, // how many words are shown at most simultaneously
|
|
53
|
+
textColor: "white",
|
|
54
|
+
fontWeight: 800,
|
|
55
|
+
fontFamily: "Mulish",
|
|
56
|
+
stream: false, // if true, words appear one by one
|
|
57
|
+
textAlign: "center",
|
|
58
|
+
textBoxWidthInPercent: 70,
|
|
59
|
+
fadeInAnimation: true,
|
|
60
|
+
currentWordColor: "cyan",
|
|
61
|
+
currentWordBackgroundColor: "red", // adds a colored box to the word currently spoken
|
|
62
|
+
shadowColor: "black",
|
|
63
|
+
shadowBlur: 30
|
|
64
|
+
}
|
|
65
|
+
```
|