From c015c553ee5f1040599368fcd064e8300bf2fb78 Mon Sep 17 00:00:00 2001 From: Igor Samokhovets Date: Fri, 28 Aug 2026 17:38:13 +0200 Subject: [PATCH 01/13] Docs: Redeploy brand changes on Vercel --- bun.lock | 1 + packages/docs/package.json | 1 + 2 files changed, 2 insertions(+) diff --git a/bun.lock b/bun.lock index d8d4c36c6d6..05230578710 100644 --- a/bun.lock +++ b/bun.lock @@ -527,6 +527,7 @@ "@remotion/animated-emoji": "workspace:*", "@remotion/animation-utils": "workspace:*", "@remotion/babel-loader": "workspace:*", + "@remotion/brand": "workspace:*", "@remotion/browser-studio": "workspace:*", "@remotion/bundler": "workspace:*", "@remotion/captions": "workspace:*", diff --git a/packages/docs/package.json b/packages/docs/package.json index 6e899a24c9d..a58518f93a4 100644 --- a/packages/docs/package.json +++ b/packages/docs/package.json @@ -44,6 +44,7 @@ "@remotion/animated-emoji": "workspace:*", "@remotion/animation-utils": "workspace:*", "@remotion/babel-loader": "workspace:*", + "@remotion/brand": "workspace:*", "@remotion/browser-studio": "workspace:*", "@remotion/bundler": "workspace:*", "@remotion/captions": "workspace:*", From 832315a287154796d952a1068bd5bfaf06966251 Mon Sep 17 00:00:00 2001 From: hiromiishino Date: Sun, 30 Aug 2026 00:03:52 +0900 Subject: [PATCH 02/13] docs: add RenderComp Free (50 MIT templates) to the templates list --- packages/docs/docs/resources.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/docs/docs/resources.mdx b/packages/docs/docs/resources.mdx index 568d936975b..410609e2bc9 100644 --- a/packages/docs/docs/resources.mdx +++ b/packages/docs/docs/resources.mdx @@ -24,6 +24,7 @@ This list tries to compile all templates, libraries, building blocks and example - [Free Remotion Components](https://www.clippkit.com/) - [Remotion Bits - Ready-made blocks to use for you and your agents](https://remotion-bits.dev/) - [SwiftClip - 30 production-ready Remotion templates](https://swift-clip.vercel.app/) ([Source code](https://github.com/zz41354899/SwiftClip)) +- [RenderComp Free - 50 MIT-licensed Remotion templates](https://rendercomp.com/free) ([Source code](https://github.com/RenderComp/free-remotion-templates)) - Docker Build & Render ([Source code](https://github.com/scotthavird/remotion-docker-template)) - [Template for deploying Remotion on Railway](https://railway.com/deploy/remotion-on-rails) ([Blog](https://medium.com/@viveknathani/remotion-on-rails-0852acc9595e)) - [Multiple shared Remotion components in a Monorepo template](https://github.com/Takamasa045/remotion-studio-monorepo) From 7b4dcde6162fd1f4aa40d57dd699cdb20680d0c5 Mon Sep 17 00:00:00 2001 From: JonnyBurger Date: Sun, 30 Aug 2026 22:02:47 +0200 Subject: [PATCH 03/13] Internal: Consolidate package publish checks --- .../src/monorepo/no-dev-files.test.ts | 33 ++++++++++++++----- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/packages/it-tests/src/monorepo/no-dev-files.test.ts b/packages/it-tests/src/monorepo/no-dev-files.test.ts index 8c4b120a5e4..71aa111dd88 100644 --- a/packages/it-tests/src/monorepo/no-dev-files.test.ts +++ b/packages/it-tests/src/monorepo/no-dev-files.test.ts @@ -89,11 +89,28 @@ const assertNoDevFilesPublished = async (pkgPath: string) => { } }; -for (const pkg of packages) { - test.concurrent( - 'should not publish any dev files for @remotion/' + pkg.pkg, - async () => { - await assertNoDevFilesPublished(pkg.path); - }, - ); -} +test( + 'should not publish any dev files', + async () => { + const results = await Promise.allSettled( + packages.map((pkg) => assertNoDevFilesPublished(pkg.path)), + ); + const errors = results.flatMap((result, index) => { + if (result.status === 'fulfilled') { + return []; + } + + return [ + `@remotion/${packages[index].pkg}: ${ + result.reason instanceof Error + ? result.reason.message + : String(result.reason) + }`, + ]; + }); + if (errors.length > 0) { + throw new Error(errors.join('\n')); + } + }, + {timeout: 40000}, +); From 97fc51f210f61419e32a2b0b9a4e0c4d587077cd Mon Sep 17 00:00:00 2001 From: Jonny Burger Date: Mon, 31 Aug 2026 10:31:18 +0200 Subject: [PATCH 04/13] `@remotion/studio`: Hide FPS counter on narrow viewports --- packages/studio/src/components/PreviewToolbar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/studio/src/components/PreviewToolbar.tsx b/packages/studio/src/components/PreviewToolbar.tsx index fdddc394960..b190b856b42 100644 --- a/packages/studio/src/components/PreviewToolbar.tsx +++ b/packages/studio/src/components/PreviewToolbar.tsx @@ -227,7 +227,7 @@ export const PreviewToolbar: React.FC<{
- + {isMobileLayout ? null : } Date: Mon, 31 Aug 2026 10:35:50 +0200 Subject: [PATCH 05/13] v4.0.519 --- bun.lock | 215 +++---- packages/animated-emoji/package.json | 2 +- packages/animation-utils/package.json | 2 +- packages/astro-example/package.json | 2 +- packages/babel-loader/package.json | 2 +- packages/brand/package.json | 2 +- .../brand/src/bottom-up-letters.element.tsx | 235 +++++++ .../brand/src/line-by-line-slide.element.tsx | 267 ++++++++ .../brand/src/per-word-crossfade.element.tsx | 288 +++++++++ packages/brand/src/word-stream.element.tsx | 338 +++++++++++ packages/browser-studio/package.json | 2 +- packages/bugs/package.json | 2 +- packages/bundler/package.json | 2 +- .../canvas-capture-extension/package.json | 2 +- packages/canvas/package.json | 2 +- packages/captions/package.json | 2 +- .../.claude-plugin/plugin.json | 2 +- packages/claude-code-plugin/package.json | 2 +- packages/cli/package.json | 2 +- packages/cloudrun/container/package.json | 2 +- packages/cloudrun/package.json | 2 +- .../codex-plugin/.codex-plugin/plugin.json | 2 +- packages/codex-plugin/package.json | 2 +- packages/codex-plugin/plugin.json | 2 +- packages/compositor-darwin-arm64/package.json | 2 +- packages/compositor-darwin-x64/package.json | 2 +- .../compositor-linux-arm64-gnu/package.json | 2 +- .../compositor-linux-arm64-musl/package.json | 2 +- .../compositor-linux-x64-gnu/package.json | 2 +- .../compositor-linux-x64-musl/package.json | 2 +- .../compositor-win32-x64-msvc/package.json | 2 +- packages/compositor/package.json | 2 +- packages/convert/package.json | 2 +- packages/core/package.json | 2 +- packages/core/src/version.ts | 2 +- packages/create-video/package.json | 2 +- packages/design/package.json | 2 +- packages/discord-poster/package.json | 2 +- packages/docs/package.json | 2 +- packages/docusaurus-plugin/package.json | 2 +- packages/effects/package.json | 2 +- packages/elevenlabs/package.json | 2 +- packages/enable-scss/package.json | 2 +- packages/eslint-config-flat/package.json | 2 +- packages/eslint-config-internal/package.json | 2 +- packages/eslint-config/package.json | 2 +- packages/eslint-plugin/package.json | 2 +- packages/example-videos/package.json | 2 +- packages/example-without-zod/package.json | 2 +- packages/example/package.json | 2 +- .../src/MovingPillCaptionsComposition.tsx | 26 + .../example/src/mirrored-spectrum.element.tsx | 176 ++++++ .../src/moving-pill-captions.element.tsx | 573 ++++++++++++++++++ packages/example/src/oscilloscope.element.tsx | 214 +++++++ packages/fonts/package.json | 2 +- packages/gif/package.json | 2 +- packages/google-fonts/package.json | 2 +- .../scripts/incompatible-fonts.ts | 108 ++-- packages/gsap/package.json | 2 +- packages/install-whisper-cpp/package.json | 2 +- packages/it-tests/package.json | 2 +- packages/jonnys-videos/package.json | 2 +- .../kimi-code-plugin/.kimi-plugin/plugin.json | 2 +- packages/kimi-code-plugin/package.json | 2 +- packages/lambda-client/package.json | 2 +- packages/lambda-go-example/package.json | 2 +- packages/lambda-go/package.json | 2 +- packages/lambda-go/version.go | 2 +- packages/lambda-php-example/composer.json | 2 +- packages/lambda-php/composer.json | 2 +- packages/lambda-php/composer.lock | 2 +- packages/lambda-php/package.json | 2 +- packages/lambda-php/src/Semantic.php | 2 +- packages/lambda-python/package.json | 2 +- .../lambda-python/remotion_lambda/version.py | 2 +- .../lib/remotion_lambda/version.rb | 2 +- packages/lambda-ruby/package.json | 2 +- packages/lambda-ruby/remotion_lambda.gemspec | 2 +- packages/lambda/package.json | 2 +- packages/layout-utils/package.json | 2 +- packages/licensing/package.json | 2 +- packages/light-leaks/package.json | 2 +- packages/lottie/package.json | 2 +- packages/mac-cursors/package.json | 2 +- packages/maptiler/package.json | 2 +- packages/mcp/package.json | 2 +- packages/media-parser/package.json | 2 +- packages/media-parser/src/version.ts | 2 +- packages/media-utils/package.json | 2 +- packages/media/package.json | 2 +- packages/motion-blur/package.json | 2 +- packages/noise/package.json | 2 +- packages/openai-whisper/package.json | 2 +- packages/paths/package.json | 2 +- packages/player-a11y/package.json | 2 +- packages/player-example/package.json | 2 +- packages/player/package.json | 2 +- packages/preload/package.json | 2 +- packages/promo-pages/package.json | 2 +- packages/react18-tests/package.json | 2 +- packages/remotion-media/package.json | 2 +- packages/renderer/package.json | 2 +- packages/rive/package.json | 2 +- packages/rough-notation/package.json | 2 +- packages/rounded-text-box/package.json | 2 +- packages/serverless-client/package.json | 2 +- packages/serverless/package.json | 2 +- packages/sfx/package.json | 2 +- packages/shapes/package.json | 2 +- packages/skia/package.json | 2 +- packages/skills-evals/package.json | 2 +- packages/skills/package.json | 2 +- .../skills/remotion-best-practices/SKILL.md | 2 +- .../skills/skills/remotion-captions/SKILL.md | 2 +- .../skills/skills/remotion-create/SKILL.md | 2 +- packages/skills/skills/remotion-docs/SKILL.md | 2 +- .../skills/remotion-interactivity/SKILL.md | 2 +- packages/skills/skills/remotion-maps/SKILL.md | 2 +- .../skills/skills/remotion-markup/SKILL.md | 2 +- .../skills/remotion-multimedia/SKILL.md | 2 +- .../skills/skills/remotion-render/SKILL.md | 2 +- packages/skills/skills/remotion-saas/SKILL.md | 2 +- .../skills/skills/remotion-studio/SKILL.md | 2 +- .../skills/skills/remotion-upgrade/SKILL.md | 2 +- packages/starburst/package.json | 2 +- packages/streaming/package.json | 2 +- packages/studio-codemods/package.json | 2 +- packages/studio-protocol/package.json | 2 +- packages/studio-server/package.json | 2 +- packages/studio-shared/package.json | 2 +- packages/studio/package.json | 2 +- packages/svg-3d-engine/package.json | 2 +- packages/tailwind-v4/package.json | 2 +- packages/tailwind/package.json | 2 +- packages/test-utils/package.json | 2 +- packages/three/package.json | 2 +- packages/timeline-utils/package.json | 2 +- packages/transitions/package.json | 2 +- packages/vercel/package.json | 2 +- packages/web-renderer/package.json | 2 +- packages/webcodecs/package.json | 2 +- packages/whisper-web/package.json | 2 +- packages/whisper-webgpu/package.json | 2 +- packages/zod-types-v3/package.json | 2 +- packages/zod-types/package.json | 2 +- 145 files changed, 2414 insertions(+), 296 deletions(-) create mode 100644 packages/brand/src/bottom-up-letters.element.tsx create mode 100644 packages/brand/src/line-by-line-slide.element.tsx create mode 100644 packages/brand/src/per-word-crossfade.element.tsx create mode 100644 packages/brand/src/word-stream.element.tsx create mode 100644 packages/example/src/MovingPillCaptionsComposition.tsx create mode 100644 packages/example/src/mirrored-spectrum.element.tsx create mode 100644 packages/example/src/moving-pill-captions.element.tsx create mode 100644 packages/example/src/oscilloscope.element.tsx diff --git a/bun.lock b/bun.lock index 05230578710..18e175438ff 100644 --- a/bun.lock +++ b/bun.lock @@ -24,7 +24,7 @@ }, "packages/animated-emoji": { "name": "@remotion/animated-emoji", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "remotion": "workspace:*", }, @@ -36,7 +36,7 @@ }, "packages/animation-utils": { "name": "@remotion/animation-utils", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "remotion": "workspace:*", }, @@ -52,7 +52,7 @@ }, "packages/astro-example": { "name": "@remotion/astro-example", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@astrojs/react": "4.0.0", "@remotion/gif": "workspace:*", @@ -71,7 +71,7 @@ }, "packages/babel-loader": { "name": "@remotion/babel-loader", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@babel/core": "7.29.6", "@babel/plugin-proposal-class-properties": "7.14.5", @@ -95,7 +95,7 @@ }, "packages/brand": { "name": "@remotion/brand", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@mediabunny/prores": "catalog:", }, @@ -137,7 +137,7 @@ }, "packages/browser-studio": { "name": "@remotion/browser-studio", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/studio-codemods": "workspace:*", "@remotion/studio-protocol": "workspace:*", @@ -164,7 +164,7 @@ }, "packages/bundler": { "name": "@remotion/bundler", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/media-parser": "workspace:*", "@remotion/studio": "workspace:*", @@ -193,7 +193,7 @@ }, "packages/canvas": { "name": "@remotion/canvas", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/player": "workspace:*", "remotion": "workspace:*", @@ -214,8 +214,9 @@ }, "packages/canvas-capture-extension": { "name": "@remotion/canvas-capture-extension", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { + "@remotion/design": "workspace:*", "mediabunny": "catalog:", "react": "catalog:", "react-dom": "catalog:", @@ -235,7 +236,7 @@ }, "packages/captions": { "name": "@remotion/captions", - "version": "4.0.518", + "version": "4.0.519", "devDependencies": { "@remotion/eslint-config-internal": "workspace:*", "@typescript/native-preview": "catalog:", @@ -244,7 +245,7 @@ }, "packages/claude-code-plugin": { "name": "@remotion/claude-code-plugin", - "version": "4.0.518", + "version": "4.0.519", "devDependencies": { "@remotion/eslint-config-internal": "workspace:*", "@typescript/native-preview": "catalog:", @@ -253,7 +254,7 @@ }, "packages/cli": { "name": "@remotion/cli", - "version": "4.0.518", + "version": "4.0.519", "bin": { "remotion": "remotion-cli.js", "remotionb": "remotionb-cli.js", @@ -298,7 +299,7 @@ }, "packages/cloudrun": { "name": "@remotion/cloudrun", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@google-cloud/artifact-registry": "3.5.1", "@google-cloud/functions-framework": "3.4.6", @@ -324,7 +325,7 @@ }, "packages/codex-plugin": { "name": "@remotion/codex-plugin", - "version": "4.0.518", + "version": "4.0.519", "devDependencies": { "@remotion/eslint-config-internal": "workspace:*", "@typescript/native-preview": "catalog:", @@ -333,39 +334,39 @@ }, "packages/compositor": { "name": "@remotion/compositor", - "version": "4.0.518", + "version": "4.0.519", }, "packages/compositor-darwin-arm64": { "name": "@remotion/compositor-darwin-arm64", - "version": "4.0.518", + "version": "4.0.519", }, "packages/compositor-darwin-x64": { "name": "@remotion/compositor-darwin-x64", - "version": "4.0.518", + "version": "4.0.519", }, "packages/compositor-linux-arm64-gnu": { "name": "@remotion/compositor-linux-arm64-gnu", - "version": "4.0.518", + "version": "4.0.519", }, "packages/compositor-linux-arm64-musl": { "name": "@remotion/compositor-linux-arm64-musl", - "version": "4.0.518", + "version": "4.0.519", }, "packages/compositor-linux-x64-gnu": { "name": "@remotion/compositor-linux-x64-gnu", - "version": "4.0.518", + "version": "4.0.519", }, "packages/compositor-linux-x64-musl": { "name": "@remotion/compositor-linux-x64-musl", - "version": "4.0.518", + "version": "4.0.519", }, "packages/compositor-win32-x64-msvc": { "name": "@remotion/compositor-win32-x64-msvc", - "version": "4.0.518", + "version": "4.0.519", }, "packages/convert": { "name": "@remotion/convert", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@mediabunny/aac-encoder": "catalog:", "@mediabunny/ac3": "catalog:", @@ -428,7 +429,7 @@ }, "packages/core": { "name": "remotion", - "version": "4.0.518", + "version": "4.0.519", "devDependencies": { "@happy-dom/global-registrator": "14.5.1", "@remotion/eslint-config-internal": "workspace:*", @@ -450,7 +451,7 @@ }, "packages/create-video": { "name": "create-video", - "version": "4.0.518", + "version": "4.0.519", "bin": { "create-video": "bin.js", }, @@ -472,7 +473,7 @@ }, "packages/design": { "name": "@remotion/design", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@radix-ui/react-select": "2.1.1", "@radix-ui/react-slot": "1.2.4", @@ -502,11 +503,11 @@ }, "packages/discord-poster": { "name": "@remotion/discord-poster", - "version": "4.0.518", + "version": "4.0.519", }, "packages/docs": { "name": "docs", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@aws-sdk/s3-request-presigner": "catalog:", "@babel/parser": "7.24.1", @@ -641,7 +642,7 @@ }, "packages/docusaurus-plugin": { "name": "@remotion/docusaurus-plugin", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@docusaurus/types": "3.6.0", "@shikijs/twoslash": "3.22.0", @@ -660,7 +661,7 @@ }, "packages/effects": { "name": "@remotion/effects", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "remotion": "workspace:*", }, @@ -674,7 +675,7 @@ }, "packages/elevenlabs": { "name": "@remotion/elevenlabs", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/captions": "workspace:*", }, @@ -686,7 +687,7 @@ }, "packages/enable-scss": { "name": "@remotion/enable-scss", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "css-loader": "7.1.4", "sass-loader": "14.2.1", @@ -704,7 +705,7 @@ }, "packages/eslint-config": { "name": "@remotion/eslint-config", - "version": "4.0.518", + "version": "4.0.519", "devDependencies": { "@remotion/eslint-config-internal": "workspace:*", "@remotion/eslint-plugin": "workspace:*", @@ -721,7 +722,7 @@ }, "packages/eslint-config-flat": { "name": "@remotion/eslint-config-flat", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "typescript-eslint": "8.21.0", }, @@ -740,7 +741,7 @@ }, "packages/eslint-config-internal": { "name": "@remotion/eslint-config-internal", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@eslint/compat": "1.2.2", "@eslint/eslintrc": "3.1.0", @@ -759,7 +760,7 @@ }, "packages/eslint-plugin": { "name": "@remotion/eslint-plugin", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@typescript-eslint/utils": "5.19.0", }, @@ -774,7 +775,7 @@ }, "packages/example": { "name": "@remotion/example", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@mdx-js/loader": "2.3.0", "@mdx-js/react": "2.3.0", @@ -871,7 +872,7 @@ }, "packages/example-videos": { "name": "@remotion/example-videos", - "version": "4.0.518", + "version": "4.0.519", "devDependencies": { "@remotion/eslint-config-internal": "workspace:*", "@typescript/native-preview": "catalog:", @@ -882,7 +883,7 @@ }, "packages/example-without-zod": { "name": "@remotion/example-without-zod", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/cli": "workspace:*", "react": "catalog:", @@ -892,7 +893,7 @@ }, "packages/fonts": { "name": "@remotion/fonts", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "remotion": "workspace:*", }, @@ -904,7 +905,7 @@ }, "packages/gif": { "name": "@remotion/gif", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "remotion": "workspace:*", }, @@ -925,7 +926,7 @@ }, "packages/google-fonts": { "name": "@remotion/google-fonts", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "remotion": "workspace:*", }, @@ -938,7 +939,7 @@ }, "packages/gsap": { "name": "@remotion/gsap", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "remotion": "workspace:*", }, @@ -961,7 +962,7 @@ }, "packages/install-whisper-cpp": { "name": "@remotion/install-whisper-cpp", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/captions": "workspace:*", }, @@ -973,7 +974,7 @@ }, "packages/it-tests": { "name": "@remotion/it-tests", - "version": "4.0.518", + "version": "4.0.519", "devDependencies": { "@mdx-js/loader": "2.3.0", "@remotion/babel-loader": "workspace:*", @@ -1028,7 +1029,7 @@ }, "packages/jonnys-videos": { "name": "@remotion/jonnys-videos", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@mediabunny/prores": "catalog:", "@remotion/captions": "workspace:*", @@ -1052,7 +1053,7 @@ }, "packages/kimi-code-plugin": { "name": "@remotion/kimi-code-plugin", - "version": "4.0.518", + "version": "4.0.519", "devDependencies": { "@remotion/eslint-config-internal": "workspace:*", "@typescript/native-preview": "catalog:", @@ -1061,7 +1062,7 @@ }, "packages/lambda": { "name": "@remotion/lambda", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@aws-sdk/client-cloudwatch-logs": "catalog:", "@aws-sdk/client-iam": "catalog:", @@ -1103,7 +1104,7 @@ }, "packages/lambda-client": { "name": "@remotion/lambda-client", - "version": "4.0.518", + "version": "4.0.519", "devDependencies": { "@aws-sdk/client-cloudwatch-logs": "catalog:", "@aws-sdk/client-iam": "catalog:", @@ -1127,25 +1128,25 @@ }, "packages/lambda-go": { "name": "@remotion/lambda-go", - "version": "4.0.518", + "version": "4.0.519", "devDependencies": { "remotion": "workspace:*", }, }, "packages/lambda-go-example": { "name": "@remotion/lambda-go-example", - "version": "4.0.518", + "version": "4.0.519", }, "packages/lambda-php": { "name": "@remotion/lambda-php", - "version": "4.0.518", + "version": "4.0.519", "devDependencies": { "remotion": "workspace:*", }, }, "packages/lambda-python": { "name": "@remotion/lambda-python", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "dotenv": "17.3.1", }, @@ -1155,14 +1156,14 @@ }, "packages/lambda-ruby": { "name": "@remotion/lambda-ruby", - "version": "4.0.518", + "version": "4.0.519", "devDependencies": { "remotion": "workspace:*", }, }, "packages/layout-utils": { "name": "@remotion/layout-utils", - "version": "4.0.518", + "version": "4.0.519", "devDependencies": { "@remotion/eslint-config-internal": "workspace:*", "@typescript/native-preview": "catalog:", @@ -1178,7 +1179,7 @@ }, "packages/licensing": { "name": "@remotion/licensing", - "version": "4.0.518", + "version": "4.0.519", "devDependencies": { "@remotion/eslint-config-internal": "workspace:*", "@typescript/native-preview": "catalog:", @@ -1189,7 +1190,7 @@ }, "packages/light-leaks": { "name": "@remotion/light-leaks", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/effects": "workspace:*", "remotion": "workspace:*", @@ -1209,7 +1210,7 @@ }, "packages/lottie": { "name": "@remotion/lottie", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "remotion": "workspace:*", }, @@ -1229,7 +1230,7 @@ }, "packages/mac-cursors": { "name": "@remotion/mac-cursors", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "remotion": "workspace:*", }, @@ -1247,7 +1248,7 @@ }, "packages/maptiler": { "name": "@remotion/maptiler", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@maptiler/sdk": "4.0.2", "@turf/turf": "7.3.2", @@ -1267,7 +1268,7 @@ }, "packages/mcp": { "name": "@remotion/mcp", - "version": "4.0.518", + "version": "4.0.519", "bin": { "remotion-mcp": "./dist/esm/index.mjs", }, @@ -1284,7 +1285,7 @@ }, "packages/media": { "name": "@remotion/media", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "mediabunny": "catalog:", "remotion": "workspace:*", @@ -1308,7 +1309,7 @@ }, "packages/media-parser": { "name": "@remotion/media-parser", - "version": "4.0.518", + "version": "4.0.519", "devDependencies": { "@remotion/eslint-config-internal": "workspace:*", "@remotion/example-videos": "workspace:*", @@ -1321,7 +1322,7 @@ }, "packages/media-utils": { "name": "@remotion/media-utils", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "mediabunny": "catalog:", "remotion": "workspace:*", @@ -1338,7 +1339,7 @@ }, "packages/motion-blur": { "name": "@remotion/motion-blur", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "remotion": "workspace:*", }, @@ -1357,7 +1358,7 @@ }, "packages/noise": { "name": "@remotion/noise", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "remotion": "workspace:*", "simplex-noise": "4.0.1", @@ -1370,7 +1371,7 @@ }, "packages/openai-whisper": { "name": "@remotion/openai-whisper", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/captions": "workspace:*", }, @@ -1383,7 +1384,7 @@ }, "packages/paths": { "name": "@remotion/paths", - "version": "4.0.518", + "version": "4.0.519", "devDependencies": { "@remotion/eslint-config-internal": "workspace:*", "@typescript/native-preview": "catalog:", @@ -1392,7 +1393,7 @@ }, "packages/player": { "name": "@remotion/player", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "remotion": "workspace:*", }, @@ -1415,7 +1416,7 @@ }, "packages/player-a11y": { "name": "@remotion/player-a11y", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/player": "workspace:*", "remotion": "workspace:*", @@ -1434,7 +1435,7 @@ }, "packages/player-example": { "name": "@remotion/player-example", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/bundler": "workspace:*", "@remotion/canvas": "workspace:*", @@ -1457,7 +1458,7 @@ }, "packages/preload": { "name": "@remotion/preload", - "version": "4.0.518", + "version": "4.0.519", "devDependencies": { "@remotion/eslint-config-internal": "workspace:*", "@typescript/native-preview": "catalog:", @@ -1466,7 +1467,7 @@ }, "packages/promo-pages": { "name": "@remotion/promo-pages", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@mediabunny/aac-encoder": "catalog:", "@mediabunny/ac3": "catalog:", @@ -1509,7 +1510,7 @@ }, "packages/react18-tests": { "name": "@remotion/react18-tests", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/zod-types": "workspace:*", "@remotion/zod-types-v3": "workspace:*", @@ -1539,7 +1540,7 @@ }, "packages/remotion-media": { "name": "@remotion/remotion-media", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/cli": "workspace:*", "@remotion/paths": "workspace:*", @@ -1562,7 +1563,7 @@ }, "packages/renderer": { "name": "@remotion/renderer", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/licensing": "workspace:*", "@remotion/streaming": "workspace:*", @@ -1600,7 +1601,7 @@ }, "packages/rive": { "name": "@remotion/rive", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@rive-app/canvas-advanced": "2.31.5", "remotion": "workspace:*", @@ -1619,7 +1620,7 @@ }, "packages/rough-notation": { "name": "@remotion/rough-notation", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/paths": "workspace:*", "remotion": "workspace:*", @@ -1639,7 +1640,7 @@ }, "packages/rounded-text-box": { "name": "@remotion/rounded-text-box", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/layout-utils": "workspace:*", "@remotion/paths": "workspace:*", @@ -1652,7 +1653,7 @@ }, "packages/serverless": { "name": "@remotion/serverless", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/bundler": "workspace:*", "@remotion/licensing": "workspace:*", @@ -1667,7 +1668,7 @@ }, "packages/serverless-client": { "name": "@remotion/serverless-client", - "version": "4.0.518", + "version": "4.0.519", "devDependencies": { "@remotion/eslint-config-internal": "workspace:*", "@remotion/renderer": "workspace:*", @@ -1679,7 +1680,7 @@ }, "packages/sfx": { "name": "@remotion/sfx", - "version": "4.0.518", + "version": "4.0.519", "devDependencies": { "@remotion/eslint-config-internal": "workspace:*", "@typescript/native-preview": "catalog:", @@ -1688,7 +1689,7 @@ }, "packages/shapes": { "name": "@remotion/shapes", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/paths": "workspace:*", "remotion": "workspace:*", @@ -1709,7 +1710,7 @@ }, "packages/skia": { "name": "@remotion/skia", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "remotion": "workspace:*", }, @@ -1733,7 +1734,7 @@ }, "packages/skills": { "name": "@remotion/skills", - "version": "4.0.518", + "version": "4.0.519", "devDependencies": { "@remotion/bundler": "workspace:*", "@remotion/cli": "workspace:*", @@ -1751,7 +1752,7 @@ }, "packages/skills-evals": { "name": "@remotion/skills-evals", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/skills": "workspace:*", "react": "catalog:", @@ -1768,7 +1769,7 @@ }, "packages/starburst": { "name": "@remotion/starburst", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/effects": "workspace:*", "remotion": "workspace:*", @@ -1788,7 +1789,7 @@ }, "packages/streaming": { "name": "@remotion/streaming", - "version": "4.0.518", + "version": "4.0.519", "devDependencies": { "@remotion/eslint-config-internal": "workspace:*", "@typescript/native-preview": "catalog:", @@ -1797,7 +1798,7 @@ }, "packages/studio": { "name": "@remotion/studio", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@jridgewell/trace-mapping": "0.3.31", "@remotion/canvas": "workspace:*", @@ -1837,7 +1838,7 @@ }, "packages/studio-codemods": { "name": "@remotion/studio-codemods", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@babel/parser": "7.24.1", "@babel/types": "7.24.0", @@ -1854,7 +1855,7 @@ }, "packages/studio-protocol": { "name": "@remotion/studio-protocol", - "version": "4.0.518", + "version": "4.0.519", "devDependencies": { "@remotion/eslint-config-internal": "workspace:*", "@typescript/native-preview": "catalog:", @@ -1863,7 +1864,7 @@ }, "packages/studio-server": { "name": "@remotion/studio-server", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@babel/parser": "7.24.1", "@babel/types": "7.24.0", @@ -1895,7 +1896,7 @@ }, "packages/studio-shared": { "name": "@remotion/studio-shared", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/studio-protocol": "workspace:*", "remotion": "workspace:*", @@ -1909,7 +1910,7 @@ }, "packages/svg-3d-engine": { "name": "@remotion/svg-3d-engine", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/paths": "workspace:*", }, @@ -1921,7 +1922,7 @@ }, "packages/tailwind": { "name": "@remotion/tailwind", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "autoprefixer": "10.4.20", "css-loader": "7.1.4", @@ -1944,7 +1945,7 @@ }, "packages/tailwind-v4": { "name": "@remotion/tailwind-v4", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@tailwindcss/webpack": "4.2.0", "css-loader": "7.1.4", @@ -2668,7 +2669,7 @@ }, "packages/test-utils": { "name": "@remotion/test-utils", - "version": "4.0.518", + "version": "4.0.519", "devDependencies": { "@remotion/eslint-config-internal": "workspace:*", "@typescript/native-preview": "catalog:", @@ -2680,7 +2681,7 @@ }, "packages/three": { "name": "@remotion/three", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "remotion": "workspace:*", }, @@ -2707,7 +2708,7 @@ }, "packages/timeline-utils": { "name": "@remotion/timeline-utils", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "mediabunny": "catalog:", "remotion": "workspace:*", @@ -2721,7 +2722,7 @@ }, "packages/transitions": { "name": "@remotion/transitions", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/paths": "workspace:*", "@remotion/shapes": "workspace:*", @@ -2745,7 +2746,7 @@ }, "packages/vercel": { "name": "@remotion/vercel", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/renderer": "workspace:*", "remotion": "workspace:*", @@ -2763,7 +2764,7 @@ }, "packages/web-renderer": { "name": "@remotion/web-renderer", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@mediabunny/aac-encoder": "catalog:", "@mediabunny/flac-encoder": "catalog:", @@ -2801,7 +2802,7 @@ }, "packages/webcodecs": { "name": "@remotion/webcodecs", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/media-parser": "workspace:*", }, @@ -2818,7 +2819,7 @@ }, "packages/whisper-web": { "name": "@remotion/whisper-web", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/captions": "workspace:*", }, @@ -2830,7 +2831,7 @@ }, "packages/whisper-webgpu": { "name": "@remotion/whisper-webgpu", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@huggingface/transformers": "catalog:", "@remotion/captions": "workspace:*", @@ -2843,7 +2844,7 @@ }, "packages/zod-types": { "name": "@remotion/zod-types", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "remotion": "workspace:*", }, @@ -2856,7 +2857,7 @@ }, "packages/zod-types-v3": { "name": "@remotion/zod-types-v3", - "version": "4.0.518", + "version": "4.0.519", "dependencies": { "@remotion/zod-types": "workspace:*", "remotion": "workspace:*", diff --git a/packages/animated-emoji/package.json b/packages/animated-emoji/package.json index 5729a1acc7d..7664d5b1706 100644 --- a/packages/animated-emoji/package.json +++ b/packages/animated-emoji/package.json @@ -1,6 +1,6 @@ { "name": "@remotion/animated-emoji", - "version": "4.0.518", + "version": "4.0.519", "main": "dist/cjs/index.js", "types": "dist/cjs/index.d.ts", "module": "dist/esm/index.mjs", diff --git a/packages/animation-utils/package.json b/packages/animation-utils/package.json index 32cb030f572..78ac0455ac9 100644 --- a/packages/animation-utils/package.json +++ b/packages/animation-utils/package.json @@ -7,7 +7,7 @@ "name": "Chetan Karwa", "email": "cbkarwa@gmail.com" }, - "version": "4.0.518", + "version": "4.0.519", "description": "Helpers for animating CSS properties", "main": "./dist/index.js", "module": "./dist/index.mjs", diff --git a/packages/astro-example/package.json b/packages/astro-example/package.json index de429577188..0fc8c7e5f06 100644 --- a/packages/astro-example/package.json +++ b/packages/astro-example/package.json @@ -5,7 +5,7 @@ "name": "@remotion/astro-example", "private": true, "type": "module", - "version": "4.0.518", + "version": "4.0.519", "scripts": { "dev": "astro dev", "start": "astro dev", diff --git a/packages/babel-loader/package.json b/packages/babel-loader/package.json index 0238d7ae9c7..1b810b89796 100644 --- a/packages/babel-loader/package.json +++ b/packages/babel-loader/package.json @@ -3,7 +3,7 @@ "url": "https://github.com/remotion-dev/remotion/tree/main/packages/babel-loader" }, "name": "@remotion/babel-loader", - "version": "4.0.518", + "version": "4.0.519", "description": "Babel loader for Remotion", "main": "dist/index.js", "scripts": { diff --git a/packages/brand/package.json b/packages/brand/package.json index ad7deee80fa..c446433b812 100644 --- a/packages/brand/package.json +++ b/packages/brand/package.json @@ -3,7 +3,7 @@ "url": "https://github.com/remotion-dev/remotion/tree/main/packages/brand" }, "name": "@remotion/brand", - "version": "4.0.518", + "version": "4.0.519", "private": true, "sideEffects": [ "*.css" diff --git a/packages/brand/src/bottom-up-letters.element.tsx b/packages/brand/src/bottom-up-letters.element.tsx new file mode 100644 index 00000000000..ef9be142702 --- /dev/null +++ b/packages/brand/src/bottom-up-letters.element.tsx @@ -0,0 +1,235 @@ +import { Easing, Interactive, Sequence, interpolate, useCurrentFrame, type InteractiveBaseProps, type InteractiveTransformProps, type InteractivitySchema, type SequenceControls } from "remotion"; +import { forwardRef, useImperativeHandle, useRef, type ComponentProps } from "react"; + +interface BottomUpLettersProps { + text: string; + staggerDelay?: number; + distance?: number; + fontSize?: number; + color?: string; + fontWeight?: number; + speed?: number; + className?: string; +} + +function BottomUpLettersBase({ + text, + staggerDelay = 3, + distance = 46, + fontSize = 72, + color = "#171717", + fontWeight = 600, + speed = 1, + className, +}: BottomUpLettersProps) { + const frame = useCurrentFrame() * speed; + + const chars = Array.from(text); + const charDurationFrames = 12; + const charTravelFrames = 7; + + return ( +
+ + {chars.map((char, i) => { + const local = frame - i * staggerDelay; + const easing = Easing.bezier(0.18, 1, 0.32, 1); + const opacity = interpolate(local, [0, charDurationFrames], [0, 1], { + extrapolateLeft: "clamp", + extrapolateRight: "clamp", + easing, + }); + const y = interpolate(local, [0, charTravelFrames], [distance, 0], { + extrapolateLeft: "clamp", + extrapolateRight: "clamp", + easing, + }); + return ( + + {char} + + ); + })} + +
+ ); +} + +const elementSchema = { + ...Interactive.baseSchema, + text: { + type: "text-content", + default: "Shift", + description: "Text", + }, + staggerDelay: { + type: "number", + min: 1, + max: 12, + step: 1, + default: 3, + description: "Stagger", + hiddenFromList: false, + }, + distance: { + type: "number", + min: 0, + max: 120, + step: 1, + default: 46, + description: "Distance", + hiddenFromList: false, + }, + fontSize: { + type: "number", + min: 12, + max: 160, + step: 1, + default: 72, + description: "Font size", + hiddenFromList: false, + }, + color: { + type: "color", + default: "#171717", + description: "Color", + }, + fontWeight: { + type: "enum", + default: "600", + variants: { + "400": {}, + "500": {}, + "600": {}, + "700": {}, + }, + description: "Font weight", + }, + speed: { + type: "number", + default: 1, + min: 0.25, + max: 4, + step: 0.25, + description: "Speed", + hiddenFromList: false, + }, + width: { + type: "number", + default: 190, + min: 10, + step: 10, + description: "Width", + }, + height: { + type: "number", + default: 100, + min: 10, + step: 10, + description: "Height", + }, + ...Interactive.transformSchema, +} as const satisfies InteractivitySchema; + +const ELEMENT_PROP_KEYS = new Set(["text","staggerDelay","distance","fontSize","color","fontWeight","speed"]); + +const ELEMENT_PROP_DEFAULTS: Record = { + text: "Shift", + staggerDelay: 3, + distance: 46, + fontSize: 72, + color: "#171717", + fontWeight: "600", + speed: 1, +}; + +type BottomUpLettersElementProps = InteractiveBaseProps & + InteractiveTransformProps & { readonly width?: number; readonly height?: number } & + ComponentProps; + +const BottomUpLettersInner = forwardRef< + HTMLDivElement, + BottomUpLettersElementProps & { readonly controls: SequenceControls | undefined } +>(({ controls, name, style, width = 190, height = 100, ...rest }, ref) => { + const outlineRef = useRef(null); + useImperativeHandle(ref, () => outlineRef.current as HTMLDivElement, []); + const componentProps: Record = { ...ELEMENT_PROP_DEFAULTS }; + const sequenceProps: Record = {}; + for (const [key, value] of Object.entries(rest)) { + if (ELEMENT_PROP_KEYS.has(key)) { + if (value !== undefined) componentProps[key] = value; + } else { + sequenceProps[key] = value; + } + } + return ( + "} + outlineRef={outlineRef} + > +
+
+ )} + /> +
+
+
+ ); +}); + +export const BottomUpLetters = Interactive.withSchema({ + Component: BottomUpLettersInner, + componentName: "", + componentIdentity: null, + schema: elementSchema, + supportsEffects: false, +}); diff --git a/packages/brand/src/line-by-line-slide.element.tsx b/packages/brand/src/line-by-line-slide.element.tsx new file mode 100644 index 00000000000..65248a0f057 --- /dev/null +++ b/packages/brand/src/line-by-line-slide.element.tsx @@ -0,0 +1,267 @@ +import { Easing, Interactive, Sequence, interpolate, useCurrentFrame, useVideoConfig, type InteractiveBaseProps, type InteractiveTransformProps, type InteractivitySchema, type SequenceControls } from "remotion"; +import { forwardRef, useImperativeHandle, useRef, type ComponentProps } from "react"; + +interface LineByLineSlideProps { + text: string; + distance?: number; + fontSize?: number; + color?: string; + fontWeight?: number; + speed?: number; + className?: string; +} + +function LineByLineSlideBase({ + text, + distance = 48, + fontSize = 72, + color = "#171717", + fontWeight = 600, + speed = 1, + className, +}: LineByLineSlideProps) { + const frame = useCurrentFrame() * speed; + const { durationInFrames } = useVideoConfig(); + + const lines = text.split("\n"); + + const enterDur = 27; + const enterTravel = 14; + const exitDur = 18; + const exitTravelFrom = 8; + const enterStagger = 4; + const exitStagger = 2; + + const enterEasing = Easing.bezier(0.22, 1, 0.36, 1); + const exitEasing = Easing.bezier(0.64, 0, 0.78, 0); + + const enterEnd = enterDur + (lines.length - 1) * enterStagger; + const exitStart = Math.max( + enterEnd, + durationInFrames - exitDur - (lines.length - 1) * exitStagger, + ); + + return ( +
+ + {lines.map((line, i) => { + const enterLocal = frame - i * enterStagger; + const exitLocal = frame - exitStart - i * exitStagger; + + const enterP = interpolate(enterLocal, [0, enterDur], [0, 1], { + extrapolateLeft: "clamp", + extrapolateRight: "clamp", + easing: enterEasing, + }); + + const exitP = interpolate(exitLocal, [0, exitDur], [0, 1], { + extrapolateLeft: "clamp", + extrapolateRight: "clamp", + easing: exitEasing, + }); + + const opacity = enterP * (1 - exitP); + + const xEnter = interpolate( + enterLocal, + [0, enterTravel], + [-distance, 0], + { + extrapolateLeft: "clamp", + extrapolateRight: "clamp", + easing: enterEasing, + }, + ); + + const xExit = interpolate( + exitLocal, + [exitTravelFrom, exitDur], + [0, distance], + { + extrapolateLeft: "clamp", + extrapolateRight: "clamp", + easing: exitEasing, + }, + ); + + const x = xEnter + xExit; + + return ( + + {line} + + ); + })} + +
+ ); +} + +const elementSchema = { + ...Interactive.baseSchema, + text: { + type: "text-content", + default: "Think different.\nDo more.", + description: "Text", + }, + distance: { + type: "number", + min: 0, + max: 160, + step: 1, + default: 48, + description: "Distance", + hiddenFromList: false, + }, + fontSize: { + type: "number", + min: 12, + max: 160, + step: 1, + default: 72, + description: "Font size", + hiddenFromList: false, + }, + color: { + type: "color", + default: "#171717", + description: "Color", + }, + fontWeight: { + type: "enum", + default: "600", + variants: { + "400": {}, + "500": {}, + "600": {}, + "700": {}, + }, + description: "Font weight", + }, + speed: { + type: "number", + default: 1, + min: 0.25, + max: 4, + step: 0.25, + description: "Speed", + hiddenFromList: false, + }, + width: { + type: "number", + default: 600, + min: 10, + step: 10, + description: "Width", + }, + height: { + type: "number", + default: 200, + min: 10, + step: 10, + description: "Height", + }, + ...Interactive.transformSchema, +} as const satisfies InteractivitySchema; + +const ELEMENT_PROP_KEYS = new Set(["text","distance","fontSize","color","fontWeight","speed"]); + +const ELEMENT_PROP_DEFAULTS: Record = { + text: "Think different.\nDo more.", + distance: 48, + fontSize: 72, + color: "#171717", + fontWeight: "600", + speed: 1, +}; + +type LineByLineSlideElementProps = InteractiveBaseProps & + InteractiveTransformProps & { readonly width?: number; readonly height?: number } & + ComponentProps; + +const LineByLineSlideInner = forwardRef< + HTMLDivElement, + LineByLineSlideElementProps & { readonly controls: SequenceControls | undefined } +>(({ controls, name, style, width = 600, height = 200, ...rest }, ref) => { + const outlineRef = useRef(null); + useImperativeHandle(ref, () => outlineRef.current as HTMLDivElement, []); + const componentProps: Record = { ...ELEMENT_PROP_DEFAULTS }; + const sequenceProps: Record = {}; + for (const [key, value] of Object.entries(rest)) { + if (ELEMENT_PROP_KEYS.has(key)) { + if (value !== undefined) componentProps[key] = value; + } else { + sequenceProps[key] = value; + } + } + return ( + "} + outlineRef={outlineRef} + > +
+
+ )} + /> +
+
+
+ ); +}); + +export const LineByLineSlide = Interactive.withSchema({ + Component: LineByLineSlideInner, + componentName: "", + componentIdentity: null, + schema: elementSchema, + supportsEffects: false, +}); diff --git a/packages/brand/src/per-word-crossfade.element.tsx b/packages/brand/src/per-word-crossfade.element.tsx new file mode 100644 index 00000000000..d0b63ef6187 --- /dev/null +++ b/packages/brand/src/per-word-crossfade.element.tsx @@ -0,0 +1,288 @@ +import { Easing, Interactive, Sequence, interpolate, useCurrentFrame, type InteractiveBaseProps, type InteractiveTransformProps, type InteractivitySchema, type SequenceControls } from "remotion"; +import { forwardRef, useImperativeHandle, useRef, type ComponentProps } from "react"; + +interface PerWordCrossfadeProps { + fromText: string; + toText: string; + fontSize?: number; + color?: string; + fontWeight?: number; + speed?: number; + className?: string; +} + +function PerWordCrossfadeBase({ + fromText, + toText, + fontSize = 72, + color = "#171717", + fontWeight = 600, + speed = 1, + className, +}: PerWordCrossfadeProps) { + const frame = useCurrentFrame() * speed; + + const fromWords = fromText.split(" "); + const toWords = toText.split(" "); + + const enterDur = 21; + const enterTravel = 5; + const exitDur = 15; + const exitTravelFrom = 6; + const enterStagger = 2; + const exitStagger = 1; + const overlapF = 5; + const microDelayF = 2; + + const enterEasing = Easing.bezier(0.16, 1, 0.3, 1); + const exitEasing = Easing.bezier(0.7, 0, 0.84, 0); + + const exitTotal = exitDur + (fromWords.length - 1) * exitStagger; + const newStart = Math.max(0, exitTotal - overlapF + microDelayF); + + const fontStack = + "var(--font-geist-sans), -apple-system, BlinkMacSystemFont, sans-serif"; + + return ( +
+
+ + {fromWords.map((word, i) => { + const local = frame - i * exitStagger; + const opacity = interpolate(local, [0, exitDur], [1, 0], { + extrapolateLeft: "clamp", + extrapolateRight: "clamp", + easing: exitEasing, + }); + const y = interpolate(local, [exitTravelFrom, exitDur], [0, -6], { + extrapolateLeft: "clamp", + extrapolateRight: "clamp", + easing: exitEasing, + }); + return ( + + {word} + + ); + })} + +
+ +
+ + {toWords.map((word, j) => { + const local = frame - newStart - j * enterStagger; + const opacity = interpolate(local, [0, enterDur], [0, 1], { + extrapolateLeft: "clamp", + extrapolateRight: "clamp", + easing: enterEasing, + }); + const y = interpolate(local, [0, enterTravel], [8, 0], { + extrapolateLeft: "clamp", + extrapolateRight: "clamp", + easing: enterEasing, + }); + return ( + + {word} + + ); + })} + +
+
+ ); +} + +const elementSchema = { + ...Interactive.baseSchema, + fromText: { + type: "text-content", + default: "Beautifully simple.", + description: "From text", + }, + toText: { + type: "text-content", + default: "Designed for focus.", + description: "To text", + }, + fontSize: { + type: "number", + min: 12, + max: 160, + step: 1, + default: 72, + description: "Font size", + hiddenFromList: false, + }, + color: { + type: "color", + default: "#171717", + description: "Color", + }, + fontWeight: { + type: "enum", + default: "600", + variants: { + "400": {}, + "500": {}, + "600": {}, + "700": {}, + }, + description: "Font weight", + }, + speed: { + type: "number", + default: 1, + min: 0.25, + max: 4, + step: 0.25, + description: "Speed", + hiddenFromList: false, + }, + width: { + type: "number", + default: 720, + min: 10, + step: 10, + description: "Width", + }, + height: { + type: "number", + default: 100, + min: 10, + step: 10, + description: "Height", + }, + ...Interactive.transformSchema, +} as const satisfies InteractivitySchema; + +const ELEMENT_PROP_KEYS = new Set(["fromText","toText","fontSize","color","fontWeight","speed"]); + +const ELEMENT_PROP_DEFAULTS: Record = { + fromText: "Beautifully simple.", + toText: "Designed for focus.", + fontSize: 72, + color: "#171717", + fontWeight: "600", + speed: 1, +}; + +type PerWordCrossfadeElementProps = InteractiveBaseProps & + InteractiveTransformProps & { readonly width?: number; readonly height?: number } & + ComponentProps; + +const PerWordCrossfadeInner = forwardRef< + HTMLDivElement, + PerWordCrossfadeElementProps & { readonly controls: SequenceControls | undefined } +>(({ controls, name, style, width = 720, height = 100, ...rest }, ref) => { + const outlineRef = useRef(null); + useImperativeHandle(ref, () => outlineRef.current as HTMLDivElement, []); + const componentProps: Record = { ...ELEMENT_PROP_DEFAULTS }; + const sequenceProps: Record = {}; + for (const [key, value] of Object.entries(rest)) { + if (ELEMENT_PROP_KEYS.has(key)) { + if (value !== undefined) componentProps[key] = value; + } else { + sequenceProps[key] = value; + } + } + return ( + "} + outlineRef={outlineRef} + > +
+
+ )} + /> +
+
+
+ ); +}); + +export const PerWordCrossfade = Interactive.withSchema({ + Component: PerWordCrossfadeInner, + componentName: "", + componentIdentity: null, + schema: elementSchema, + supportsEffects: false, +}); diff --git a/packages/brand/src/word-stream.element.tsx b/packages/brand/src/word-stream.element.tsx new file mode 100644 index 00000000000..95f69c44434 --- /dev/null +++ b/packages/brand/src/word-stream.element.tsx @@ -0,0 +1,338 @@ +import { Easing, Interactive, Sequence, interpolate, useCurrentFrame, type InteractiveBaseProps, type InteractiveTransformProps, type InteractivitySchema, type SequenceControls } from "remotion"; +import { forwardRef, useImperativeHandle, useRef, type ComponentProps } from "react"; + +interface WordStreamProps { + text: string; + fontSize?: number; + color?: string; + fontWeight?: number; + wordGap?: number; + hold?: number; + drift?: number; + speed?: number; + className?: string; +} + +interface PhraseSchedule { + words: string[]; + start: number; + exitStart: number; + last: boolean; +} + +const REVEAL_FRAMES = 3; +const ENTRY_FRAMES = 8; +const RUN_OUT_FRAMES = 5; +const SWAP_OVERLAP = 0; + +function wordStreamLength(text: string, wordGap = 6, hold = 18): number { + const schedule = schedulePhrases(text, wordGap, hold); + const finalPhrase = schedule[schedule.length - 1]; + if (!finalPhrase) return 0; + return ( + finalPhrase.start + (finalPhrase.words.length - 1) * wordGap + REVEAL_FRAMES + ); +} + +function schedulePhrases( + text: string, + wordGap: number, + hold: number, +): PhraseSchedule[] { + const phrases = text + .split("|") + .map((phrase) => phrase.trim()) + .filter(Boolean); + let cursor = 0; + return phrases.map((phrase, i) => { + const words = phrase.split(/\s+/); + const start = cursor; + const complete = start + (words.length - 1) * wordGap + REVEAL_FRAMES; + const exitStart = complete + hold; + cursor = exitStart + SWAP_OVERLAP; + return { words, start, exitStart, last: i === phrases.length - 1 }; + }); +} + +const revealEasing = Easing.bezier(0.2, 0.8, 0.2, 1); +const entryEasing = Easing.bezier(0.2, 0.8, 0.3, 1); +const runOutEasing = Easing.bezier(0.7, 0, 0.9, 0.4); + +function WordStreamBase({ + text, + fontSize = 72, + color = "#171717", + fontWeight = 400, + wordGap = 6, + hold = 18, + drift = 2, + speed = 1, + className, +}: WordStreamProps) { + const frame = useCurrentFrame() * speed; + + const schedule = schedulePhrases(text, wordGap, hold); + + return ( +
+ {schedule.map((phrase, i) => { + if (frame < phrase.start) return null; + if (!phrase.last && frame >= phrase.exitStart) return null; + + const scale = fontSize / 72; + const crawl = scale * drift; + const life = phrase.exitStart - phrase.start; + + const entryX = interpolate( + frame, + [phrase.start, phrase.start + ENTRY_FRAMES], + [scale * 30, 0], + { + extrapolateLeft: "clamp", + extrapolateRight: "clamp", + easing: entryEasing, + }, + ); + const crawlX = + crawl * + (life / 2 - (Math.min(frame, phrase.exitStart) - phrase.start)); + const runOutX = phrase.last + ? 0 + : interpolate( + frame, + [phrase.exitStart - RUN_OUT_FRAMES, phrase.exitStart], + [0, -scale * 80], + { + extrapolateLeft: "clamp", + extrapolateRight: "clamp", + easing: runOutEasing, + }, + ); + const x = entryX + crawlX + runOutX; + + return ( +
+ + {phrase.words.map((word, j) => { + const revealAt = phrase.start + j * wordGap; + + const opacity = interpolate( + frame, + [revealAt, revealAt + REVEAL_FRAMES], + [0, 1], + { + extrapolateLeft: "clamp", + extrapolateRight: "clamp", + easing: revealEasing, + }, + ); + + return ( + + {word} + + ); + })} + +
+ ); + })} +
+ ); +} + +const elementSchema = { + ...Interactive.baseSchema, + text: { + type: "text-content", + default: "introducing | one-tap checkout | for your store", + description: "Phrases (| separated)", + }, + fontSize: { + type: "number", + min: 12, + max: 160, + step: 1, + default: 72, + description: "Font size", + hiddenFromList: false, + }, + wordGap: { + type: "number", + min: 2, + max: 30, + step: 1, + default: 6, + description: "Frames / word", + hiddenFromList: false, + }, + hold: { + type: "number", + min: 6, + max: 90, + step: 3, + default: 18, + description: "Phrase hold", + hiddenFromList: false, + }, + drift: { + type: "number", + min: 0, + max: 6, + step: 0.5, + default: 2, + description: "Drift px / frame", + hiddenFromList: false, + }, + color: { + type: "color", + default: "#171717", + description: "Color", + }, + fontWeight: { + type: "enum", + default: "400", + variants: { + "400": {}, + "500": {}, + "600": {}, + "700": {}, + }, + description: "Font weight", + }, + speed: { + type: "number", + default: 1, + min: 0.25, + max: 4, + step: 0.25, + description: "Speed", + hiddenFromList: false, + }, + width: { + type: "number", + default: 700, + min: 10, + step: 10, + description: "Width", + }, + height: { + type: "number", + default: 110, + min: 10, + step: 10, + description: "Height", + }, + ...Interactive.transformSchema, +} as const satisfies InteractivitySchema; + +const ELEMENT_PROP_KEYS = new Set(["text","fontSize","wordGap","hold","drift","color","fontWeight","speed"]); + +const ELEMENT_PROP_DEFAULTS: Record = { + text: "introducing | one-tap checkout | for your store", + fontSize: 72, + wordGap: 6, + hold: 18, + drift: 2, + color: "#171717", + fontWeight: "400", + speed: 1, +}; + +type WordStreamElementProps = InteractiveBaseProps & + InteractiveTransformProps & { readonly width?: number; readonly height?: number } & + ComponentProps; + +const WordStreamInner = forwardRef< + HTMLDivElement, + WordStreamElementProps & { readonly controls: SequenceControls | undefined } +>(({ controls, name, style, width = 700, height = 110, ...rest }, ref) => { + const outlineRef = useRef(null); + useImperativeHandle(ref, () => outlineRef.current as HTMLDivElement, []); + const componentProps: Record = { ...ELEMENT_PROP_DEFAULTS }; + const sequenceProps: Record = {}; + for (const [key, value] of Object.entries(rest)) { + if (ELEMENT_PROP_KEYS.has(key)) { + if (value !== undefined) componentProps[key] = value; + } else { + sequenceProps[key] = value; + } + } + return ( + "} + outlineRef={outlineRef} + > +
+
+ )} + /> +
+
+
+ ); +}); + +export const WordStream = Interactive.withSchema({ + Component: WordStreamInner, + componentName: "", + componentIdentity: null, + schema: elementSchema, + supportsEffects: false, +}); diff --git a/packages/browser-studio/package.json b/packages/browser-studio/package.json index b091a500822..b7d6c41e08a 100644 --- a/packages/browser-studio/package.json +++ b/packages/browser-studio/package.json @@ -4,7 +4,7 @@ }, "name": "@remotion/browser-studio", "private": true, - "version": "4.0.518", + "version": "4.0.519", "description": "Run Remotion Studio in the browser", "main": "dist/esm/index.mjs", "types": "dist/index.d.ts", diff --git a/packages/bugs/package.json b/packages/bugs/package.json index 869fa7fc480..2019d942ecb 100644 --- a/packages/bugs/package.json +++ b/packages/bugs/package.json @@ -4,5 +4,5 @@ }, "name": "bugs", "private": true, - "version": "4.0.518" + "version": "4.0.519" } diff --git a/packages/bundler/package.json b/packages/bundler/package.json index 424c5654ed5..b1755bf1e78 100644 --- a/packages/bundler/package.json +++ b/packages/bundler/package.json @@ -3,7 +3,7 @@ "url": "https://github.com/remotion-dev/remotion/tree/main/packages/bundler" }, "name": "@remotion/bundler", - "version": "4.0.518", + "version": "4.0.519", "description": "Bundle Remotion compositions using Webpack", "main": "dist/index.js", "bugs": { diff --git a/packages/canvas-capture-extension/package.json b/packages/canvas-capture-extension/package.json index ff42eae8f46..5a2b648c8a9 100644 --- a/packages/canvas-capture-extension/package.json +++ b/packages/canvas-capture-extension/package.json @@ -1,6 +1,6 @@ { "name": "@remotion/canvas-capture-extension", - "version": "4.0.518", + "version": "4.0.519", "private": true, "type": "module", "scripts": { diff --git a/packages/canvas/package.json b/packages/canvas/package.json index baed23c55c3..bde1f5bf5bc 100644 --- a/packages/canvas/package.json +++ b/packages/canvas/package.json @@ -3,7 +3,7 @@ "url": "https://github.com/remotion-dev/remotion/tree/main/packages/canvas" }, "name": "@remotion/canvas", - "version": "4.0.518", + "version": "4.0.519", "description": "Headless primitives for Remotion authoring interfaces", "main": "dist/index.cjs", "types": "dist/index.d.ts", diff --git a/packages/captions/package.json b/packages/captions/package.json index 79b79c7e985..fa2b323d796 100644 --- a/packages/captions/package.json +++ b/packages/captions/package.json @@ -3,7 +3,7 @@ "url": "https://github.com/remotion-dev/remotion/tree/main/packages/captions" }, "name": "@remotion/captions", - "version": "4.0.518", + "version": "4.0.519", "description": "Primitives for dealing with captions", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/claude-code-plugin/.claude-plugin/plugin.json b/packages/claude-code-plugin/.claude-plugin/plugin.json index bb0d5bebe5b..9f29ab90c93 100644 --- a/packages/claude-code-plugin/.claude-plugin/plugin.json +++ b/packages/claude-code-plugin/.claude-plugin/plugin.json @@ -2,7 +2,7 @@ "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "remotion", "displayName": "Remotion", - "version": "4.0.518", + "version": "4.0.519", "description": "Remotion video creation skills — best practices, animations, audio, captions, 3D, and more for building programmatic videos with React.", "author": { "name": "Remotion", diff --git a/packages/claude-code-plugin/package.json b/packages/claude-code-plugin/package.json index aaed54317d3..1e387144750 100644 --- a/packages/claude-code-plugin/package.json +++ b/packages/claude-code-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@remotion/claude-code-plugin", - "version": "4.0.518", + "version": "4.0.519", "private": true, "type": "module", "repository": { diff --git a/packages/cli/package.json b/packages/cli/package.json index 86b60265bee..26091a4a464 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -3,7 +3,7 @@ "url": "https://github.com/remotion-dev/remotion/tree/main/packages/cli" }, "name": "@remotion/cli", - "version": "4.0.518", + "version": "4.0.519", "description": "Control Remotion features using the `npx remotion` command", "main": "dist/index.js", "bin": { diff --git a/packages/cloudrun/container/package.json b/packages/cloudrun/container/package.json index 753664ed113..d2dea479269 100644 --- a/packages/cloudrun/container/package.json +++ b/packages/cloudrun/container/package.json @@ -1,6 +1,6 @@ { "name": "cloud-run-render", - "version": "4.0.518", + "version": "4.0.519", "description": "Render media and stills on GCP Cloud Run", "main": "dist/index.js", "scripts": { diff --git a/packages/cloudrun/package.json b/packages/cloudrun/package.json index dd39e8fb720..414b2d48527 100644 --- a/packages/cloudrun/package.json +++ b/packages/cloudrun/package.json @@ -3,7 +3,7 @@ "url": "https://github.com/remotion-dev/remotion/tree/main/packages/cloudrun" }, "name": "@remotion/cloudrun", - "version": "4.0.518", + "version": "4.0.519", "description": "Render Remotion videos on Google Cloud Run", "main": "dist/index.js", "scripts": { diff --git a/packages/codex-plugin/.codex-plugin/plugin.json b/packages/codex-plugin/.codex-plugin/plugin.json index 058820d01cf..309931c92b5 100644 --- a/packages/codex-plugin/.codex-plugin/plugin.json +++ b/packages/codex-plugin/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "remotion", - "version": "4.0.518", + "version": "4.0.519", "description": "Remotion video creation skills — best practices, animations, audio, captions, 3D, and more for building programmatic videos with React.", "author": { "name": "Remotion", diff --git a/packages/codex-plugin/package.json b/packages/codex-plugin/package.json index 80baacbe5e6..461b3641b79 100644 --- a/packages/codex-plugin/package.json +++ b/packages/codex-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@remotion/codex-plugin", - "version": "4.0.518", + "version": "4.0.519", "private": true, "type": "module", "repository": { diff --git a/packages/codex-plugin/plugin.json b/packages/codex-plugin/plugin.json index a642f49f65f..532044b4339 100644 --- a/packages/codex-plugin/plugin.json +++ b/packages/codex-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "remotion", - "version": "4.0.518", + "version": "4.0.519", "description": "Remotion video creation skills — best practices, animations, audio, captions, 3D, and more for building programmatic videos with React.", "author": { "name": "Remotion", diff --git a/packages/compositor-darwin-arm64/package.json b/packages/compositor-darwin-arm64/package.json index 4ccb403cba2..cea50545d79 100644 --- a/packages/compositor-darwin-arm64/package.json +++ b/packages/compositor-darwin-arm64/package.json @@ -2,7 +2,7 @@ "repository": { "url": "https://github.com/remotion-dev/remotion/tree/main/packages/compositor-darwin-arm64" }, - "version": "4.0.518", + "version": "4.0.519", "name": "@remotion/compositor-darwin-arm64", "os": [ "darwin" diff --git a/packages/compositor-darwin-x64/package.json b/packages/compositor-darwin-x64/package.json index 6395cb4b9bd..efcdb226fc0 100644 --- a/packages/compositor-darwin-x64/package.json +++ b/packages/compositor-darwin-x64/package.json @@ -2,7 +2,7 @@ "repository": { "url": "https://github.com/remotion-dev/remotion/tree/main/packages/compositor-darwin-x64" }, - "version": "4.0.518", + "version": "4.0.519", "name": "@remotion/compositor-darwin-x64", "os": [ "darwin" diff --git a/packages/compositor-linux-arm64-gnu/package.json b/packages/compositor-linux-arm64-gnu/package.json index 0bf09b44db4..1c73734136c 100644 --- a/packages/compositor-linux-arm64-gnu/package.json +++ b/packages/compositor-linux-arm64-gnu/package.json @@ -2,7 +2,7 @@ "repository": { "url": "https://github.com/remotion-dev/remotion/tree/main/packages/compositor-linux-arm64-gnu" }, - "version": "4.0.518", + "version": "4.0.519", "name": "@remotion/compositor-linux-arm64-gnu", "os": [ "linux" diff --git a/packages/compositor-linux-arm64-musl/package.json b/packages/compositor-linux-arm64-musl/package.json index a84bf39b9b4..c3687e2ad38 100644 --- a/packages/compositor-linux-arm64-musl/package.json +++ b/packages/compositor-linux-arm64-musl/package.json @@ -2,7 +2,7 @@ "repository": { "url": "https://github.com/remotion-dev/remotion/tree/main/packages/compositor-linux-arm64-musl" }, - "version": "4.0.518", + "version": "4.0.519", "name": "@remotion/compositor-linux-arm64-musl", "os": [ "linux" diff --git a/packages/compositor-linux-x64-gnu/package.json b/packages/compositor-linux-x64-gnu/package.json index e4bae653ea2..da33e9df734 100644 --- a/packages/compositor-linux-x64-gnu/package.json +++ b/packages/compositor-linux-x64-gnu/package.json @@ -2,7 +2,7 @@ "repository": { "url": "https://github.com/remotion-dev/remotion/tree/main/packages/compositor-linux-x64-gnu" }, - "version": "4.0.518", + "version": "4.0.519", "name": "@remotion/compositor-linux-x64-gnu", "os": [ "linux" diff --git a/packages/compositor-linux-x64-musl/package.json b/packages/compositor-linux-x64-musl/package.json index 2358499e5fc..302c29d65eb 100644 --- a/packages/compositor-linux-x64-musl/package.json +++ b/packages/compositor-linux-x64-musl/package.json @@ -2,7 +2,7 @@ "repository": { "url": "https://github.com/remotion-dev/remotion/tree/main/packages/compositor-linux-x64-musl" }, - "version": "4.0.518", + "version": "4.0.519", "name": "@remotion/compositor-linux-x64-musl", "os": [ "linux" diff --git a/packages/compositor-win32-x64-msvc/package.json b/packages/compositor-win32-x64-msvc/package.json index 3b2def6fcc7..08d7cb0d736 100644 --- a/packages/compositor-win32-x64-msvc/package.json +++ b/packages/compositor-win32-x64-msvc/package.json @@ -2,7 +2,7 @@ "repository": { "url": "https://github.com/remotion-dev/remotion/tree/main/packages/compositor-win32-x64-msvc" }, - "version": "4.0.518", + "version": "4.0.519", "name": "@remotion/compositor-win32-x64-msvc", "os": [ "win32" diff --git a/packages/compositor/package.json b/packages/compositor/package.json index 6655455bb43..9969f39167d 100644 --- a/packages/compositor/package.json +++ b/packages/compositor/package.json @@ -3,7 +3,7 @@ "url": "https://github.com/remotion-dev/remotion/tree/main/packages/compositor" }, "name": "@remotion/compositor", - "version": "4.0.518", + "version": "4.0.519", "description": "Rust binary for Remotion", "scripts": { "build-all": "bun build.ts --all" diff --git a/packages/convert/package.json b/packages/convert/package.json index d59189365df..d124f4e7eed 100644 --- a/packages/convert/package.json +++ b/packages/convert/package.json @@ -1,6 +1,6 @@ { "name": "@remotion/convert", - "version": "4.0.518", + "version": "4.0.519", "private": true, "type": "module", "author": "Jonny Burger , Hunain Ahmed ", diff --git a/packages/core/package.json b/packages/core/package.json index 8fc3510dc54..a5e7cc28b0c 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -3,7 +3,7 @@ "url": "https://github.com/remotion-dev/remotion/tree/main/packages/core" }, "name": "remotion", - "version": "4.0.518", + "version": "4.0.519", "description": "Make videos programmatically", "main": "dist/cjs/index.js", "types": "dist/cjs/index.d.ts", diff --git a/packages/core/src/version.ts b/packages/core/src/version.ts index 50a9667f921..664b485c814 100644 --- a/packages/core/src/version.ts +++ b/packages/core/src/version.ts @@ -5,4 +5,4 @@ * @see [Documentation](https://remotion.dev/docs/version) * @returns {string} The current version of the remotion package */ -export const VERSION = '4.0.518'; +export const VERSION = '4.0.519'; diff --git a/packages/create-video/package.json b/packages/create-video/package.json index d928ac8fc1f..683c4d97ec0 100644 --- a/packages/create-video/package.json +++ b/packages/create-video/package.json @@ -3,7 +3,7 @@ "url": "https://github.com/remotion-dev/remotion/tree/main/packages/create-video" }, "name": "create-video", - "version": "4.0.518", + "version": "4.0.519", "description": "Create a new Remotion project", "main": "dist/index.js", "bin": { diff --git a/packages/design/package.json b/packages/design/package.json index 611a7075622..085406fbca9 100644 --- a/packages/design/package.json +++ b/packages/design/package.json @@ -1,6 +1,6 @@ { "name": "@remotion/design", - "version": "4.0.518", + "version": "4.0.519", "main": "dist/index.js", "types": "dist/index.d.ts", "module": "dist/esm/index.mjs", diff --git a/packages/discord-poster/package.json b/packages/discord-poster/package.json index 3a7dd48a90c..c3bb6835046 100644 --- a/packages/discord-poster/package.json +++ b/packages/discord-poster/package.json @@ -3,7 +3,7 @@ "url": "https://github.com/remotion-dev/remotion/tree/main/packages/discord-poster" }, "name": "@remotion/discord-poster", - "version": "4.0.518", + "version": "4.0.519", "license": "SEE LICENSE IN LICENSE.md", "type": "module", "scripts": { diff --git a/packages/docs/package.json b/packages/docs/package.json index a58518f93a4..0f617e5b2f3 100644 --- a/packages/docs/package.json +++ b/packages/docs/package.json @@ -4,7 +4,7 @@ }, "name": "docs", "private": true, - "version": "4.0.518", + "version": "4.0.519", "scripts": { "formatting": "oxfmt src standalone --check", "format": "oxfmt src standalone", diff --git a/packages/docusaurus-plugin/package.json b/packages/docusaurus-plugin/package.json index 50880ee6ca5..5222add2066 100644 --- a/packages/docusaurus-plugin/package.json +++ b/packages/docusaurus-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@remotion/docusaurus-plugin", - "version": "4.0.518", + "version": "4.0.519", "main": "dist/index.js", "types": "dist/index.d.ts", "scripts": { diff --git a/packages/effects/package.json b/packages/effects/package.json index 59cd84cda66..5fd889c1ae5 100644 --- a/packages/effects/package.json +++ b/packages/effects/package.json @@ -1,6 +1,6 @@ { "name": "@remotion/effects", - "version": "4.0.518", + "version": "4.0.519", "description": "Effects that can be applied to Remotion-based canvas components", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/elevenlabs/package.json b/packages/elevenlabs/package.json index c0aa41ca2b0..945e02bf889 100644 --- a/packages/elevenlabs/package.json +++ b/packages/elevenlabs/package.json @@ -3,7 +3,7 @@ "url": "https://github.com/remotion-dev/remotion/tree/main/packages/elevenlabs" }, "name": "@remotion/elevenlabs", - "version": "4.0.518", + "version": "4.0.519", "description": "Work with the output of the ElevenLabs API", "main": "dist/index.js", "bugs": { diff --git a/packages/enable-scss/package.json b/packages/enable-scss/package.json index f907d5b8d73..e482855fe3e 100644 --- a/packages/enable-scss/package.json +++ b/packages/enable-scss/package.json @@ -3,7 +3,7 @@ "url": "https://github.com/remotion-dev/remotion/tree/main/packages/enable-scss" }, "name": "@remotion/enable-scss", - "version": "4.0.518", + "version": "4.0.519", "description": "Enable SCSS support in Remotion", "main": "dist/cjs/index.js", "types": "dist/cjs/index.d.ts", diff --git a/packages/eslint-config-flat/package.json b/packages/eslint-config-flat/package.json index b7b0ab30e90..268b96b180d 100644 --- a/packages/eslint-config-flat/package.json +++ b/packages/eslint-config-flat/package.json @@ -3,7 +3,7 @@ "url": "https://github.com/remotion-dev/remotion/tree/main/packages/eslint-config-flat" }, "name": "@remotion/eslint-config-flat", - "version": "4.0.518", + "version": "4.0.519", "description": "Default configuration for Remotion templates (ESLint >= 9)", "main": "dist/esm/index.mjs", "type": "module", diff --git a/packages/eslint-config-internal/package.json b/packages/eslint-config-internal/package.json index 953a57937d9..9d8e25918b3 100644 --- a/packages/eslint-config-internal/package.json +++ b/packages/eslint-config-internal/package.json @@ -3,7 +3,7 @@ "url": "https://github.com/remotion-dev/remotion/tree/main/packages/eslint-config-internal" }, "name": "@remotion/eslint-config-internal", - "version": "4.0.518", + "version": "4.0.519", "license": "SEE LICENSE IN LICENSE.md", "main": "dist/index.js", "scripts": { diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index 451435ee42f..d501c83085d 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -3,7 +3,7 @@ "url": "https://github.com/remotion-dev/remotion/tree/main/packages/eslint-config" }, "name": "@remotion/eslint-config", - "version": "4.0.518", + "version": "4.0.519", "description": "Default configuration for Remotion templates (ESLint <= 8)", "main": "dist/index.js", "files": [ diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 47fe8953c32..00519e8fa2e 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -3,7 +3,7 @@ "url": "https://github.com/remotion-dev/remotion/tree/main/packages/eslint-plugin" }, "name": "@remotion/eslint-plugin", - "version": "4.0.518", + "version": "4.0.519", "description": "Rules for writing Remotion code", "scripts": { "test": "node src/tests/execute.mjs", diff --git a/packages/example-videos/package.json b/packages/example-videos/package.json index a017ad089db..4cacd4d8878 100644 --- a/packages/example-videos/package.json +++ b/packages/example-videos/package.json @@ -3,7 +3,7 @@ "url": "https://github.com/remotion-dev/remotion/tree/main/packages/example-videos" }, "name": "@remotion/example-videos", - "version": "4.0.518", + "version": "4.0.519", "main": "dist/index.js", "types": "dist/index.d.ts", "scripts": { diff --git a/packages/example-without-zod/package.json b/packages/example-without-zod/package.json index 5afae6bdb2a..37c6bed59a6 100644 --- a/packages/example-without-zod/package.json +++ b/packages/example-without-zod/package.json @@ -4,7 +4,7 @@ }, "name": "@remotion/example-without-zod", "private": true, - "version": "4.0.518", + "version": "4.0.519", "license": "SEE LICENSE IN LICENSE.md", "author": "Jonny Burger", "main": "dist/index.js", diff --git a/packages/example/package.json b/packages/example/package.json index ddae347986b..4f4d41a662e 100644 --- a/packages/example/package.json +++ b/packages/example/package.json @@ -4,7 +4,7 @@ }, "name": "@remotion/example", "private": true, - "version": "4.0.518", + "version": "4.0.519", "license": "SEE LICENSE IN LICENSE.md", "author": "Jonny Burger", "main": "dist/index.js", diff --git a/packages/example/src/MovingPillCaptionsComposition.tsx b/packages/example/src/MovingPillCaptionsComposition.tsx new file mode 100644 index 00000000000..cb648c74bfb --- /dev/null +++ b/packages/example/src/MovingPillCaptionsComposition.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import {MovingPillCaptions} from './moving-pill-captions.element'; +import {AudioOscilloscope} from './oscilloscope.element'; + +export const MovingPillCaptionsComposition: React.FC = () => { + return ( + <> + + + + ); +}; diff --git a/packages/example/src/mirrored-spectrum.element.tsx b/packages/example/src/mirrored-spectrum.element.tsx new file mode 100644 index 00000000000..e9632dd0d4b --- /dev/null +++ b/packages/example/src/mirrored-spectrum.element.tsx @@ -0,0 +1,176 @@ +import {Audio} from '@remotion/media'; +import {useWindowedAudioData, visualizeAudio} from '@remotion/media-utils'; +import React, {forwardRef, useImperativeHandle, useRef} from 'react'; +import { + Interactive, + Sequence, + useCurrentFrame, + useVideoConfig, + type InteractiveBaseProps, + type InteractiveTransformProps, + type InteractivitySchema, + type SequenceControls, +} from 'remotion'; + +type MirroredAudioSpectrumProps = InteractiveBaseProps & + InteractiveTransformProps & { + readonly audioSrc?: string; + readonly barColor?: string; + readonly numberOfBars?: number; + readonly sensitivity?: number; + }; + +const mirroredAudioSpectrumSchema = { + ...Interactive.baseSchema, + audioSrc: { + type: 'asset', + default: + 'https://remotion.media/elements/remotion-made-this-picture-move.mp3', + description: 'Audio source', + }, + barColor: { + type: 'color', + default: '#0b84f3', + description: 'Bar color', + }, + numberOfBars: { + type: 'number', + min: 3, + max: 127, + step: 2, + default: 65, + description: 'Number of bars', + hiddenFromList: false, + keyframable: false, + }, + sensitivity: { + type: 'number', + min: 0.25, + max: 3, + step: 0.05, + default: 1.5, + description: 'Sensitivity', + hiddenFromList: false, + }, + ...Interactive.transformSchema, +} as const satisfies InteractivitySchema; + +const MirroredAudioSpectrumContent: React.FC<{ + readonly audioSrc: string; + readonly barColor: string; + readonly numberOfBars: number; + readonly outlineRef: React.RefObject; + readonly sensitivity: number; + readonly style: MirroredAudioSpectrumProps['style']; +}> = ({audioSrc, barColor, numberOfBars, outlineRef, sensitivity, style}) => { + const frame = useCurrentFrame(); + const {fps} = useVideoConfig(); + const {audioData, dataOffsetInSeconds} = useWindowedAudioData({ + fps, + frame, + src: audioSrc, + windowInSeconds: 10, + }); + const roundedNumberOfBars = Math.max( + 3, + Math.min(127, Math.round(numberOfBars)), + ); + const numberOfFrequencies = Math.ceil(roundedNumberOfBars / 2); + const frequencyData = audioData + ? visualizeAudio({ + audioData, + dataOffsetInSeconds, + fps, + frame, + numberOfSamples: 256, + optimizeFor: 'speed', + }) + : []; + const frequencyDataSubset = frequencyData.slice(0, numberOfFrequencies); + const frequenciesToDisplay = [ + ...frequencyDataSubset.slice(roundedNumberOfBars % 2).reverse(), + ...frequencyDataSubset, + ]; + + return ( +
+