← GPT-AI-VIDEO
CODE · 12.4 KB

remotion/CorpRenewalShort.jsx

Workspace snapshot · 09/04 14:52

import React from "react";
import { AbsoluteFill, Audio, Easing, Img, Sequence, interpolate, spring, staticFile, useCurrentFrame, useVideoConfig } from "remotion";
import logo from "../assets/public/pengin-corp-renewal-2025/pengin-logo.svg";
import ueki from "../assets/public/pengin-corp-renewal-2025/ueki.png";
import suzuki from "../assets/public/pengin-corp-renewal-2025/suzuki.png";
import aihara from "../assets/public/pengin-corp-renewal-2025/aihara.png";
import directions from "../assets/public/pengin-corp-renewal-2025/design-directions.png";
import sitemap from "../assets/public/pengin-corp-renewal-2025/sitemap.png";
import wireframe from "../assets/public/pengin-corp-renewal-2025/wireframe-overview.png";
import shoot1 from "../assets/public/pengin-corp-renewal-2025/shoot-01.jpg";
import shoot3 from "../assets/public/pengin-corp-renewal-2025/shoot-03.jpg";
import shoot6 from "../assets/public/pengin-corp-renewal-2025/shoot-06.jpg";
import home from "../assets/public/pengin-corp-renewal-2025/site-home-vertical.png";
import hookKeyframe from "../assets/generated/pengin-corp-renewal/hook-keyframe-v1.png";

const blue = "#1757a6";
const navy = "#07162d";
const white = "#f7f6f1";
const orange = "#ff5d32";
const clamp = { extrapolateLeft: "clamp", extrapolateRight: "clamp" };
const ease = Easing.bezier(0.22, 1, 0.36, 1);
const fade = (f, a, b) => interpolate(f, [a, a + 10, b - 10, b], [0, 1, 1, 0], clamp);

const Texture = () => <AbsoluteFill style={{ pointerEvents: "none", opacity: 0.1, backgroundImage: "radial-gradient(#07162d 0.8px, transparent 0.8px)", backgroundSize: "9px 9px", mixBlendMode: "multiply" }} />;
const FrameLabel = ({ index, dark = false }) => <div style={{ position: "absolute", top: 46, left: 58, right: 58, display: "flex", justifyContent: "space-between", color: dark ? white : navy, fontFamily: "Arial, sans-serif", fontWeight: 800, fontSize: 18, letterSpacing: "0.16em", zIndex: 20 }}><span>PENGIN / PROCESS NOTE</span><span>0{index}</span></div>;
const Cut = ({ children, dark = false, index = 1 }) => <AbsoluteFill style={{ background: dark ? navy : white, color: dark ? white : navy, overflow: "hidden", fontFamily: '"Yu Gothic", "Hiragino Sans", sans-serif' }}><FrameLabel index={index} dark={dark} />{children}<Texture /></AbsoluteFill>;

const BigType = ({ children, style }) => <div style={{ fontWeight: 950, fontSize: 106, lineHeight: 0.96, letterSpacing: "-0.07em", wordBreak: "keep-all", ...style }}>{children}</div>;

const Opening = () => {
  const f = useCurrentFrame();
  const zoom = interpolate(f, [0, 110], [1.08, 1.18], clamp);
  return <Cut index={1}><Img src={hookKeyframe} style={{ position: "absolute", inset: -40, width: 1160, height: 2000, objectFit: "cover", transformOrigin: "center center", transform: `scale(${zoom})` }} /><div style={{ position: "absolute", inset: 0, background: "linear-gradient(180deg,rgba(7,22,45,0) 35%,rgba(7,22,45,.94) 88%)" }} /><div style={{ position: "absolute", left: 62, right: 62, bottom: 110, color: white, opacity: fade(f, 0, 120), transform: `translateY(${interpolate(f,[0,22],[90,0],{...clamp,easing:ease})}px)` }}><div style={{ fontSize: 31, fontWeight: 800, letterSpacing: ".04em", marginBottom: 24 }}>WEB制作会社が、</div><BigType>自社サイトを<br/>作ったら。</BigType></div></Cut>;
};

const Debate = () => {
  const f = useCurrentFrame();
  const people = [[aihara,"理念は譲れない"],[suzuki,"発信力を強く"],[ueki,"この会社、おもろそう"]];
  return <Cut index={2} dark><div style={{ position: "absolute", top: 170, left: 55, right: 55, display: "flex", gap: 12 }}>{people.map(([src,q],i)=>{const y=interpolate(f,[i*8,i*8+24],[100,0],{...clamp,easing:ease});return <div key={q} style={{ flex:1, transform:`translateY(${y}px)`, opacity:interpolate(f,[i*8,i*8+14],[0,1],clamp) }}><div style={{ height: 430, background: i===1?blue:white, overflow:"hidden" }}><Img src={src} style={{ width:"100%",height:"100%",objectFit:"cover",filter:"grayscale(1) contrast(1.1)" }}/></div><div style={{ marginTop:14,fontSize:25,lineHeight:1.25,fontWeight:900 }}>{q}</div></div>})}</div><div style={{ position:"absolute",left:60,right:60,bottom:125 }}><div style={{ fontFamily:"Arial",fontSize:25,fontWeight:800,color:orange,letterSpacing:".08em" }}>CONCEPT MEETING</div><BigType style={{marginTop:18}}>1か月、<br/>決まらない。</BigType></div></Cut>;
};

