Spaces:
Running
Running
| import { Meta, Transcript } from "common-utils"; | |
| import { Audio, Img, spring, staticFile, useCurrentFrame } from "remotion"; | |
| import * as Montserrat from "@remotion/google-fonts/Montserrat"; | |
| import { MediaBackground } from "../youtube/MediaBackground"; | |
| import { ErrorMsg } from "../common/Error"; | |
| import { RenderUtils } from "../RenderUtils"; | |
| export default function IG2LineMotivationalScene(props: { meta: Meta; item: Transcript }) { | |
| const { meta, item: transcript } = props; | |
| const { fps } = meta; | |
| const { mediaAbsPaths, audioFullPath, audioStartOffsetSec, durationInSeconds } = transcript; | |
| const media = mediaAbsPaths[0]; | |
| const watermark = mediaAbsPaths[1]; | |
| const bgMusicPath = RenderUtils.tryStaticFile(audioFullPath); | |
| const { fontFamily } = Montserrat.loadFont("normal", { | |
| weights: ["400"], | |
| ignoreTooManyRequestsWarning: true | |
| }); | |
| const frame = useCurrentFrame(); | |
| const scale = spring({ fps, frame }); | |
| const baseStyle = { | |
| textAlign: 'center', | |
| borderColor: "transparent", | |
| borderRadius: "2rem", | |
| borderLeftWidth: "4px", | |
| borderRightWidth: "4px", | |
| color: "#fff", | |
| textShadow: "0px 0px 50px #000, 0px 0px 50px #000", | |
| padding: "0.2rem 1.5rem", | |
| }; | |
| const highlightStyle = { | |
| backgroundColor: "#FFFF00", | |
| color: "#fff", | |
| textShadow: "0px 0px 50px #000, 0px 0px 50px #000", | |
| borderStyle: "solid", | |
| }; | |
| const audioCaption = transcript.audioCaption | |
| if (!audioCaption) { | |
| return ( | |
| <ErrorMsg> | |
| Missing `audioCaption` in transcript item {`[${transcript.title || transcript.index}]`} | |
| </ErrorMsg> | |
| ) | |
| } | |
| let line1 = audioCaption.words[0] | |
| let line2 = audioCaption.words[1] | |
| let line2String = line2.word | |
| let line2Opacity = 0 | |
| let line2animStartFrame = line2.start * fps; | |
| let line2animEndFrame = line2.end * fps; | |
| if (frame > line2animStartFrame) { | |
| line2Opacity = Math.min( | |
| 1, | |
| (frame - line2animStartFrame) / (line2animEndFrame - line2animStartFrame) | |
| ); | |
| } | |
| let watermarkPath; | |
| if (watermark) { | |
| watermarkPath = staticFile(watermark.path) | |
| } | |
| let watermarkText = audioCaption.words[2] | |
| let watermarkOpacity = 0 | |
| if (watermarkText) { | |
| let watermarkanimStartFrame = watermarkText.start * fps; | |
| let watermarkanimEndFrame = watermarkText.end * fps; | |
| if (frame > line2animStartFrame) { | |
| watermarkOpacity = Math.min( | |
| 1, | |
| (frame - watermarkanimStartFrame) / (watermarkanimEndFrame - watermarkanimStartFrame) | |
| ); | |
| } | |
| } | |
| let audioStartFrom = fps * (audioStartOffsetSec || 0) | |
| return ( | |
| <> | |
| <MediaBackground | |
| direction="none" | |
| emphasisOnImage={true} | |
| duration={fps * durationInSeconds} | |
| bgImagePaths={[{ path: media.path! }]} | |
| > | |
| {audioFullPath && <Audio src={bgMusicPath} startFrom={audioStartFrom} />} | |
| <div | |
| className="p-6 rounded-lg" | |
| style={{ | |
| width: "100%", | |
| height: "100%", | |
| display: "flex", | |
| flexDirection: "column", | |
| justifyContent: "center", | |
| alignItems: "center", | |
| alignContent: "center", | |
| flex: 1, | |
| }} | |
| > | |
| <span | |
| style={{ | |
| ...baseStyle, | |
| fontFamily, | |
| fontSize: 42, | |
| ...line1.textStyle | |
| } as any} | |
| > | |
| {line1.word} | |
| </span> | |
| <span | |
| style={{ | |
| ...baseStyle, | |
| fontFamily, | |
| fontSize: 42, | |
| opacity: line2Opacity, | |
| color: highlightStyle.color, | |
| ...line2.textStyle | |
| } as any} | |
| > | |
| {line2.word} | |
| </span> | |
| </div> | |
| { | |
| watermarkPath && ( | |
| <Img src={watermarkPath} | |
| style={{ | |
| width: '50%', | |
| ...audioCaption.words[2]?.textStyle, | |
| opacity: watermarkOpacity ?? 1 | |
| }} /> | |
| ) | |
| } | |
| </MediaBackground> | |
| </> | |
| ); | |
| } |