Mbonea
commited on
Commit
•
1c1e321
0
Parent(s):
intial commit
Browse files- .github/workflows/render-video.yml +30 -0
- .gitignore +4 -0
- .vscode/Rectifier.code-workspace +26 -0
- .vscode/settings.json +8 -0
- App/Editor/Schema.py +13 -0
- App/Editor/editorRoutes.py +32 -0
- App/Worker.py +89 -0
- App/__init__.py +9 -0
- App/app.py +18 -0
- App/celery_config.py +19 -0
- Remotion-app/.gitattributes +35 -0
- Remotion-app/.gitignore +6 -0
- Remotion-app/.prettierrc +14 -0
- Remotion-app/Dockerfile +35 -0
- Remotion-app/README.md +54 -0
- Remotion-app/package.json +28 -0
- Remotion-app/remotion.config.js +9 -0
- Remotion-app/src/HelloWorld/Subtitle.jsx +59 -0
- Remotion-app/src/HelloWorld/Transcription.json +105 -0
- Remotion-app/src/HelloWorld/constants.js +6 -0
- Remotion-app/src/HelloWorld/index.jsx +48 -0
- Remotion-app/src/Root.jsx +21 -0
- Remotion-app/src/index.js +7 -0
- requirements.txt +19 -0
- sample.py +1 -0
.github/workflows/render-video.yml
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: Render video
|
2 |
+
on:
|
3 |
+
workflow_dispatch:
|
4 |
+
inputs:
|
5 |
+
titleText:
|
6 |
+
description: "Which text should it say?"
|
7 |
+
required: true
|
8 |
+
default: "Welcome to Remotion"
|
9 |
+
titleColor:
|
10 |
+
description: "Which color should it be in?"
|
11 |
+
required: true
|
12 |
+
default: "black"
|
13 |
+
jobs:
|
14 |
+
render:
|
15 |
+
name: Render video
|
16 |
+
runs-on: ubuntu-latest
|
17 |
+
steps:
|
18 |
+
- uses: actions/checkout@main
|
19 |
+
- uses: actions/setup-node@main
|
20 |
+
- run: sudo apt update
|
21 |
+
- run: sudo apt install ffmpeg
|
22 |
+
- run: npm i
|
23 |
+
- run: echo $WORKFLOW_INPUT > input-props.json
|
24 |
+
env:
|
25 |
+
WORKFLOW_INPUT: ${{ toJson(github.event.inputs) }}
|
26 |
+
- run: npm run build -- --props="./input-props.json"
|
27 |
+
- uses: actions/upload-artifact@v2
|
28 |
+
with:
|
29 |
+
name: video.mp4
|
30 |
+
path: out/video.mp4
|
.gitignore
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
*.pyc
|
2 |
+
*.session
|
3 |
+
*.session-journal
|
4 |
+
.env
|
.vscode/Rectifier.code-workspace
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"folders": [
|
3 |
+
{
|
4 |
+
"path": ".."
|
5 |
+
},
|
6 |
+
{
|
7 |
+
"path": "../../short/.github"
|
8 |
+
},
|
9 |
+
{
|
10 |
+
"path": "../../short/.vscode"
|
11 |
+
},
|
12 |
+
{
|
13 |
+
"path": "../../short/node_modules"
|
14 |
+
},
|
15 |
+
{
|
16 |
+
"path": "../../short/out"
|
17 |
+
},
|
18 |
+
{
|
19 |
+
"path": "../../short/public"
|
20 |
+
},
|
21 |
+
{
|
22 |
+
"path": "../../short/src"
|
23 |
+
}
|
24 |
+
],
|
25 |
+
"settings": {}
|
26 |
+
}
|
.vscode/settings.json
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"editor.tabSize": 2,
|
3 |
+
"typescript.tsdk": "node_modules/typescript/lib",
|
4 |
+
"editor.codeActionsOnSave": {
|
5 |
+
"source.organizeImports": false
|
6 |
+
},
|
7 |
+
"typescript.enablePromptUseWorkspaceTsdk": true
|
8 |
+
}
|
App/Editor/Schema.py
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import List, Optional
|
2 |
+
from pydantic import BaseModel, HttpUrl
|
3 |
+
|
4 |
+
|
5 |
+
class EditorRequest(BaseModel):
|
6 |
+
links: Optional[List[HttpUrl]]
|
7 |
+
script: str
|
8 |
+
|
9 |
+
|
10 |
+
class TaskInfo(BaseModel):
|
11 |
+
task_id: str
|
12 |
+
progress: int
|
13 |
+
completed_tasks: List[str]
|
App/Editor/editorRoutes.py
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from fastapi import APIRouter, HTTPException, status
|
2 |
+
from .Schema import EditorRequest, TaskInfo
|
3 |
+
from App.Worker import celery_task
|
4 |
+
from celery.result import AsyncResult
|
5 |
+
|
6 |
+
videditor_router = APIRouter(tags=["vidEditor"])
|
7 |
+
|
8 |
+
|
9 |
+
@videditor_router.post("/create-video")
|
10 |
+
async def create_video(videoRequest: EditorRequest):
|
11 |
+
result = celery_task.delay(videoRequest)
|
12 |
+
return {"task_id": result.task_id}
|
13 |
+
|
14 |
+
|
15 |
+
@videditor_router.get("/progress/{task_id}", response_model=TaskInfo)
|
16 |
+
async def progress(task_id: str):
|
17 |
+
task_result = AsyncResult(
|
18 |
+
task_id,
|
19 |
+
)
|
20 |
+
if not task_result.ready():
|
21 |
+
progress = task_result.info.get("progress", 0)
|
22 |
+
completed_tasks = task_result.info.get("completed_tasks", [])
|
23 |
+
return {
|
24 |
+
"task_id": task_id,
|
25 |
+
"progress": progress,
|
26 |
+
"completed_tasks": completed_tasks,
|
27 |
+
}
|
28 |
+
else:
|
29 |
+
raise HTTPException(
|
30 |
+
status_code=status.HTTP_404_NOT_FOUND,
|
31 |
+
detail="Task not found",
|
32 |
+
)
|
App/Worker.py
ADDED
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from celery import Celery, chain
|
2 |
+
import os, shutil, subprocess
|
3 |
+
import uuid
|
4 |
+
import time
|
5 |
+
from App import celery_config, bot
|
6 |
+
from typing import List
|
7 |
+
from App.Editor.Schema import EditorRequest
|
8 |
+
from celery.signals import worker_process_init
|
9 |
+
|
10 |
+
|
11 |
+
celery = Celery()
|
12 |
+
celery.config_from_object(celery_config)
|
13 |
+
celery.conf.update(
|
14 |
+
# Other Celery configuration settings
|
15 |
+
CELERYD_LOG_LEVEL="DEBUG", # Set log level to DEBUG for the worker
|
16 |
+
)
|
17 |
+
|
18 |
+
|
19 |
+
@worker_process_init.connect
|
20 |
+
def worker_process_init_handler(**kwargs):
|
21 |
+
bot.start()
|
22 |
+
|
23 |
+
|
24 |
+
# Downloads list of links
|
25 |
+
# Script
|
26 |
+
|
27 |
+
|
28 |
+
def download_with_wget(link, download_dir):
|
29 |
+
subprocess.run(["wget", "-P", download_dir, link])
|
30 |
+
|
31 |
+
|
32 |
+
@celery.task
|
33 |
+
def copy_remotion_app(src: str, dest: str):
|
34 |
+
shutil.copytree(src, dest)
|
35 |
+
|
36 |
+
|
37 |
+
@celery.task
|
38 |
+
def install_dependencies(directory: str):
|
39 |
+
os.chdir(directory)
|
40 |
+
os.system("npm install")
|
41 |
+
|
42 |
+
|
43 |
+
@celery.task
|
44 |
+
def download_assets(links: List[str], temp_dir: str):
|
45 |
+
for i, link in enumerate(links):
|
46 |
+
download_dir = os.path.join(temp_dir, "public")
|
47 |
+
download_with_wget(link, download_dir)
|
48 |
+
|
49 |
+
|
50 |
+
@celery.task
|
51 |
+
def render_video(directory: str, output_directory: str):
|
52 |
+
os.chdir(directory)
|
53 |
+
os.system(f"npm run build --output {output_directory}")
|
54 |
+
|
55 |
+
|
56 |
+
@celery.task
|
57 |
+
def cleanup_temp_directory(
|
58 |
+
temp_dir: str, output_dir: str, chat_id: int = -1002069945904
|
59 |
+
):
|
60 |
+
try:
|
61 |
+
bot.send_video(chat_id, output_dir, caption="Your video caption")
|
62 |
+
finally:
|
63 |
+
# Cleanup: Remove the temporary directory
|
64 |
+
shutil.rmtree(temp_dir, ignore_errors=True)
|
65 |
+
|
66 |
+
|
67 |
+
@celery.task
|
68 |
+
def celery_task(video_request: EditorRequest):
|
69 |
+
remotion_app_dir = os.path.join("/srv", "Remotion-app")
|
70 |
+
project_id = str(uuid.uuid4())
|
71 |
+
temp_dir = f"/tmp/{project_id}"
|
72 |
+
output_dir = f"/tmp/{project_id}/{project_id}.mp4"
|
73 |
+
|
74 |
+
chain(
|
75 |
+
copy_remotion_app.s(remotion_app_dir, temp_dir),
|
76 |
+
install_dependencies.s(temp_dir),
|
77 |
+
download_assets.s(video_request.links, temp_dir)
|
78 |
+
if video_request.links
|
79 |
+
else None,
|
80 |
+
render_video.s(temp_dir, output_dir),
|
81 |
+
cleanup_temp_directory.s(temp_dir, output_dir),
|
82 |
+
).apply_async(
|
83 |
+
link_error=handle_error
|
84 |
+
) # Link the tasks and handle errors
|
85 |
+
|
86 |
+
|
87 |
+
def handle_error(task_id, err, *args, **kwargs):
|
88 |
+
print(f"Error in task {task_id}: {err}")
|
89 |
+
# You can add additional error handling logic here
|
App/__init__.py
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from pyrogram import Client
|
2 |
+
import os
|
3 |
+
|
4 |
+
TELEGRAM_SESSION = os.environ.get("TELEGRAM_SESSION")
|
5 |
+
|
6 |
+
|
7 |
+
bot: Client = Client(
|
8 |
+
"Editor", session_string=TELEGRAM_SESSION, workdir="/srv", workers=9
|
9 |
+
)
|
App/app.py
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from fastapi import FastAPI, BackgroundTasks
|
2 |
+
from .Editor.editorRoutes import videditor_router
|
3 |
+
from App import bot
|
4 |
+
|
5 |
+
app = FastAPI()
|
6 |
+
|
7 |
+
|
8 |
+
@app.on_event("startup")
|
9 |
+
async def startup_event():
|
10 |
+
await bot.start()
|
11 |
+
|
12 |
+
|
13 |
+
@app.get("/")
|
14 |
+
def read_root():
|
15 |
+
return {"Hello": "World"}
|
16 |
+
|
17 |
+
|
18 |
+
app.include_router(videditor_router)
|
App/celery_config.py
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from os import environ
|
2 |
+
import ssl
|
3 |
+
|
4 |
+
task_serializer = "json"
|
5 |
+
result_serializer = "json"
|
6 |
+
accept_content = ["json"]
|
7 |
+
timezone = "Europe/Oslo"
|
8 |
+
enable_utc = True
|
9 |
+
|
10 |
+
broker_url = f"rediss://default:8a715dd4651c8739b157d0ee0bb2d924@master.cache--j5zxzwppzvjs.addon.code.run:6379?ssl_cert_reqs=none"
|
11 |
+
result_backend = f"db+postgresql+psycopg2://postgres:[email protected]:5432/postgres"
|
12 |
+
|
13 |
+
# SSL/TLS and SNI configuration
|
14 |
+
broker_use_ssl = {
|
15 |
+
"ssl_cert_reqs": ssl.CERT_NONE,
|
16 |
+
"ssl_match_hostname": False,
|
17 |
+
"ssl_check_hostname": False,
|
18 |
+
"ssl_sni": "master.cache--j5zxzwppzvjs.addon.code.run",
|
19 |
+
}
|
Remotion-app/.gitattributes
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
28 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
29 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
30 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
31 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
32 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
33 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
Remotion-app/.gitignore
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
node_modules
|
2 |
+
dist
|
3 |
+
.DS_Store
|
4 |
+
.env
|
5 |
+
|
6 |
+
out
|
Remotion-app/.prettierrc
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"singleQuote": true,
|
3 |
+
"bracketSpacing": false,
|
4 |
+
"jsxBracketSameLine": false,
|
5 |
+
"useTabs": true,
|
6 |
+
"overrides": [
|
7 |
+
{
|
8 |
+
"files": ["*.yml"],
|
9 |
+
"options": {
|
10 |
+
"singleQuote": false
|
11 |
+
}
|
12 |
+
}
|
13 |
+
]
|
14 |
+
}
|
Remotion-app/Dockerfile
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Builder stage
|
2 |
+
FROM python:3.10.0 as builder
|
3 |
+
|
4 |
+
RUN useradd -ms /bin/bash admin
|
5 |
+
|
6 |
+
WORKDIR /srv
|
7 |
+
RUN chown -R admin:admin /srv
|
8 |
+
RUN chmod -R 755 /srv
|
9 |
+
|
10 |
+
# Install dependencies
|
11 |
+
RUN apt-get update && \
|
12 |
+
apt-get install -y libu2f-udev libvulkan1 mesa-vulkan-drivers wget
|
13 |
+
|
14 |
+
# Install Thorium Browser
|
15 |
+
RUN curl -LO https://github.com/Alex313031/thorium/releases/download/M117.0.5938.157/thorium-browser_117.0.5938.157_amd64.deb && \
|
16 |
+
dpkg -i thorium-browser_117.0.5938.157_amd64.deb
|
17 |
+
|
18 |
+
# Install Node.js and npm
|
19 |
+
RUN apt-get install -y nodejs npm
|
20 |
+
|
21 |
+
USER admin
|
22 |
+
|
23 |
+
# Copy the application code
|
24 |
+
COPY --chown=admin . /srv
|
25 |
+
|
26 |
+
# Install Python dependencies
|
27 |
+
COPY requirements.txt .
|
28 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
29 |
+
|
30 |
+
# Install JavaScript dependencies (if you have a package.json file)
|
31 |
+
COPY package*.json ./
|
32 |
+
RUN npm install
|
33 |
+
|
34 |
+
# Command to run the application
|
35 |
+
CMD uvicorn App.app:app --host 0.0.0.0 --port 7860 --workers 4 & celery -A App.Worker.celery worker -c 4 --loglevel=DEBUG
|
Remotion-app/README.md
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Remotion video
|
2 |
+
|
3 |
+
<p align="center">
|
4 |
+
<a href="https://github.com/remotion-dev/logo">
|
5 |
+
<picture>
|
6 |
+
<source media="(prefers-color-scheme: dark)" srcset="https://github.com/remotion-dev/logo/raw/main/animated-logo-banner-dark.gif">
|
7 |
+
<img alt="Animated Remotion Logo" src="https://github.com/remotion-dev/logo/raw/main/animated-logo-banner-light.gif">
|
8 |
+
</picture>
|
9 |
+
</a>
|
10 |
+
</p>
|
11 |
+
|
12 |
+
Welcome to your Remotion project!
|
13 |
+
|
14 |
+
## Commands
|
15 |
+
|
16 |
+
**Install Dependencies**
|
17 |
+
|
18 |
+
```console
|
19 |
+
npm i
|
20 |
+
```
|
21 |
+
|
22 |
+
**Start Preview**
|
23 |
+
|
24 |
+
```console
|
25 |
+
npm start
|
26 |
+
```
|
27 |
+
|
28 |
+
**Render video**
|
29 |
+
|
30 |
+
```console
|
31 |
+
npm run build
|
32 |
+
```
|
33 |
+
|
34 |
+
**Upgrade Remotion**
|
35 |
+
|
36 |
+
```console
|
37 |
+
npm run upgrade
|
38 |
+
```
|
39 |
+
|
40 |
+
## Docs
|
41 |
+
|
42 |
+
Get started with Remotion by reading the [fundamentals page](https://www.remotion.dev/docs/the-fundamentals).
|
43 |
+
|
44 |
+
## Help
|
45 |
+
|
46 |
+
We provide help on our [Discord server](https://discord.gg/6VzzNDwUwV).
|
47 |
+
|
48 |
+
## Issues
|
49 |
+
|
50 |
+
Found an issue with Remotion? [File an issue here](https://github.com/JonnyBurger/remotion/issues/new).
|
51 |
+
|
52 |
+
## License
|
53 |
+
|
54 |
+
Note that for some entities a company license is needed. [Read the terms here](https://github.com/JonnyBurger/remotion/blob/main/LICENSE.md).
|
Remotion-app/package.json
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "short",
|
3 |
+
"version": "1.0.0",
|
4 |
+
"description": "My Remotion video",
|
5 |
+
"scripts": {
|
6 |
+
"start": "remotion studio",
|
7 |
+
"build": "remotion render HelloWorld out/video.mp4",
|
8 |
+
"upgrade": "remotion upgrade",
|
9 |
+
"test": "eslint src --ext ts,tsx,js,jsx"
|
10 |
+
},
|
11 |
+
"repository": {},
|
12 |
+
"license": "UNLICENSED",
|
13 |
+
"dependencies": {
|
14 |
+
"@remotion/cli": "4.0.69",
|
15 |
+
"@remotion/google-fonts": "4.0.69",
|
16 |
+
"@remotion/preload": "4.0.69",
|
17 |
+
"@remotion/transitions": "4.0.69",
|
18 |
+
"@remotion/zod-types": "4.0.69",
|
19 |
+
"react": "^18.0.0",
|
20 |
+
"react-dom": "^18.0.0",
|
21 |
+
"remotion": "4.0.69",
|
22 |
+
"zod": "^3.21.4"
|
23 |
+
},
|
24 |
+
"devDependencies": {
|
25 |
+
"prettier": "^2.8.8"
|
26 |
+
},
|
27 |
+
"packageManager": "[email protected]"
|
28 |
+
}
|
Remotion-app/remotion.config.js
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// All configuration options: https://remotion.dev/docs/config
|
2 |
+
// Each option also is available as a CLI flag: https://remotion.dev/docs/cli
|
3 |
+
|
4 |
+
// Note: When using the Node.JS APIs, the config file doesn't apply. Instead, pass options directly to the APIs
|
5 |
+
|
6 |
+
import {Config} from '@remotion/cli/config';
|
7 |
+
|
8 |
+
Config.setVideoImageFormat('jpeg');
|
9 |
+
Config.setFrameRange([0, (54 * 30) / 5]);
|
Remotion-app/src/HelloWorld/Subtitle.jsx
ADDED
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React, {createElement} from 'react';
|
2 |
+
import {useVideoConfig} from 'remotion';
|
3 |
+
import {loadFont as loadMain} from '@remotion/google-fonts/Bungee';
|
4 |
+
import transcriptData from './Transcription.json';
|
5 |
+
const {fontFamily: fontFamily2} = loadMain();
|
6 |
+
import {TransitionSeries} from '@remotion/transitions';
|
7 |
+
|
8 |
+
const codeStyle = (index) => {
|
9 |
+
return {
|
10 |
+
color: 'white',
|
11 |
+
position: 'absolute',
|
12 |
+
backgroundColor: 'red',
|
13 |
+
top: '50%',
|
14 |
+
width: '100%',
|
15 |
+
transform: 'translate(-50%, -50%)',
|
16 |
+
left: '50%',
|
17 |
+
};
|
18 |
+
};
|
19 |
+
|
20 |
+
const subtitle = {
|
21 |
+
fontFamily: fontFamily2,
|
22 |
+
fontSize: 120,
|
23 |
+
textAlign: 'center',
|
24 |
+
display: 'relative',
|
25 |
+
bottom: 140,
|
26 |
+
width: '100%',
|
27 |
+
};
|
28 |
+
|
29 |
+
export const Subtitle = () => {
|
30 |
+
const {fps} = useVideoConfig();
|
31 |
+
|
32 |
+
return (
|
33 |
+
<div style={subtitle}>
|
34 |
+
<TransitionSeries>
|
35 |
+
{transcriptData.map((entry, index) => {
|
36 |
+
return (
|
37 |
+
<TransitionSeries.Sequence
|
38 |
+
from={entry.start * fps}
|
39 |
+
durationInFrames={fps * (entry.end - entry.start)}
|
40 |
+
>
|
41 |
+
<Letter index={index} color="#0b84f3">
|
42 |
+
{entry.text}
|
43 |
+
</Letter>
|
44 |
+
</TransitionSeries.Sequence>
|
45 |
+
);
|
46 |
+
})}
|
47 |
+
</TransitionSeries>
|
48 |
+
</div>
|
49 |
+
);
|
50 |
+
};
|
51 |
+
|
52 |
+
export function Letter({children, color, index}) {
|
53 |
+
const x = codeStyle(index);
|
54 |
+
return createElement(
|
55 |
+
'div',
|
56 |
+
{className: 'greeting', style: {...x, color: 'white'}},
|
57 |
+
children
|
58 |
+
);
|
59 |
+
}
|
Remotion-app/src/HelloWorld/Transcription.json
ADDED
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
[
|
2 |
+
{ "end": 0.28, "text": " Jawan", "start": 0 },
|
3 |
+
{ "end": 0.62, "text": " is", "start": 0.28 },
|
4 |
+
{ "end": 0.78, "text": " a", "start": 0.62 },
|
5 |
+
{ "end": 1.8, "text": " 2023", "start": 0.78 },
|
6 |
+
{ "end": 2.6, "text": " action", "start": 1.8 },
|
7 |
+
{ "end": 3, "text": " thriller", "start": 2.6 },
|
8 |
+
{ "end": 3.42, "text": " movie", "start": 3 },
|
9 |
+
{ "end": 3.92, "text": " starring", "start": 3.42 },
|
10 |
+
{ "end": 4.26, "text": " Shah", "start": 3.92 },
|
11 |
+
{ "end": 4.82, "text": " Rakhkan,", "start": 4.26 },
|
12 |
+
{ "end": 5.48, "text": " Mayan", "start": 5.28 },
|
13 |
+
{ "end": 5.8, "text": " Thara", "start": 5.48 },
|
14 |
+
{ "end": 6.32, "text": " and", "start": 5.8 },
|
15 |
+
{ "end": 6.7, "text": " Vijay", "start": 6.32 },
|
16 |
+
{ "end": 7.18, "text": " Sethu", "start": 6.7 },
|
17 |
+
{ "end": 7.54, "text": " Pathy.", "start": 7.18 },
|
18 |
+
{ "end": 7.94, "text": " The", "start": 7.88 },
|
19 |
+
{ "end": 8.24, "text": " movie", "start": 7.94 },
|
20 |
+
{ "end": 8.7, "text": " follows", "start": 8.24 },
|
21 |
+
{ "end": 8.98, "text": " the", "start": 8.7 },
|
22 |
+
{ "end": 9.46, "text": " emotional", "start": 8.98 },
|
23 |
+
{ "end": 9.82, "text": " journey", "start": 9.46 },
|
24 |
+
{ "end": 10.08, "text": " of", "start": 9.82 },
|
25 |
+
{ "end": 10.2, "text": " a", "start": 10.08 },
|
26 |
+
{ "end": 10.52, "text": " prison", "start": 10.2 },
|
27 |
+
{ "end": 11.1, "text": " warden", "start": 10.52 },
|
28 |
+
{ "end": 11.42, "text": " who", "start": 11.1 },
|
29 |
+
{ "end": 12.04, "text": " recruits", "start": 11.42 },
|
30 |
+
{ "end": 12.4, "text": " inmates", "start": 12.04 },
|
31 |
+
{ "end": 12.7, "text": " to", "start": 12.4 },
|
32 |
+
{ "end": 12.98, "text": " commit", "start": 12.7 },
|
33 |
+
{ "end": 13.54, "text": " outrageous", "start": 12.98 },
|
34 |
+
{ "end": 14.06, "text": " crimes", "start": 13.54 },
|
35 |
+
{ "end": 14.36, "text": " that", "start": 14.06 },
|
36 |
+
{ "end": 14.58, "text": " shed", "start": 14.36 },
|
37 |
+
{ "end": 14.9, "text": " light", "start": 14.58 },
|
38 |
+
{ "end": 15.14, "text": " on", "start": 14.9 },
|
39 |
+
{ "end": 15.62, "text": " corruption", "start": 15.14 },
|
40 |
+
{ "end": 15.96, "text": " and", "start": 15.62 },
|
41 |
+
{ "end": 16.5, "text": " injustice", "start": 15.96 },
|
42 |
+
{ "end": 16.78, "text": " in", "start": 16.5 },
|
43 |
+
{ "end": 16.9, "text": " the", "start": 16.78 },
|
44 |
+
{ "end": 17.5, "text": " society.", "start": 16.9 },
|
45 |
+
{ "end": 17.9, "text": " He", "start": 17.8 },
|
46 |
+
{ "end": 18.04, "text": " is", "start": 17.9 },
|
47 |
+
{ "end": 18.34, "text": " driven", "start": 18.04 },
|
48 |
+
{ "end": 18.62, "text": " by", "start": 18.34 },
|
49 |
+
{ "end": 18.76, "text": " a", "start": 18.62 },
|
50 |
+
{ "end": 19.2, "text": " personal", "start": 18.76 },
|
51 |
+
{ "end": 19.74, "text": " vendetta", "start": 19.2 },
|
52 |
+
{ "end": 20.06, "text": " and", "start": 19.74 },
|
53 |
+
{ "end": 20.2, "text": " a", "start": 20.06 },
|
54 |
+
{ "end": 20.56, "text": " promise", "start": 20.2 },
|
55 |
+
{ "end": 20.82, "text": " he", "start": 20.56 },
|
56 |
+
{ "end": 21.04, "text": " made", "start": 20.82 },
|
57 |
+
{ "end": 21.38, "text": " years", "start": 21.04 },
|
58 |
+
{ "end": 21.68, "text": " ago", "start": 21.38 },
|
59 |
+
{ "end": 21.82, "text": " to", "start": 21.68 },
|
60 |
+
{ "end": 22.16, "text": " someone", "start": 21.82 },
|
61 |
+
{ "end": 22.42, "text": " he", "start": 22.16 },
|
62 |
+
{ "end": 22.76, "text": " loved.", "start": 22.42 },
|
63 |
+
{ "end": 23.12, "text": " His", "start": 23 },
|
64 |
+
{ "end": 23.4, "text": " quest", "start": 23.12 },
|
65 |
+
{ "end": 23.7, "text": " for", "start": 23.4 },
|
66 |
+
{ "end": 24.02, "text": " revenge", "start": 23.7 },
|
67 |
+
{ "end": 24.44, "text": " leads", "start": 24.02 },
|
68 |
+
{ "end": 24.7, "text": " him", "start": 24.44 },
|
69 |
+
{ "end": 24.92, "text": " to", "start": 24.7 },
|
70 |
+
{ "end": 25.1, "text": " an", "start": 24.92 },
|
71 |
+
{ "end": 25.64, "text": " unexpected", "start": 25.1 },
|
72 |
+
{ "end": 26.42, "text": " reunion", "start": 25.64 },
|
73 |
+
{ "end": 26.7, "text": " with", "start": 26.42 },
|
74 |
+
{ "end": 26.9, "text": " his", "start": 26.7 },
|
75 |
+
{ "end": 27.24, "text": " past", "start": 26.9 },
|
76 |
+
{ "end": 27.76, "text": " and", "start": 27.24 },
|
77 |
+
{ "end": 27.88, "text": " a", "start": 27.76 },
|
78 |
+
{ "end": 28.26, "text": " shocking", "start": 27.88 },
|
79 |
+
{ "end": 28.84, "text": " revelation", "start": 28.26 },
|
80 |
+
{ "end": 29.24, "text": " that", "start": 28.84 },
|
81 |
+
{ "end": 29.74, "text": " changes", "start": 29.24 },
|
82 |
+
{ "end": 30.02, "text": " his", "start": 29.74 },
|
83 |
+
{ "end": 30.3, "text": " life", "start": 30.02 },
|
84 |
+
{ "end": 30.78, "text": " forever.", "start": 30.3 },
|
85 |
+
{ "end": 31.14, "text": " The", "start": 31.12 },
|
86 |
+
{ "end": 31.46, "text": " movie", "start": 31.14 },
|
87 |
+
{ "end": 31.7, "text": " is", "start": 31.46 },
|
88 |
+
{ "end": 31.8, "text": " a", "start": 31.7 },
|
89 |
+
{ "end": 32.18, "text": " gripping", "start": 31.8 },
|
90 |
+
{ "end": 32.48, "text": " tale", "start": 32.18 },
|
91 |
+
{ "end": 32.7, "text": " of", "start": 32.48 },
|
92 |
+
{ "end": 33.14, "text": " betrayal,", "start": 32.7 },
|
93 |
+
{ "end": 34.06, "text": " redemption,", "start": 33.64 },
|
94 |
+
{ "end": 34.6, "text": " and", "start": 34.5 },
|
95 |
+
{ "end": 35.04, "text": " justice,", "start": 34.6 },
|
96 |
+
{ "end": 35.54, "text": " with", "start": 35.46 },
|
97 |
+
{ "end": 35.88, "text": " stunning", "start": 35.54 },
|
98 |
+
{ "end": 36.36, "text": " action", "start": 35.88 },
|
99 |
+
{ "end": 37.08, "text": " sequences", "start": 36.36 },
|
100 |
+
{ "end": 37.42, "text": " and", "start": 37.08 },
|
101 |
+
{ "end": 37.56, "text": " a", "start": 37.42 },
|
102 |
+
{ "end": 38, "text": " powerful", "start": 37.56 },
|
103 |
+
{ "end": 38.7, "text": " performance", "start": 38 },
|
104 |
+
{ "end": 39.02, "text": " by", "start": 38.7 },
|
105 |
+
{ "end": 39.32, "text": " Shah", "start": 39.02 }]
|
Remotion-app/src/HelloWorld/constants.js
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Change any of these to update your video live.
|
2 |
+
|
3 |
+
export const COLOR_1 = '#86A8E7';
|
4 |
+
export const COLOR_2 = '#91EAE4';
|
5 |
+
|
6 |
+
export const FONT_FAMILY = 'SF Pro Text, Helvetica, Arial, sans-serif';
|
Remotion-app/src/HelloWorld/index.jsx
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import {Subtitle} from './Subtitle';
|
2 |
+
import {
|
3 |
+
spring,
|
4 |
+
AbsoluteFill,
|
5 |
+
useCurrentFrame,
|
6 |
+
useVideoConfig,
|
7 |
+
Audio,
|
8 |
+
staticFile,
|
9 |
+
Video,
|
10 |
+
} from 'remotion';
|
11 |
+
import {preloadAudio, resolveRedirect} from '@remotion/preload';
|
12 |
+
|
13 |
+
export const HelloWorld = ({titleText, titleColor}) => {
|
14 |
+
const frame = useCurrentFrame();
|
15 |
+
const {fps} = useVideoConfig();
|
16 |
+
const scale = spring({
|
17 |
+
fps,
|
18 |
+
frame,
|
19 |
+
config: {
|
20 |
+
damping: 200,
|
21 |
+
mass: 0.5,
|
22 |
+
stiffness: 200,
|
23 |
+
overshootClamping: false,
|
24 |
+
restDisplacementThreshold: 0.01,
|
25 |
+
restSpeedThreshold: 0.01,
|
26 |
+
},
|
27 |
+
});
|
28 |
+
|
29 |
+
return (
|
30 |
+
<AbsoluteFill style={{position: 'relative', backgroundColor: 'black'}}>
|
31 |
+
<Audio
|
32 |
+
volume={0.15}
|
33 |
+
src={staticFile('background.mp3')}
|
34 |
+
// src={'https://yakova-streamer.hf.space/download/20707'}
|
35 |
+
/>
|
36 |
+
|
37 |
+
{/* <Video
|
38 |
+
src={
|
39 |
+
'https://player.vimeo.com/external/514185553.hd.mp4?s=33cb766901019185385a757eab89a9fd0d50d0c0&profile_id=172&oauth2_token_id=57447761'
|
40 |
+
}
|
41 |
+
/> */}
|
42 |
+
{/* <Audio src={'https://yakova-streamer.hf.space/download/20711'} /> */}
|
43 |
+
{/* <img src={''} style={{transform: `scale(${scale})`}} /> */}
|
44 |
+
|
45 |
+
<Subtitle />
|
46 |
+
</AbsoluteFill>
|
47 |
+
);
|
48 |
+
};
|
Remotion-app/src/Root.jsx
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import {Composition} from 'remotion';
|
2 |
+
import {HelloWorld} from './HelloWorld';
|
3 |
+
|
4 |
+
export const RemotionRoot = () => {
|
5 |
+
return (
|
6 |
+
<>
|
7 |
+
<Composition
|
8 |
+
id="HelloWorld"
|
9 |
+
component={HelloWorld}
|
10 |
+
durationInFrames={15000}
|
11 |
+
fps={30}
|
12 |
+
height={1920}
|
13 |
+
width={1080}
|
14 |
+
defaultProps={{
|
15 |
+
titleText: 'Welcome to Remotion',
|
16 |
+
titleColor: 'black',
|
17 |
+
}}
|
18 |
+
/>
|
19 |
+
</>
|
20 |
+
);
|
21 |
+
};
|
Remotion-app/src/index.js
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// This is your entry file! Refer to it when you render:
|
2 |
+
// npx remotion render <entry-file> HelloWorld out/video.mp4
|
3 |
+
|
4 |
+
import {registerRoot} from 'remotion';
|
5 |
+
import {RemotionRoot} from './Root';
|
6 |
+
|
7 |
+
registerRoot(RemotionRoot);
|
requirements.txt
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
asyncpg==0.27.0
|
2 |
+
click==8.1.3
|
3 |
+
databases==0.7.0
|
4 |
+
fastapi==0.92.0
|
5 |
+
greenlet==2.0.2
|
6 |
+
itsdangerous==2.1.2
|
7 |
+
starlette==0.25.0
|
8 |
+
typesystem==0.3.1
|
9 |
+
Werkzeug==2.2.2
|
10 |
+
pydantic[email]
|
11 |
+
uvicorn==0.21.1
|
12 |
+
gunicorn
|
13 |
+
ujson
|
14 |
+
psutil
|
15 |
+
celery
|
16 |
+
python-multipart
|
17 |
+
git+https://github.com/redis/redis-py.git
|
18 |
+
TgCrypto
|
19 |
+
pyrogram
|
sample.py
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
|