@revideo/create 0.5.11-alpha.1101 → 0.5.11-alpha.1103

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.
Files changed (184) hide show
  1. package/examples/README.md +43 -0
  2. package/examples/avatar-with-background/package.json +27 -0
  3. package/examples/avatar-with-background/src/project.meta +31 -0
  4. package/examples/avatar-with-background/src/project.ts +6 -0
  5. package/examples/avatar-with-background/src/render.ts +14 -0
  6. package/examples/avatar-with-background/src/revideo.d.ts +1 -0
  7. package/examples/avatar-with-background/src/scenes/example.meta +5 -0
  8. package/examples/avatar-with-background/src/scenes/example.tsx +28 -0
  9. package/examples/avatar-with-background/tsconfig.json +9 -0
  10. package/examples/avatar-with-background/vite.config.ts +8 -0
  11. package/examples/default/package.json +22 -0
  12. package/examples/default/src/project.tsx +56 -0
  13. package/examples/default/src/render.ts +15 -0
  14. package/examples/default/tsconfig.json +10 -0
  15. package/examples/github-stars-celebration/package-lock.json +3833 -0
  16. package/examples/github-stars-celebration/package.json +24 -0
  17. package/examples/github-stars-celebration/src/global.css +1 -0
  18. package/examples/github-stars-celebration/src/project.meta +28 -0
  19. package/examples/github-stars-celebration/src/project.ts +8 -0
  20. package/examples/github-stars-celebration/src/render.ts +15 -0
  21. package/examples/github-stars-celebration/src/revideo.d.ts +1 -0
  22. package/examples/github-stars-celebration/src/scenes/example.meta +5 -0
  23. package/examples/github-stars-celebration/src/scenes/example.tsx +51 -0
  24. package/examples/github-stars-celebration/tsconfig.json +9 -0
  25. package/examples/github-stars-celebration/vite.config.ts +8 -0
  26. package/examples/google-cloud-run-parallelized/README.md +127 -0
  27. package/examples/google-cloud-run-parallelized/render-orchestrator/Dockerfile +56 -0
  28. package/examples/google-cloud-run-parallelized/render-orchestrator/package.json +22 -0
  29. package/examples/google-cloud-run-parallelized/render-orchestrator/src/index.ts +72 -0
  30. package/examples/google-cloud-run-parallelized/render-orchestrator/src/revideo.d.ts +1 -0
  31. package/examples/google-cloud-run-parallelized/render-orchestrator/tsconfig.json +10 -0
  32. package/examples/google-cloud-run-parallelized/render-worker/.gcloudignore +17 -0
  33. package/examples/google-cloud-run-parallelized/render-worker/.puppeteerrc.cjs +9 -0
  34. package/examples/google-cloud-run-parallelized/render-worker/package.json +30 -0
  35. package/examples/google-cloud-run-parallelized/render-worker/src/index.ts +45 -0
  36. package/examples/google-cloud-run-parallelized/render-worker/src/project.meta +31 -0
  37. package/examples/google-cloud-run-parallelized/render-worker/src/project.ts +6 -0
  38. package/examples/google-cloud-run-parallelized/render-worker/src/render.ts +14 -0
  39. package/examples/google-cloud-run-parallelized/render-worker/src/revideo.d.ts +1 -0
  40. package/examples/google-cloud-run-parallelized/render-worker/src/scenes/example.tsx +30 -0
  41. package/examples/google-cloud-run-parallelized/render-worker/tsconfig.json +13 -0
  42. package/examples/google-cloud-run-parallelized/render-worker/vite.config.ts +9 -0
  43. package/examples/logo.svg +6 -0
  44. package/examples/logo_dark.svg +6 -0
  45. package/examples/marketing-templates/README.md +10 -0
  46. package/examples/marketing-templates/marketing-template/package.json +24 -0
  47. package/examples/marketing-templates/marketing-template/src/globals.css +0 -0
  48. package/examples/marketing-templates/marketing-template/src/project.meta +28 -0
  49. package/examples/marketing-templates/marketing-template/src/project.ts +9 -0
  50. package/examples/marketing-templates/marketing-template/src/render.ts +15 -0
  51. package/examples/marketing-templates/marketing-template/src/revideo.d.ts +1 -0
  52. package/examples/marketing-templates/marketing-template/src/scenes/example.meta +5 -0
  53. package/examples/marketing-templates/marketing-template/src/scenes/example.tsx +67 -0
  54. package/examples/marketing-templates/marketing-template/tsconfig.json +9 -0
  55. package/examples/marketing-templates/marketing-template/vite.config.ts +9 -0
  56. package/examples/marketing-templates/multiple-videos-in-one/package.json +24 -0
  57. package/examples/marketing-templates/multiple-videos-in-one/src/project.meta +28 -0
  58. package/examples/marketing-templates/multiple-videos-in-one/src/project.ts +9 -0
  59. package/examples/marketing-templates/multiple-videos-in-one/src/render.ts +15 -0
  60. package/examples/marketing-templates/multiple-videos-in-one/src/revideo.d.ts +1 -0
  61. package/examples/marketing-templates/multiple-videos-in-one/src/scenes/example.meta +5 -0
  62. package/examples/marketing-templates/multiple-videos-in-one/src/scenes/example.tsx +122 -0
  63. package/examples/marketing-templates/multiple-videos-in-one/tsconfig.json +9 -0
  64. package/examples/marketing-templates/multiple-videos-in-one/vite.config.ts +9 -0
  65. package/examples/minimal-drag-drop/README.md +29 -0
  66. package/examples/minimal-drag-drop/next/app/api/render/route.ts +22 -0
  67. package/examples/minimal-drag-drop/next/app/globals.css +3 -0
  68. package/examples/minimal-drag-drop/next/app/layout.tsx +25 -0
  69. package/examples/minimal-drag-drop/next/app/page.tsx +277 -0
  70. package/examples/minimal-drag-drop/next/next-env.d.ts +5 -0
  71. package/examples/minimal-drag-drop/next/next.config.mjs +4 -0
  72. package/examples/minimal-drag-drop/next/package-lock.json +5577 -0
  73. package/examples/minimal-drag-drop/next/package.json +35 -0
  74. package/examples/minimal-drag-drop/next/postcss.config.js +6 -0
  75. package/examples/minimal-drag-drop/next/public/favicon.ico +0 -0
  76. package/examples/minimal-drag-drop/next/public/next.svg +1 -0
  77. package/examples/minimal-drag-drop/next/public/vercel.svg +1 -0
  78. package/examples/minimal-drag-drop/next/tailwind.config.ts +30 -0
  79. package/examples/minimal-drag-drop/next/tsconfig.json +26 -0
  80. package/examples/minimal-drag-drop/next/utils/parse.ts +35 -0
  81. package/examples/minimal-drag-drop/revideo/package-lock.json +3771 -0
  82. package/examples/minimal-drag-drop/revideo/package.json +24 -0
  83. package/examples/minimal-drag-drop/revideo/src/global.css +1 -0
  84. package/examples/minimal-drag-drop/revideo/src/project.meta +28 -0
  85. package/examples/minimal-drag-drop/revideo/src/project.ts +9 -0
  86. package/examples/minimal-drag-drop/revideo/src/render.ts +15 -0
  87. package/examples/minimal-drag-drop/revideo/src/revideo.d.ts +1 -0
  88. package/examples/minimal-drag-drop/revideo/src/scenes/example.meta +5 -0
  89. package/examples/minimal-drag-drop/revideo/src/scenes/example.tsx +44 -0
  90. package/examples/minimal-drag-drop/revideo/tsconfig.json +9 -0
  91. package/examples/minimal-drag-drop/revideo/vite.config.ts +6 -0
  92. package/examples/parallelized-aws-lambda/.dockerignore +3 -0
  93. package/examples/parallelized-aws-lambda/Dockerfile +21 -0
  94. package/examples/parallelized-aws-lambda/Dockerfile.base +64 -0
  95. package/examples/parallelized-aws-lambda/README.md +197 -0
  96. package/examples/parallelized-aws-lambda/revideo-project/.puppeteerrc.cjs +9 -0
  97. package/examples/parallelized-aws-lambda/revideo-project/package-lock.json +4133 -0
  98. package/examples/parallelized-aws-lambda/revideo-project/package.json +28 -0
  99. package/examples/parallelized-aws-lambda/revideo-project/src/lambda.ts +157 -0
  100. package/examples/parallelized-aws-lambda/revideo-project/src/project.meta +28 -0
  101. package/examples/parallelized-aws-lambda/revideo-project/src/project.ts +7 -0
  102. package/examples/parallelized-aws-lambda/revideo-project/src/render.ts +17 -0
  103. package/examples/parallelized-aws-lambda/revideo-project/src/revideo.d.ts +1 -0
  104. package/examples/parallelized-aws-lambda/revideo-project/src/scenes/example.meta +5 -0
  105. package/examples/parallelized-aws-lambda/revideo-project/src/scenes/example.tsx +30 -0
  106. package/examples/parallelized-aws-lambda/revideo-project/tsconfig.json +10 -0
  107. package/examples/parallelized-aws-lambda/revideo-project/vite.config.ts +9 -0
  108. package/examples/reddit-post-video/README.md +84 -0
  109. package/examples/reddit-post-video/package-lock.json +2941 -0
  110. package/examples/reddit-post-video/package.json +27 -0
  111. package/examples/reddit-post-video/src/global.css +1 -0
  112. package/examples/reddit-post-video/src/metadata.json +576 -0
  113. package/examples/reddit-post-video/src/project.meta +31 -0
  114. package/examples/reddit-post-video/src/project.ts +9 -0
  115. package/examples/reddit-post-video/src/render.ts +157 -0
  116. package/examples/reddit-post-video/src/revideo.d.ts +1 -0
  117. package/examples/reddit-post-video/src/scenes/example.meta +5 -0
  118. package/examples/reddit-post-video/src/scenes/example.tsx +74 -0
  119. package/examples/reddit-post-video/tsconfig.json +9 -0
  120. package/examples/reddit-post-video/vite.config.ts +6 -0
  121. package/examples/rive-explanation-video/README.md +9 -0
  122. package/examples/rive-explanation-video/package.json +25 -0
  123. package/examples/rive-explanation-video/src/global.css +1 -0
  124. package/examples/rive-explanation-video/src/project.meta +31 -0
  125. package/examples/rive-explanation-video/src/project.ts +8 -0
  126. package/examples/rive-explanation-video/src/render.ts +15 -0
  127. package/examples/rive-explanation-video/src/revideo.d.ts +1 -0
  128. package/examples/rive-explanation-video/src/scenes/example.meta +5 -0
  129. package/examples/rive-explanation-video/src/scenes/example.tsx +218 -0
  130. package/examples/rive-explanation-video/tsconfig.json +9 -0
  131. package/examples/rive-explanation-video/vite.config.ts +8 -0
  132. package/examples/saas-template/.prettierrc +9 -0
  133. package/examples/saas-template/README.md +28 -0
  134. package/examples/saas-template/app/actions.tsx +114 -0
  135. package/examples/saas-template/app/api/render/route.ts +23 -0
  136. package/examples/saas-template/app/globals.css +3 -0
  137. package/examples/saas-template/app/layout.tsx +25 -0
  138. package/examples/saas-template/app/page.tsx +204 -0
  139. package/examples/saas-template/next.config.mjs +4 -0
  140. package/examples/saas-template/package.json +39 -0
  141. package/examples/saas-template/postcss.config.js +6 -0
  142. package/examples/saas-template/revideo/global.css +1 -0
  143. package/examples/saas-template/revideo/project.ts +9 -0
  144. package/examples/saas-template/revideo/scene.tsx +179 -0
  145. package/examples/saas-template/tailwind.config.ts +30 -0
  146. package/examples/saas-template/tsconfig.json +27 -0
  147. package/examples/saas-template/utils/parse.ts +35 -0
  148. package/examples/stitching-videos/README.md +7 -0
  149. package/examples/stitching-videos/package.json +23 -0
  150. package/examples/stitching-videos/src/project.meta +28 -0
  151. package/examples/stitching-videos/src/project.ts +20 -0
  152. package/examples/stitching-videos/src/render.ts +27 -0
  153. package/examples/stitching-videos/src/revideo.d.ts +1 -0
  154. package/examples/stitching-videos/src/scenes/example.tsx +30 -0
  155. package/examples/stitching-videos/tsconfig.json +9 -0
  156. package/examples/stitching-videos/vite.config.ts +8 -0
  157. package/examples/three-js-example/README.md +8 -0
  158. package/examples/three-js-example/package-lock.json +2753 -0
  159. package/examples/three-js-example/package.json +25 -0
  160. package/examples/three-js-example/src/components/Three.ts +166 -0
  161. package/examples/three-js-example/src/global.css +1 -0
  162. package/examples/three-js-example/src/project.meta +31 -0
  163. package/examples/three-js-example/src/project.ts +8 -0
  164. package/examples/three-js-example/src/render.ts +15 -0
  165. package/examples/three-js-example/src/revideo.d.ts +1 -0
  166. package/examples/three-js-example/src/scenes/basic3D.meta +5 -0
  167. package/examples/three-js-example/src/scenes/basic3D.tsx +89 -0
  168. package/examples/three-js-example/tsconfig.json +9 -0
  169. package/examples/three-js-example/vite.config.ts +6 -0
  170. package/examples/youtube-shorts/README.md +65 -0
  171. package/examples/youtube-shorts/package-lock.json +3881 -0
  172. package/examples/youtube-shorts/package.json +30 -0
  173. package/examples/youtube-shorts/src/get-assets.ts +34 -0
  174. package/examples/youtube-shorts/src/global.css +3 -0
  175. package/examples/youtube-shorts/src/metadata.json +635 -0
  176. package/examples/youtube-shorts/src/project.meta +28 -0
  177. package/examples/youtube-shorts/src/project.ts +9 -0
  178. package/examples/youtube-shorts/src/render.ts +12 -0
  179. package/examples/youtube-shorts/src/revideo.d.ts +1 -0
  180. package/examples/youtube-shorts/src/scenes/example.tsx +224 -0
  181. package/examples/youtube-shorts/src/utils.ts +123 -0
  182. package/examples/youtube-shorts/tsconfig.json +9 -0
  183. package/examples/youtube-shorts/vite.config.ts +8 -0
  184. package/package.json +9 -9
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "github-stars-celebration",
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/core": "0.5.10",
13
+ "@revideo/2d": "0.5.10",
14
+ "@revideo/renderer": "0.5.10",
15
+ "@revideo/vite-plugin": "0.5.10",
16
+ "@revideo/ffmpeg": "0.5.10"
17
+ },
18
+ "devDependencies": {
19
+ "@revideo/ui": "0.5.10",
20
+ "@revideo/cli": "0.5.10",
21
+ "typescript": "5.5.4",
22
+ "vite": "^4.5"
23
+ }
24
+ }
@@ -0,0 +1 @@
1
+ @import url('https://fonts.googleapis.com/css2?family=Lexend:wght@100..900&display=swap');
@@ -0,0 +1,28 @@
1
+ {
2
+ "version": 0,
3
+ "shared": {
4
+ "background": "rgb(20,20,20)",
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": 30,
21
+ "resolutionScale": 1,
22
+ "colorSpace": "srgb",
23
+ "exporter": {
24
+ "name": "@revideo/core/wasm",
25
+ "options": {}
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,8 @@
1
+ import {makeProject} from '@revideo/core';
2
+ import "./global.css"
3
+
4
+ import example from './scenes/example?scene';
5
+
6
+ export default makeProject({
7
+ scenes: [example],
8
+ });
@@ -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,5 @@
1
+ {
2
+ "version": 0,
3
+ "timeEvents": [],
4
+ "seed": 2126556333
5
+ }
@@ -0,0 +1,51 @@
1
+ import {Audio, Img, Txt, makeScene2D} from '@revideo/2d';
2
+ import {all, useScene, createRef, waitFor, easeInExpo, easeInCubic} from '@revideo/core';
3
+
4
+ export default makeScene2D(function* (view) {
5
+ const rocketRef = createRef<Img>();
6
+ const earthRef = createRef<Img>();
7
+ const txtRef = createRef<Txt>();
8
+ const logoRef = createRef<Img>();
9
+
10
+
11
+ yield view.add(
12
+ <>
13
+ <Img
14
+ width={'20%'}
15
+ ref={earthRef}
16
+ src={'earth.png'}
17
+ position={[-useScene().getSize().width/2+50, useScene().getSize().height/2-50]}
18
+ />,
19
+ <Img
20
+ width={'5%'}
21
+ ref={rocketRef}
22
+ src={
23
+ '/rocket.png'
24
+ }
25
+ position={[earthRef().position().x+150, earthRef().position().y-150]}
26
+ />,
27
+ </>
28
+ );
29
+
30
+ yield* rocketRef().position([1000, -600], 2, easeInCubic);
31
+
32
+ yield view.add(
33
+ <Txt fontFamily={"Lexend"} fill="white" ref={txtRef} textAlign={"center"} fontSize={60}></Txt>
34
+ )
35
+
36
+ yield* txtRef().text("Thank you for 1,000 Github stars!", 2);
37
+
38
+ yield view.add(
39
+ <Img
40
+ width={'1%'}
41
+ ref={logoRef}
42
+ y={-50}
43
+ src={
44
+ 'https://revideo-example-assets.s3.amazonaws.com/revideo-logo-white.png'
45
+ }
46
+ />,
47
+ );
48
+
49
+
50
+ yield* all(txtRef().position.y(150, 2), logoRef().width("30%", 2));
51
+ });
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "@revideo/2d/tsconfig.project.json",
3
+ "include": ["src"],
4
+ "compilerOptions": {
5
+ "noEmit": false,
6
+ "outDir": "dist",
7
+ "module": "CommonJS"
8
+ }
9
+ }
@@ -0,0 +1,8 @@
1
+ import {defineConfig} from 'vite';
2
+ import motionCanvas from '@revideo/vite-plugin';
3
+
4
+ export default defineConfig({
5
+ plugins: [
6
+ motionCanvas(),
7
+ ],
8
+ });
@@ -0,0 +1,127 @@
1
+ # Parallel Rendering with Cloud Functions
2
+
3
+ This project shows you how you can parallelize rendering across multiple Google Cloud functions to get much faster rendering speeds. Instead of rendering, say, 60 seconds of video in one process, we can also use 30 cloud functions to render 2s of video each, and afterwards stitch together the resulting partial videos.
4
+
5
+ In this example, we are going to deploy two services to Google Cloud:
6
+
7
+ - `/render-worker`: This is a Google Cloud Function that is responsible for rendering a partial video. It has access to your video template (`/render-worker/src/scenes`) and receives the number of total workers as well as its worker ID as an input. It accordingly exports the audio and visuals of the partial video.
8
+
9
+ - `/render-orchestrator`: This is a minimal Google Cloud Run service that manages the render workers and is your entrypoint to start rendering jobs. It receives rendering requests along with the number of desired workers, accordingly sends partial render requests to the render workers and merges their results together to obtain the final video
10
+
11
+ ## Getting Started
12
+
13
+ To get started, clone the `revideo-examples` repository and navigate to the `google-cloud-run-parallelized` directory.
14
+
15
+ ### Enable gcloud services
16
+
17
+ To set up your Google Cloud services, ensure that you have the gcloud CLI installed ([guide](https://cloud.google.com/sdk/docs/install)). Then, enable the required services to deploy Cloud Functions:
18
+
19
+ ```
20
+ gcloud services enable run.googleapis.com
21
+ gcloud services enable cloudfunctions.googleapis.com
22
+ gcloud services enable storage.googleapis.com
23
+ gcloud services enable cloudbuild.googleapis.com
24
+ ```
25
+
26
+ ### Create Storage Bucket
27
+
28
+ You'll need a storage bucket to save your videos as well as partial videos to. To create one, run the following command and replace `<your-region>` with your desired region (e.g. `us-east1`):
29
+
30
+ ```
31
+ gsutil mb -l <your-region> gs://<your-bucket-name>/
32
+ ```
33
+
34
+ Now enable public read access by running the following command:
35
+
36
+ ```
37
+ gsutil iam ch allUsers:objectViewer gs://<your-bucket-name>/
38
+ ```
39
+
40
+ Finally, you need to modify the CORS settings of your bucket. To do so, create the following file `cors_config.json`:
41
+
42
+ ```
43
+ [
44
+ {
45
+ "origin": ["*"],
46
+ "responseHeader": ["Content-Type"],
47
+ "method": ["GET", "HEAD", "DELETE"],
48
+ "maxAgeSeconds": 3600
49
+ }
50
+ ]
51
+ ```
52
+
53
+ Now run:
54
+
55
+ ```
56
+ gsutil cors set cors_config.json gs://<your-bucket-name>/
57
+ ```
58
+
59
+ Now you can deploy your render worker cloud function.
60
+
61
+
62
+ ### Deploy Render Worker Cloud Function
63
+
64
+ To deploy the render worker cloud function, navigate to `/render-worker` and run `npm install`. Now run the following command:
65
+
66
+ 🚨 **Note:** In the commands below, make sure to select the same region (<your-region>) as the bucket you just created. Otherwise, your render jobs will run much slower.
67
+
68
+ ```
69
+ gcloud functions deploy render-worker \
70
+ --runtime nodejs18 \
71
+ --trigger-http \
72
+ --allow-unauthenticated \
73
+ --gen2 \
74
+ --memory 4Gi \
75
+ --cpu 2 \
76
+ --concurrency=1 \
77
+ --timeout=3600s \
78
+ --region=<your-region> \
79
+ --set-env-vars=FFMPEG_PATH=ffmpeg,FFPROBE_PATH=ffprobe,GCP_BUCKET_NAME=<your-bucket-name>
80
+ ```
81
+
82
+ You'll now have to wait some time for the deployment. Once your cloud function is deployed, its URL will be logged to the terminal (we will reference it as `<your-render-function-url>`). You will need this URL to configure your cloud run service that calls the cloud function you just deployed.
83
+
84
+
85
+ ### Deploy Render Orchestrator Cloud Run Service
86
+
87
+ To deploy the service that orchestrates the cloud functions, navigate to `/render-orchestrator`, then run `npm install` and the following command:
88
+
89
+ ```
90
+ gcloud run deploy render-orchestrator \
91
+ --source . \
92
+ --memory 8Gi \
93
+ --cpu 4 \
94
+ --allow-unauthenticated \
95
+ --concurrency=1 \
96
+ --timeout=3600s \
97
+ --region <your-region> \
98
+ --set-env-vars=FFMPEG_PATH=ffmpeg,FFPROBE_PATH=ffprobe,GCP_BUCKET_NAME=<your-bucket-name>,RENDER_WORKER_URL=<your-render-function-url>
99
+ ```
100
+
101
+ Again, you'll have to wait a bit for the service to be deployed. Once that is done, you can send a request to its url `<your-render-orchestrator-url>`.
102
+
103
+ ### Sending a Request
104
+
105
+ Once the render worker and orchestrator are running, you can send a render request as follows:
106
+
107
+ ```
108
+ curl -X POST <your-render-orchestrator-url>/render \
109
+ -H "Content-Type: application/json" \
110
+ -d '{"variables": {"username": "John"}, "numWorkers": 5}'
111
+ ```
112
+
113
+ This will distribute the rendering work across five cloud functions. You can check out the logs and rendering progress in the Google Cloud Function logs.
114
+
115
+
116
+ ## Usage Notes
117
+
118
+ Some useful information, as well as considerations on what parameters to use:
119
+
120
+ **Cold Start times:**
121
+ Depending on your previous usage, your Google Cloud account & project might not be prioritized for cold start times, and thus the bottleneck of your render speeds might be cold start tiems. You can check the logs of your render worker function to see how fast the render workers spin up after sending the request. For example, we have noticed that after creating a new Google Cloud project, we sometimes had to wait for 30s+ for a render worker to spin up, whereas cold start times were very fast on a project that we had been using for a lot of time already.
122
+
123
+ **Video Duration:**
124
+ Parallel rendering is especially effective for longer videos (>1 min). For short videos, the overhead of waiting for a bunch of cloud functions to cold boot may not be worth it
125
+
126
+ **Choosing the number of workers:**
127
+ Depending on the length of the video you're going to render, you might want to adjust the `numWorkers` parameter. A single worker should not render less than a second of video
@@ -0,0 +1,56 @@
1
+ FROM node:18-bullseye
2
+
3
+ RUN apt-get update && apt-get install -y \
4
+ nscd \
5
+ libnss3 \
6
+ libdbus-1-3 \
7
+ libatk1.0-0 \
8
+ libatk-bridge2.0-0 \
9
+ libcups2 \
10
+ libxkbcommon0 \
11
+ libxcomposite1 \
12
+ libxdamage1 \
13
+ libxrandr2 \
14
+ libgbm1 \
15
+ libpango-1.0-0 \
16
+ libcairo2 \
17
+ libasound2 \
18
+ libatspi2.0-0
19
+
20
+ RUN apt-get install -y libxfixes3
21
+
22
+ WORKDIR /usr/src/app
23
+
24
+ RUN wget https://github.com/eugeneware/ffmpeg-static/releases/download/b6.0/ffmpeg-linux-x64
25
+
26
+ RUN chmod +x ffmpeg-linux-x64
27
+
28
+ RUN mv ffmpeg-linux-x64 ffmpeg
29
+
30
+ RUN mv ffmpeg /usr/local/bin/
31
+
32
+ ENV FFMPEG_PATH=ffmpeg
33
+
34
+ RUN wget https://github.com/eugeneware/ffmpeg-static/releases/download/b6.0/ffprobe-linux-x64
35
+
36
+ RUN chmod +x ffprobe-linux-x64
37
+
38
+ RUN mv ffprobe-linux-x64 ffprobe
39
+
40
+ RUN mv ffprobe /usr/local/bin/
41
+
42
+ ENV FFPROBE_PATH=ffprobe
43
+
44
+ COPY package*.json ./
45
+
46
+ COPY . ./
47
+
48
+ RUN npm install
49
+
50
+ RUN npx puppeteer browsers install chrome
51
+
52
+ RUN apt-get update && apt-get install -y nscd libnss3
53
+
54
+ RUN ffmpeg -version
55
+
56
+ CMD service nscd start && npm start
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "google-cloud-run",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "scripts": {
6
+ "start": "tsc && node dist/index.js"
7
+ },
8
+ "dependencies": {
9
+ "@google-cloud/storage": "^7.11.0",
10
+ "@revideo/2d": "0.5.10",
11
+ "@revideo/core": "0.5.10",
12
+ "@revideo/ffmpeg": "0.5.10",
13
+ "express": "^4.19.2",
14
+ "uuid": "^9.0.1"
15
+ },
16
+ "devDependencies": {
17
+ "@types/express": "^4.17.21",
18
+ "@types/uuid": "^9.0.8",
19
+ "typescript": "^5.4.5",
20
+ "vite": "^4.5"
21
+ }
22
+ }
@@ -0,0 +1,72 @@
1
+ import { mergeAudioWithVideo, concatenateMedia } from '@revideo/ffmpeg';
2
+ import { Storage } from '@google-cloud/storage';
3
+ import * as express from 'express';
4
+ import * as fs from 'fs';
5
+ import axios from 'axios';
6
+ import { v4 as uuidv4 } from 'uuid';
7
+
8
+ const storage = new Storage();
9
+
10
+ const app = express();
11
+ app.use(express.json());
12
+
13
+ app.get('/', (req, res) => {
14
+ res.status(200).send(`Hello World!`);
15
+ });
16
+
17
+ app.post('/render', async (req, res) => {
18
+ try {
19
+ const { variables, numWorkers } = req.body;
20
+ const jobId = uuidv4();
21
+
22
+ const renderPromises = [];
23
+ for (let i = 0; i < numWorkers; i++) {
24
+ renderPromises.push(makeRenderRequest(variables, i, numWorkers));
25
+ }
26
+
27
+ const results = await Promise.all(renderPromises);
28
+ const audios = results.map(result => result.audioUrl);
29
+ const videos = results.map(result => result.videoUrl);
30
+
31
+ await Promise.all([
32
+ concatenateMedia(audios, `${jobId}-audio.wav`),
33
+ concatenateMedia(videos, `${jobId}-visuals.mp4`)
34
+ ]);
35
+
36
+ await mergeAudioWithVideo(`${jobId}-audio.wav`, `${jobId}-visuals.mp4`, `${jobId}.mp4`);
37
+
38
+ const resultFileBuffer = fs.readFileSync(`${jobId}.mp4`);
39
+ await storage.bucket(process.env.GCP_BUCKET_NAME).file(`${jobId}.mp4`).save(resultFileBuffer);
40
+
41
+ res.status(200).json({
42
+ file: `https://storage.googleapis.com/${process.env.GCP_BUCKET_NAME}/${`${jobId}.mp4`}`
43
+ });
44
+ } catch (err) {
45
+ console.error('Error rendering video:', err);
46
+ res.status(500).send(`Error rendering video: ${err}`);
47
+ }
48
+ });
49
+
50
+ const port = parseInt(process.env.PORT) || 8080;
51
+ app.listen(port, () => {
52
+ console.log(`listening on port ${port}`);
53
+ });
54
+
55
+ async function makeRenderRequest(variables: any, workerId: number, numWorkers: number) {
56
+ try {
57
+ const response = await axios.post(`${process.env.RENDER_WORKER_URL}`, {
58
+ variables,
59
+ workerId,
60
+ numWorkers
61
+ }, {
62
+ headers: {
63
+ 'Content-Type': 'application/json'
64
+ }
65
+ });
66
+
67
+ return response.data;
68
+ } catch (error) {
69
+ console.error('Error making render request:', error);
70
+ }
71
+ }
72
+
@@ -0,0 +1 @@
1
+ /// <reference types="@revideo/core/project" />
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "@revideo/2d/tsconfig.project.json",
3
+ "include": ["src"],
4
+ "compilerOptions": {
5
+ "noEmit": false,
6
+ "outDir": "dist",
7
+ "module": "CommonJS"
8
+ }
9
+ }
10
+
@@ -0,0 +1,17 @@
1
+ # This file specifies files that are *not* uploaded to Google Cloud
2
+ # using gcloud. It follows the same syntax as .gitignore, with the addition of
3
+ # "#!include" directives (which insert the entries of the given .gitignore-style
4
+ # file at that point).
5
+ #
6
+ # For more information, run:
7
+ # $ gcloud topic gcloudignore
8
+ #
9
+ .gcloudignore
10
+ # If you would like to upload your .git directory, .gitignore file or files
11
+ # from your .gitignore file, remove the corresponding line
12
+ # below:
13
+ .git
14
+ .gitignore
15
+
16
+ node_modules
17
+ #!include:.gitignore
@@ -0,0 +1,9 @@
1
+ const { join } = require('path');
2
+
3
+ /**
4
+ * @type {import("puppeteer").Configuration}
5
+ */
6
+ module.exports = {
7
+ cacheDirectory: join(__dirname, '.cache', 'puppeteer'),
8
+ };
9
+ // [END monitoring_synthetic_monitoring_custom_puppeteer_cjs]
@@ -0,0 +1,30 @@
1
+ {
2
+ "main": "dist/index.js",
3
+ "scripts": {
4
+ "editor": "vite",
5
+ "build": "tsc",
6
+ "start": "functions-framework --target=render-worker",
7
+ "prestart": "npm run build",
8
+ "gcp-build": "node node_modules/puppeteer/install.mjs && npm run build"
9
+ },
10
+ "dependencies": {
11
+ "@ffmpeg-installer/ffmpeg": "^1.1.0",
12
+ "@ffprobe-installer/ffprobe": "^2.1.2",
13
+ "@google-cloud/functions-framework": "^3.4.0",
14
+ "@google-cloud/storage": "^7.11.0",
15
+ "@revideo/2d": "0.5.10",
16
+ "@revideo/cli": "0.5.10",
17
+ "@revideo/core": "0.5.10",
18
+ "@revideo/ffmpeg": "0.5.10",
19
+ "@revideo/renderer": "0.5.10",
20
+ "@revideo/ui": "0.5.10",
21
+ "@revideo/vite-plugin": "0.5.10",
22
+ "@types/express": "^4.17.21",
23
+ "@types/uuid": "^9.0.8",
24
+ "express": "^4.19.2",
25
+ "puppeteer": "^22.9.0",
26
+ "typescript": "5.5.4",
27
+ "uuid": "^9.0.1",
28
+ "vite": "^4.5"
29
+ }
30
+ }
@@ -0,0 +1,45 @@
1
+ import * as ff from '@google-cloud/functions-framework';
2
+ import { renderPartialVideo } from '@revideo/renderer';
3
+ import { Storage } from '@google-cloud/storage';
4
+ import { v4 as uuidv4 } from 'uuid';
5
+ import * as fs from 'fs';
6
+
7
+ const storage = new Storage();
8
+
9
+ ff.http('render-worker', async (req: ff.Request, res: ff.Response) => {
10
+ try {
11
+ const { workerId, numWorkers, variables } = req.body;
12
+ const jobId = uuidv4();
13
+
14
+ console.log("Rendering video...")
15
+ const {audioFile, videoFile} = await renderPartialVideo({
16
+ projectFile: "./src/project.ts",
17
+ workerId,
18
+ numWorkers,
19
+ variables,
20
+ settings: { outFile: `${jobId}.mp4`, logProgress: true, puppeteer: { args: ['--no-sandbox', '--disable-setuid-sandbox'] }}
21
+ });
22
+
23
+ const audioFileName = `${jobId}-audio.mp3`;
24
+ const audioFileBuffer = fs.readFileSync(audioFile);
25
+ const audioFileUploadPromise = storage.bucket(process.env.GCP_BUCKET_NAME || "").file(audioFileName).save(audioFileBuffer);
26
+
27
+ const videoFileName = `${jobId}-video.mp4`;
28
+ const videoFileBuffer = fs.readFileSync(videoFile);
29
+ const videoFileUploadPromise = storage.bucket(process.env.GCP_BUCKET_NAME || "").file(videoFileName).save(videoFileBuffer);
30
+
31
+ await Promise.all([audioFileUploadPromise, videoFileUploadPromise]);
32
+ const audioFileUrl = `https://storage.googleapis.com/${process.env.GCP_BUCKET_NAME || ""}/${audioFileName}`;
33
+ const videoFileUrl = `https://storage.googleapis.com/${process.env.GCP_BUCKET_NAME || ""}/${videoFileName}`;
34
+
35
+ console.log("done");
36
+ res.status(200).json({
37
+ audioUrl: audioFileUrl,
38
+ videoUrl: videoFileUrl
39
+ });
40
+
41
+ } catch (err) {
42
+ console.error('Error rendering video:', err);
43
+ res.status(500).send(`Error rendering video: ${err}`);
44
+ }
45
+ });
@@ -0,0 +1,31 @@
1
+ {
2
+ "version": 0,
3
+ "shared": {
4
+ "background": "rgb(0,0,0)",
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": 30,
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,6 @@
1
+ import {makeProject} from '@revideo/core';
2
+ import example from './scenes/example?scene';
3
+
4
+ export default makeProject({
5
+ scenes: [example]
6
+ });
@@ -0,0 +1,14 @@
1
+ import {renderVideo} from '@revideo/renderer';
2
+
3
+ async function render() {
4
+ console.log('Rendering video...');
5
+
6
+ const file = await renderVideo({
7
+ projectFile: './src/project.ts',
8
+ settings: {logProgress: true}
9
+ });
10
+
11
+ console.log(`Rendered video to ${file}`);
12
+ }
13
+
14
+ render();
@@ -0,0 +1 @@
1
+ /// <reference types="@revideo/core/project" />
@@ -0,0 +1,30 @@
1
+ import {Audio, Txt, Video, makeScene2D} from '@revideo/2d';
2
+ import {all, chain, createRef, waitFor, useScene} from '@revideo/core';
3
+
4
+ export default makeScene2D(function* (view) {
5
+ const textRef = createRef<Txt>();
6
+
7
+ yield view.add(
8
+ <>
9
+ <Video
10
+ src={'https://revideo-example-assets.s3.amazonaws.com/beach-3.mp4'}
11
+ size={['100%', '100%']}
12
+ play={true}
13
+ />
14
+ <Audio
15
+ src={'https://revideo-example-assets.s3.amazonaws.com/chill-beat.mp3'}
16
+ play={true}
17
+ time={17.0}
18
+ />
19
+ </>,
20
+ );
21
+
22
+ yield* waitFor(1);
23
+
24
+ view.add(
25
+ <Txt fontFamily={"Sans-Serif"} fill={"white"} fontSize={10} ref={textRef}>Hello {useScene().variables.get("username", "user")()}</Txt>
26
+ );
27
+
28
+ yield* textRef().scale(10, 1);
29
+ yield* waitFor(30);
30
+ });
@@ -0,0 +1,13 @@
1
+ {
2
+ "extends": "@revideo/2d/tsconfig.project.json",
3
+ "compilerOptions": {
4
+ "target": "es2016",
5
+ "module": "commonjs",
6
+ "esModuleInterop": true,
7
+ "strict": true,
8
+ "outDir": "dist",
9
+ "noEmit": false
10
+ },
11
+ "include": ["src/**/*"],
12
+ "exclude": ["node_modules"]
13
+ }