| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- import React from "react";
- import {
- useCurrentFrame,
- useVideoConfig,
- AbsoluteFill,
- interpolate,
- Easing,
- } from "remotion";
- import type { RemotionScene } from "../Root";
- import { THEMES } from "../base/theme/colors";
- import { Background } from "../base/components/background";
- import { SubtitleBar } from "../base/components/subtitle-bar";
- import { AnimatedText } from "../base/components/animated-text";
- import { Watermark } from "../base/components/watermark";
- import { StepIndicator } from "./components/step-indicator";
- import { KeyPointCard } from "./components/key-point-card";
- interface KnowledgeSceneProps {
- scene: RemotionScene;
- sceneIndex: number;
- totalScenes: number;
- totalFrames: number;
- title: string;
- channelName?: string;
- }
- const KnowledgeScene: React.FC<KnowledgeSceneProps> = ({
- scene,
- sceneIndex,
- totalScenes,
- totalFrames,
- title,
- channelName,
- }) => {
- const frame = useCurrentFrame();
- const colors = THEMES.knowledge;
- const visualText = scene.displayText ?? scene.narration;
- const fadeOpacity = interpolate(
- frame,
- [0, 10, scene.endFrame - scene.startFrame - 10, scene.endFrame - scene.startFrame],
- [0, 1, 1, 0],
- { extrapolateLeft: "clamp", extrapolateRight: "clamp" }
- );
- return (
- <AbsoluteFill style={{ opacity: fadeOpacity }}>
- <Background
- colors={colors}
- sceneIndex={sceneIndex}
- totalScenes={totalScenes}
- />
- {/* Step indicator */}
- <div
- style={{
- position: "absolute",
- top: 48,
- left: 80,
- }}
- >
- <StepIndicator
- currentStep={sceneIndex}
- totalSteps={totalScenes}
- color={colors.primaryLight}
- />
- </div>
- {/* Title label */}
- <div
- style={{
- position: "absolute",
- top: 48,
- right: 80,
- fontSize: 18,
- color: "#94a3b8",
- fontFamily: "Noto Sans SC",
- }}
- >
- {title}
- </div>
- {/* Content */}
- <div
- style={{
- position: "absolute",
- top: 120,
- left: 80,
- right: 80,
- bottom: 160,
- display: "flex",
- flexDirection: "column",
- justifyContent: "center",
- gap: 32,
- overflow: "hidden",
- }}
- >
- <AnimatedText
- text={visualText}
- fontSize={44}
- color="white"
- fontWeight={600}
- delay={5}
- />
- {scene.keyframes.length > 0 && (
- <KeyPointCard
- points={scene.keyframes
- .filter((kf) => kf.type === "text" || kf.type === "highlight")
- .map((kf) => kf.content)}
- color={colors.primaryLight}
- />
- )}
- </div>
- {scene.wordTimestamps.length > 0 && (
- <SubtitleBar wordTimestamps={scene.wordTimestamps} />
- )}
- <Watermark text={channelName} />
- </AbsoluteFill>
- );
- };
- export default KnowledgeScene;
|