generated from fahricansecer/boilerplate-be
@@ -0,0 +1,7 @@
|
||||
node_modules
|
||||
dist
|
||||
.DS_Store
|
||||
.env
|
||||
|
||||
# Ignore the output video from Git but not videos you import into src/.
|
||||
out
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"useTabs": false,
|
||||
"bracketSpacing": true,
|
||||
"tabWidth": 2
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
# Remotion video
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/remotion-dev/logo">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://github.com/remotion-dev/logo/raw/main/animated-logo-banner-dark.apng">
|
||||
<img alt="Animated Remotion Logo" src="https://github.com/remotion-dev/logo/raw/main/animated-logo-banner-light.gif">
|
||||
</picture>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
Welcome to your Remotion project!
|
||||
|
||||
## Commands
|
||||
|
||||
**Install Dependencies**
|
||||
|
||||
```console
|
||||
npm i
|
||||
```
|
||||
|
||||
**Start Preview**
|
||||
|
||||
```console
|
||||
npm run dev
|
||||
```
|
||||
|
||||
**Render video**
|
||||
|
||||
```console
|
||||
npx remotion render
|
||||
```
|
||||
|
||||
**Upgrade Remotion**
|
||||
|
||||
```console
|
||||
npx remotion upgrade
|
||||
```
|
||||
|
||||
## Docs
|
||||
|
||||
Get started with Remotion by reading the [fundamentals page](https://www.remotion.dev/docs/the-fundamentals).
|
||||
|
||||
## Help
|
||||
|
||||
We provide help on our [Discord server](https://discord.gg/6VzzNDwUwV).
|
||||
|
||||
## Issues
|
||||
|
||||
Found an issue with Remotion? [File an issue here](https://github.com/remotion-dev/remotion/issues/new).
|
||||
|
||||
## License
|
||||
|
||||
Note that for some entities a company license is needed. [Read the terms here](https://github.com/remotion-dev/remotion/blob/main/LICENSE.md).
|
||||
@@ -0,0 +1,3 @@
|
||||
import { config } from "@remotion/eslint-config-flat";
|
||||
|
||||
export default config;
|
||||
Generated
+4920
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "remotion",
|
||||
"version": "1.0.0",
|
||||
"description": "My Remotion video",
|
||||
"repository": {},
|
||||
"license": "UNLICENSED",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@remotion/cli": "4.0.451",
|
||||
"react": "19.2.3",
|
||||
"react-dom": "19.2.3",
|
||||
"remotion": "4.0.451",
|
||||
"@remotion/tailwind-v4": "4.0.451",
|
||||
"tailwindcss": "4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@remotion/eslint-config-flat": "4.0.451",
|
||||
"@types/react": "19.2.7",
|
||||
"@types/web": "0.0.166",
|
||||
"eslint": "9.19.0",
|
||||
"prettier": "3.8.1",
|
||||
"typescript": "5.9.3"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "remotion studio",
|
||||
"build": "remotion bundle",
|
||||
"upgrade": "remotion upgrade",
|
||||
"lint": "eslint src && tsc"
|
||||
},
|
||||
"sideEffects": [
|
||||
"*.css"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Note: When using the Node.JS APIs, the config file
|
||||
* doesn't apply. Instead, pass options directly to the APIs.
|
||||
*
|
||||
* All configuration options: https://remotion.dev/docs/config
|
||||
*/
|
||||
|
||||
import { Config } from "@remotion/cli/config";
|
||||
import { enableTailwind } from '@remotion/tailwind-v4';
|
||||
|
||||
Config.setVideoImageFormat("jpeg");
|
||||
Config.setOverwriteOutput(true);
|
||||
Config.overrideWebpackConfig(enableTailwind);
|
||||
@@ -0,0 +1,3 @@
|
||||
export const MyComposition = () => {
|
||||
return null;
|
||||
};
|
||||
@@ -0,0 +1,135 @@
|
||||
import React from "react";
|
||||
import {
|
||||
AbsoluteFill,
|
||||
Audio,
|
||||
Img,
|
||||
Sequence,
|
||||
useCurrentFrame,
|
||||
useVideoConfig,
|
||||
interpolate,
|
||||
} from "remotion";
|
||||
|
||||
export type SceneProp = {
|
||||
imagePath: string; // absolute path inside docker /data/media/..
|
||||
audioPath?: string;
|
||||
ambientPath?: string;
|
||||
subtitle?: string;
|
||||
durationInFrames: number;
|
||||
};
|
||||
|
||||
export type MainVideoProps = {
|
||||
scenes: SceneProp[];
|
||||
musicPath?: string;
|
||||
};
|
||||
|
||||
export const MainVideo: React.FC<MainVideoProps> = ({ scenes, musicPath }) => {
|
||||
const { fps } = useVideoConfig();
|
||||
|
||||
// Helper: map local absolute path to standard file:// URL so Remotion Chromium can load it
|
||||
const makeFileUrl = (path?: string) => {
|
||||
if (!path) return undefined;
|
||||
if (path.startsWith("http")) return path;
|
||||
if (path.startsWith("file://")) return path;
|
||||
return `file://${path}`;
|
||||
};
|
||||
|
||||
let currentStartFrame = 0;
|
||||
|
||||
return (
|
||||
<AbsoluteFill style={{ backgroundColor: "black" }}>
|
||||
{/* Background Music */}
|
||||
{musicPath && <Audio src={makeFileUrl(musicPath)} volume={0.15} />}
|
||||
|
||||
{scenes.map((scene, index) => {
|
||||
const startFrame = currentStartFrame;
|
||||
currentStartFrame += scene.durationInFrames;
|
||||
|
||||
return (
|
||||
<Sequence
|
||||
key={index}
|
||||
from={startFrame}
|
||||
durationInFrames={scene.durationInFrames}
|
||||
>
|
||||
<SceneRenderer scene={scene} index={index} />
|
||||
</Sequence>
|
||||
);
|
||||
})}
|
||||
</AbsoluteFill>
|
||||
);
|
||||
};
|
||||
|
||||
const SceneRenderer: React.FC<{ scene: SceneProp; index: number }> = ({ scene, index }) => {
|
||||
const frame = useCurrentFrame();
|
||||
const { fps } = useVideoConfig();
|
||||
|
||||
// Ken Burns Effect (Zoom In / Pan)
|
||||
// Even scenes zoom in, odd scenes zoom out slightly for variation
|
||||
const scale = interpolate(
|
||||
frame,
|
||||
[0, scene.durationInFrames],
|
||||
index % 2 === 0 ? [1, 1.1] : [1.1, 1],
|
||||
{ extrapolateRight: "clamp" }
|
||||
);
|
||||
|
||||
const makeFileUrl = (path?: string) => {
|
||||
if (!path) return undefined;
|
||||
if (path.startsWith("http")) return path;
|
||||
if (path.startsWith("file://")) return path;
|
||||
return `file://${path}`;
|
||||
};
|
||||
|
||||
return (
|
||||
<AbsoluteFill style={{ overflow: "hidden" }}>
|
||||
<AbsoluteFill
|
||||
style={{
|
||||
transform: `scale(${scale})`,
|
||||
transformOrigin: "center center",
|
||||
}}
|
||||
>
|
||||
{scene.imagePath ? (
|
||||
<Img
|
||||
src={makeFileUrl(scene.imagePath)}
|
||||
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
||||
/>
|
||||
) : (
|
||||
<AbsoluteFill style={{ backgroundColor: "#111", justifyContent: "center", alignItems: "center" }}>
|
||||
<div style={{ color: "rgba(255, 255, 255, 0.2)", fontSize: "80px", fontFamily: "sans-serif", textAlign: "center", padding: "40px" }}>
|
||||
Visual Not Generated
|
||||
</div>
|
||||
</AbsoluteFill>
|
||||
)}
|
||||
</AbsoluteFill>
|
||||
|
||||
{/* Audio Tracks */}
|
||||
{scene.audioPath && <Audio src={makeFileUrl(scene.audioPath)} />}
|
||||
{scene.ambientPath && <Audio src={makeFileUrl(scene.ambientPath)} volume={0.3} />}
|
||||
|
||||
{/* Subtitles Overlay */}
|
||||
{scene.subtitle && (
|
||||
<AbsoluteFill
|
||||
style={{
|
||||
justifyContent: "flex-end",
|
||||
alignItems: "center",
|
||||
paddingBottom: "80px",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: "rgba(0, 0, 0, 0.6)",
|
||||
color: "white",
|
||||
padding: "15px 30px",
|
||||
borderRadius: "15px",
|
||||
fontSize: "48px",
|
||||
fontFamily: "sans-serif",
|
||||
textAlign: "center",
|
||||
maxWidth: "80%",
|
||||
boxShadow: "0 4px 6px rgba(0,0,0,0.3)",
|
||||
}}
|
||||
>
|
||||
{scene.subtitle}
|
||||
</div>
|
||||
</AbsoluteFill>
|
||||
)}
|
||||
</AbsoluteFill>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
import "./index.css";
|
||||
import { Composition } from "remotion";
|
||||
import { MainVideo } from "./MainVideo";
|
||||
|
||||
export const RemotionRoot: React.FC = () => {
|
||||
return (
|
||||
<>
|
||||
<Composition
|
||||
id="MainVideo"
|
||||
component={MainVideo}
|
||||
durationInFrames={300} // Default value, will be overridden via props
|
||||
fps={30}
|
||||
width={1080}
|
||||
height={1920} // Portrait by default (9:16)
|
||||
defaultProps={{
|
||||
scenes: [],
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
@import "tailwindcss";
|
||||
@@ -0,0 +1,4 @@
|
||||
import { registerRoot } from "remotion";
|
||||
import { RemotionRoot } from "./Root";
|
||||
|
||||
registerRoot(RemotionRoot);
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2018",
|
||||
"module": "commonjs",
|
||||
"jsx": "react-jsx",
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"lib": ["es2015"],
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noUnusedLocals": true
|
||||
},
|
||||
"exclude": ["remotion.config.ts"]
|
||||
}
|
||||
Reference in New Issue
Block a user