const DirectionWall = () => {
  const f = useCurrentFrame();
  const s = spring({frame:f,fps:30,config:{damping:18,stiffness:90}});
  return <Cut index={3}><div style={{ position:"absolute",top:180,left:44,right:44,height:700,background:white,border:`4px solid ${navy}`,boxShadow:"0 30px 80px rgba(7,22,45,.2)",transform:`scale(${.9+.1*s}) rotate(${interpolate(f,[0,120],[-2,1],clamp)}deg)`,overflow:"hidden" }}><Img src={directions} style={{width:"100%",height:"100%",objectFit:"contain"}}/></div><div style={{ position:"absolute",left:60,right:60,bottom:125 }}><div style={{ display:"flex",gap:12,marginBottom:34 }}>{["足跡","海","深海","キャンバス","無限"].map((x,i)=><span key={x} style={{padding:"10px 14px",background:i===2?orange:navy,color:white,fontWeight:900,fontSize:22}}>{x}</span>)}</div><BigType>出した案、<br/><span style={{color:blue}}>5方向。</span></BigType></div></Cut>;
};

const Wireframes = () => {
  const f = useCurrentFrame();
  const decision = interpolate(f, [18, 52], [0, 1], { ...clamp, easing: ease });
  const settle = spring({ frame: f, fps: 30, config: { damping: 18, stiffness: 85 } });
  const opinions = ["理念は譲れない", "発信力を強化", "この会社おもろそう"];
  return <Cut index={4} dark>
    <div style={{ position: "absolute", left: 58, right: 58, top: 160, display: "flex", gap: 12, zIndex: 5 }}>
      {opinions.map((opinion, i) => <div key={opinion} style={{ flex: 1, padding: "15px 12px", background: i === 0 ? orange : white, color: i === 0 ? white : navy, fontSize: 20, fontWeight: 950, textAlign: "center", opacity: interpolate(f,[i*7,i*7+12],[0,1],clamp), transform: `translateY(${interpolate(f,[i*7,i*7+18],[30,0],clamp)}px)` }}>{opinion}</div>)}
    </div>
    {[190, 510, 830].map((left, i) => <div key={left} style={{ position: "absolute", left, top: 218, width: 4, height: 82, background: i === 0 ? orange : white, transformOrigin: "top center", transform: `rotate(${i === 0 ? -48 : i === 2 ? 48 : 0}deg) scaleY(${decision})`, opacity: .8, zIndex: 4 }} />)}
    <div style={{ position: "absolute", left: 58, right: 58, top: 270, height: 1040, background: white, overflow: "hidden", border: `6px solid ${white}`, boxShadow: "0 36px 90px rgba(0,0,0,.35)", transform: `translateY(${interpolate(settle,[0,1],[100,0])}px)` }}>
      <Img src={wireframe} style={{ width: 1700, height: 1040, objectFit: "cover", objectPosition: "left top", transform: `translateX(${interpolate(f,[0,110],[18,-45],clamp)}px) scale(1.03)` }} />
      <div style={{ position: "absolute", left: 35, top: 34, width: 510, height: 300, border: `12px solid ${orange}`, opacity: decision, boxShadow: `0 0 ${45*decision}px rgba(255,93,50,.38)` }} />
      <div style={{ position: "absolute", left: 575, top: 42, padding: "10px 16px", background: orange, color: white, fontSize: 22, fontWeight: 950 }}>ここだけは、譲らない。</div>
    </div>
    <div style={{ position: "absolute", left: 60, right: 60, bottom: 108 }}>
      <div style={{ fontSize: 27, fontWeight: 900, color: orange, marginBottom: 18 }}>TOPページのWFは約5案。</div>
      <BigType style={{ fontSize: 82 }}>先に決めたのは、<br/><span style={{ color: orange }}>譲らない言葉。</span></BigType>
    </div>
  </Cut>;
};

