├── .gitignore
├── 1-new-project
├── .eslintrc.json
├── .gitignore
├── .prettierrc
├── README.md
├── components
│ └── Main.tsx
├── next.config.js
├── package-lock.json
├── package.json
├── pages
│ ├── _app.tsx
│ ├── _document.tsx
│ ├── api
│ │ └── videos.ts
│ └── index.tsx
├── public
│ └── favicon.ico
├── styles
│ ├── Home.module.css
│ └── globals.css
└── tsconfig.json
├── 2-basic-scene
├── .eslintrc.json
├── .gitignore
├── .prettierrc
├── README.md
├── components
│ └── Main.tsx
├── next.config.js
├── package-lock.json
├── package.json
├── pages
│ ├── _app.tsx
│ ├── _document.tsx
│ ├── api
│ │ └── videos.ts
│ └── index.tsx
├── public
│ └── favicon.ico
├── styles
│ ├── Home.module.css
│ └── globals.css
├── tsconfig.json
└── utility
│ └── getBasicComposition.ts
├── 3-live-editing
├── .eslintrc.json
├── .gitignore
├── .prettierrc
├── README.md
├── components
│ └── Main.tsx
├── next.config.js
├── package-lock.json
├── package.json
├── pages
│ ├── _app.tsx
│ ├── _document.tsx
│ ├── api
│ │ └── videos.ts
│ └── index.tsx
├── public
│ └── favicon.ico
├── styles
│ ├── Home.module.css
│ └── globals.css
├── tsconfig.json
└── utility
│ └── getBasicComposition.ts
├── 4-play-and-pause
├── .eslintrc.json
├── .gitignore
├── .prettierrc
├── README.md
├── components
│ └── Main.tsx
├── next.config.js
├── package-lock.json
├── package.json
├── pages
│ ├── _app.tsx
│ ├── _document.tsx
│ ├── api
│ │ └── videos.ts
│ └── index.tsx
├── public
│ └── favicon.ico
├── styles
│ ├── Home.module.css
│ └── globals.css
├── tsconfig.json
└── utility
│ └── getBasicComposition.ts
├── 5-state-management
├── .eslintrc.json
├── .gitignore
├── .prettierrc
├── README.md
├── components
│ └── Main.tsx
├── next.config.js
├── package-lock.json
├── package.json
├── pages
│ ├── _app.tsx
│ ├── _document.tsx
│ ├── api
│ │ └── videos.ts
│ └── index.tsx
├── public
│ └── favicon.ico
├── styles
│ ├── Home.module.css
│ └── globals.css
├── tsconfig.json
└── utility
│ └── getBasicComposition.ts
├── 6-interactivity
├── .eslintrc.json
├── .gitignore
├── .prettierrc
├── README.md
├── components
│ ├── Main.tsx
│ └── ProgressControl.tsx
├── next.config.js
├── package-lock.json
├── package.json
├── pages
│ ├── _app.tsx
│ ├── _document.tsx
│ ├── api
│ │ └── videos.ts
│ └── index.tsx
├── public
│ └── favicon.ico
├── styles
│ ├── Home.module.css
│ └── globals.css
├── tsconfig.json
└── utility
│ └── getBasicComposition.ts
├── 7-advanced-mutation
├── .eslintrc.json
├── .gitignore
├── .prettierrc
├── README.md
├── components
│ └── Main.tsx
├── next.config.js
├── package-lock.json
├── package.json
├── pages
│ ├── _app.tsx
│ ├── _document.tsx
│ ├── api
│ │ └── videos.ts
│ └── index.tsx
├── public
│ └── favicon.ico
├── styles
│ ├── Home.module.css
│ └── globals.css
├── tsconfig.json
└── utility
│ ├── addSlide.ts
│ ├── createSlide.ts
│ ├── ensureElementVisibility.ts
│ └── getSlideshowComposition.ts
├── 8-final-project
├── .eslintrc.json
├── .gitignore
├── .prettierrc
├── README.md
├── components
│ ├── CreateButton.tsx
│ ├── Main.tsx
│ └── SettingsPanel.tsx
├── next.config.js
├── package-lock.json
├── package.json
├── pages
│ ├── _app.tsx
│ ├── _document.tsx
│ ├── api
│ │ └── videos.ts
│ └── index.tsx
├── public
│ └── favicon.ico
├── styles
│ ├── Home.module.css
│ └── globals.css
├── tsconfig.json
└── utility
│ ├── addSlide.ts
│ ├── createSlide.ts
│ ├── deepClone.ts
│ ├── ensureElementVisibility.ts
│ ├── finishVideo.tsx
│ ├── setPropertyValue.ts
│ ├── setSlideTransition.ts
│ ├── setTextStyle.tsx
│ └── useWindowWidth.ts
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | /.idea
2 |
--------------------------------------------------------------------------------
/1-new-project/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "next/core-web-vitals"
3 | }
4 |
--------------------------------------------------------------------------------
/1-new-project/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 |
15 | # production
16 | /build
17 |
18 | # misc
19 | .DS_Store
20 | *.pem
21 |
22 | # debug
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 |
27 | # local env files
28 | .env*.local
29 |
30 | # vercel
31 | .vercel
32 |
33 | # typescript
34 | *.tsbuildinfo
35 | next-env.d.ts
36 |
37 | # JetBrains editors
38 | /.idea
39 |
--------------------------------------------------------------------------------
/1-new-project/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 120,
3 | "trailingComma": "all",
4 | "tabWidth": 2,
5 | "semi": true,
6 | "singleQuote": true
7 | }
8 |
--------------------------------------------------------------------------------
/1-new-project/README.md:
--------------------------------------------------------------------------------
1 | # Video Editor Tutorial – New Project
2 |
3 | This example is part of this article: [How to Build a Video Editor in JavaScript](https://creatomate.com/blog/how-to-build-a-video-editor-in-javascript)
4 |
5 | ---
6 |
7 | Run it with the following command:
8 |
9 | ```bash
10 | npm install && npm run dev
11 | ```
12 |
13 | You can also try it online using StackBlitz (Chrome and Edge only):
14 |
15 | [](https://stackblitz.com/github/creatomate/video-editor-tutorial/tree/main/1-new-project)
16 |
--------------------------------------------------------------------------------
/1-new-project/components/Main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Inter } from 'next/font/google';
3 | import styles from '@/styles/Home.module.css';
4 |
5 | const inter = Inter({ subsets: ['latin'] });
6 |
7 | export const Main: React.FC = () => {
8 | return (
9 |