const Weekend = () => {
  const f = useCurrentFrame();
  return <Cut index={5}><div style={{ position:"absolute",inset:0 }}><Img src={shoot1} style={{position:"absolute",width:760,height:690,objectFit:"cover",left:-110,top:120,transform:`scale(${interpolate(f,[0,120],[1.05,1.13],clamp)})`}}/><Img src={shoot3} style={{position:"absolute",width:610,height:600,objectFit:"cover",right:-90,top:650,border:"12px solid white"}}/><Img src={shoot6} style={{position:"absolute",width:700,height:530,objectFit:"cover",left:-80,bottom:-30,border:"12px solid white"}}/><div style={{position:"absolute",inset:0,background:"linear-gradient(180deg,rgba(247,246,241,0) 45%,rgba(247,246,241,.94) 84%)"}}></div><div style={{position:"absolute",top:220,right:55,width:520,background:navy,color:white,padding:"34px 38px",transform:`translateX(${interpolate(f,[0,24],[180,0],{...clamp,easing:ease})}px)`}}><div style={{fontSize:28,fontWeight:800}}>「平日に時間とるの無理だ」</div></div><div style={{position:"absolute",top:420,right:80,width:500,background:orange,color:white,padding:"34px 38px",transform:`translateX(${interpolate(f,[15,40],[180,0],{...clamp,easing:ease})}px)`}}><div style={{fontSize:28,fontWeight:900}}>「土日に会社でやりますか」</div></div><BigType style={{position:"absolute",left:60,right:60,bottom:105,fontSize:82}}>自社のことほど、<br/>自分で決めにくい。</BigType></div></Cut>;
};

const Ranking = () => {
  const f = useCurrentFrame();
  const hit = interpolate(f,[42,53],[0,1],clamp);
  return <Cut index={6} dark><div style={{position:"absolute",top:270,left:60,right:60,opacity:1-hit,transform:`translateY(${-hit*80}px)`}}><div style={{fontSize:35,fontWeight:800,color:orange}}>決めたはずだった。</div><BigType style={{marginTop:28}}>これは、<br/>マーケ施策<br/>ではない。</BigType></div><div style={{position:"absolute",inset:0,display:"grid",placeItems:"center",opacity:hit,transform:`scale(${.7+.3*hit})`}}><div style={{textAlign:"center"}}><div style={{fontSize:29,fontWeight:900,letterSpacing:".08em"}}>「WEB制作会社 東京」</div><div style={{fontFamily:"Arial",fontSize:380,fontWeight:950,lineHeight:.9,color:orange,letterSpacing:"-.12em"}}>9<span style={{fontSize:100,color:white}}>位</span></div><div style={{fontSize:55,fontWeight:950,marginTop:35}}>悪あがき、開始。</div></div></div></Cut>;
};

const Build = () => {
  const f = useCurrentFrame();
  return <Cut index={7}><Img src={home} style={{position:"absolute",inset:0,width:"100%",height:"100%",objectFit:"cover",transform:"scale(1.14)",transformOrigin:"top center",filter:"contrast(1.05)"}}/><div style={{position:"absolute",inset:0,background:"linear-gradient(180deg,rgba(7,22,45,.1),rgba(7,22,45,.9))"}}/><div style={{position:"absolute",top:280,left:60,right:60,color:white}}><div style={{fontFamily:"Arial",fontSize:38,fontWeight:900,color:orange}}>three.js / 1 WEEK</div><BigType style={{marginTop:22}}>「全然<br/>できません」</BigType><div style={{marginTop:55,width:"fit-content",padding:"24px 30px",background:white,color:navy,fontSize:32,fontWeight:950,transform:`translateX(${interpolate(f,[55,80],[700,0],{...clamp,easing:ease})}px)`}}>AIに聞きながら、やるか。</div></div></Cut>;
};

const Ending = () => {
  const f = useCurrentFrame();
  return <Cut index={8} dark><div style={{position:"absolute",top:0,left:0,right:0,height:740,overflow:"hidden"}}><Img src={shoot1} style={{width:"100%",height:"100%",objectFit:"cover",filter:"grayscale(1) contrast(1.15)",transform:`scale(${interpolate(f,[0,120],[1.05,1.14],clamp)})`}}/><div style={{position:"absolute",inset:0,background:"linear-gradient(180deg,transparent,rgba(7,22,45,1))"}}/></div><div style={{position:"absolute",left:60,right:60,top:770}}><div style={{width:110,height:14,background:orange,marginBottom:48}}/><BigType>制約を、<br/><span style={{color:orange}}>ワクワクへ。</span></BigType><div style={{marginTop:105,display:"flex",alignItems:"center",justifyContent:"space-between"}}><Img src={logo} style={{width:250,filter:"brightness(0) invert(1)"}}/><div style={{fontFamily:"Arial",fontSize:20,fontWeight:800,letterSpacing:".12em",textAlign:"right"}}>CORPORATE RENEWAL<br/>2025.12.25</div></div></div></Cut>;
};

export const CorpRenewalShort = () => <AbsoluteFill style={{background:navy}}>
  <Audio src={staticFile("pengin-editorial-beat.wav")} volume={0.75} />
  <Sequence from={0} durationInFrames={120}><Opening/></Sequence>
  <Sequence from={105} durationInFrames={120}><Debate/></Sequence>
  <Sequence from={210} durationInFrames={120}><DirectionWall/></Sequence>
  <Sequence from={315} durationInFrames={120}><Wireframes/></Sequence>
  <Sequence from={420} durationInFrames={120}><Weekend/></Sequence>
  <Sequence from={525} durationInFrames={120}><Ranking/></Sequence>
  <Sequence from={630} durationInFrames={120}><Build/></Sequence>
  <Sequence from={735} durationInFrames={165}><Ending/></Sequence>
</AbsoluteFill>;