חזרה לבלוג

איך בניתי מערכת רנדור וידאו ב-React

·3 דקות קריאה

הבעיה עם וידאו

הייתי צריך סרטוני פרומו לשלושה מותגים. ShawnOS, GTMOS, ContentOS. כל אחד דרש שלושה יחסי גובה-רוחב - LinkedIn (4:5), Reels (9:16), לרוחב (16:9). זה תשעה יעדי רנדור. וכל פעם שטוקנים העיצוביים השתנו, כל סרטון היה צריך להתעדכן.

בדקתי תבניות After Effects. בדקתי Canva. בדקתי לשכור מישהו. כל אפשרות הייתה צינור ידני שהיה יוצא מסנכרון עם האתרים ברגע שהייתי דוחף שינוי צבע.

לאתרים כבר היה מערכת העיצוב. שכבת הנתונים. טוקנים של המותג. מה אם הסרטונים יחיו באותו קודבייס?

Remotion והיתרון של מונוריפו

Remotion הופך קומפוננטות React לפריימים של וידאו. כותבים JSX. הוא מרנדר כל פריים ב-30fps. מקבלים MP4. לא צריך GPU. לא עורך ציר זמן. רק קוד.

התובנה המרכזית הייתה לשים את אפליקציית הוידאו בתוך מונוריפו ה-Turborepo הקיים ב-website/apps/video/. אותו חבילת @shawnos/shared שמפעילה את שלושת האתרים. אותם טוקנים עיצוביים. אותה פלטת צבעים. כשאני משנה ערך hex בחבילה המשותפת, האתרים והסרטונים כולם מתעדכנים בבילד הבא.

תשע קומפוזיציות חיות ב-Root.tsx אחד. שלושה מותגים כפול שלושה יחסי גובה-רוחב. הוק useScale() מנרמל הכל לבסיס של 1080x1350 ומשנה קנה מידה פרופורציונלית. עץ קומפוננטות אחד מרנדר בכל גודל.

ארכיטקטורת הסצנות

סרטונים בנויים מסצנות שמחוברות על ידי TransitionSeries - כלי ההרכבה של Remotion שמטפל בתזמון חפיפה בין מקטעים. כל סצנה היא קומפוננטת React עם מספר פריימים קבוע.

מערכת V3 הנוכחית רצה כ-10 שניות ב-30fps (310 פריימים סה"כ):

  • Hook (36 פריימים / 1.2 שניות) - הפתיח שתופס תשומת לב
  • BootWikiBlitz (110 פריימים / 3.7 שניות) - רצף אתחול טרמינל עם כרטיסי ויקי מהירים
  • Progression (100 פריימים / 3.3 שניות) - ויזואליזציה של מערכת השכבות בסגנון RPG
  • CtaNetwork (94 פריימים / 3.1 שניות) - קריאה לפעולה עם גרף רשת

מעברים מקבלים 10 פריימים של חפיפה בין סצנות. תצורת התזמון חיה ב-timing-v2.ts - קובץ אחד שולט בקצב של הסרטון כולו.

ספריית הקומפוננטות

שלוש קומפוננטות עושות את רוב העבודה הוויזואלית.

MatrixRain משתמש ברעש Perlin מ-@remotion/noise כדי לייצר אפקט גשם תווים דטרמיניסטי. כל עמודה נעה באופן עצמאי. בחירת התווים מוזנת על ידי עמודה, שורה, ומספר פריים. האפקט אורגני אבל ניתן לשחזור - אותו seed, אותו פלט, בכל רנדור.

TypewriterText חושף תווים פריים אחרי פריים עם סמן מהבהב. פריימים שחלפו שולטים בכמות התווים הנראים. הסמן מהבהב ב-1Hz. מתמטיקה פשוטה, אפקט נקי.

ParticleField יוצר חלקיקים צפים אמביינטיים באמצעות שני זרמי רעש עצמאיים לסחיפת x ו-y. 40 חלקיקים כברירת מחדל, מוגבלים ל-8% סחיפת קנבס. פעימה עדינה דרך ערוץ רעש שלישי.

כל שלוש הקומפוננטות דטרמיניסטיות. בלי Math.random(). Remotion דורש את זה - ערכים אקראיים משתנים בין פריימים ושוברים את הרנדור. רעש Perlin עם seeds עקביים נותן אנימציה אורגנית שניתנת לשחזור.

הטיפול הוויזואלי

כל סצנה עטופה ב-SceneWrapper שמחיל טיפול וויזואלי עקבי:

  • רקע קנבס כהה (#0D1117)
  • וינייטה רדיאלית (החשכת קצוות)
  • שטיפת צבע מבטא ב-3% שקיפות
  • רעש אמביינטי של שדה חלקיקים
  • גרגור פילם דרך SVG feTurbulence
  • שכבת קווי סריקה (אסתטיקת CRT)

התוצאה נראית כמו וידאו טרמינלי מקורי. מתאים למותג ShawnOS בלי שום עיבוד-אחרי ידני.

טוקנים עיצוביים בקוד

מערכת הטוקנים חיה ב-tokens.ts:

canvas:  #0D1117
green:   #4EC373  (ShawnOS)
teal:    #3DBFA0  (GTMOS)
purple:  #9B72CF  (ContentOS)
amber:   #D2A53C  (secondary accent)

SITE_ACCENTS ממפה שמות מותגים לצבעים. סצנת BootWikiBlitz עוברת דרך הפלטה - ירוק, טיל, ענבר, סגול, ירוק - כשכרטיסי ויקי מתחלפים. זהות המותג בנתונים, לא מקודדת קשיח בקומפוננטות.

הפונט הוא JetBrains Mono בכל מקום. monospace. עקבי עם האסתטיקה הטרמינלית בכל שלושת האתרים.

רנדור

npm run render:all מייצר את כל תשע הגרסאות. Remotion מרנדר כל קומפוזיציה לפריימי JPEG, ואז מקודד ל-MP4. בלי תלויות חיצוניות מעבר למה שב-package.json. בלי חוות רנדור בענן. רץ על MacBook.

הפלטים המרונדרים הולכים ל-website/apps/video/out/ ונפרסים לתיקיית public/video/ של כל אתר. אינדקס התוכן ב-SQLite עוקב אחרי כל קבצי הוידאו, המותגים שלהם, יחסי הגובה-רוחב, וסטטוס הפריסה.

למה זה חשוב

מערכת הוידאו היא סוג תוכן שחי באותו קודבייס כמו כל סוג תוכן אחר. פוסטים בבלוג הם קבצי markdown. מונחי ידע הם אובייקטי TypeScript. סרטונים הם קומפוננטות React. כולם חולקים את אותם טוקנים עיצוביים, את אותה שכבת נתונים, את אותו צינור פריסה.

כשאני מוסיף קטגוריית ויקי חדשה, סצנת BootWikiBlitz יכולה להתייחס אליה. כשאני משנה את צבעי המותג, הסרטונים מתעדכנים. כשאני דוחף ל-main, הכל נפרס ביחד.

בלי כלים נפרדים. בלי ייצוא ידני. בלי בעיות סנכרון. המונוריפו הוא המערכת.

$ remotion render Root LeadMagnetV3 --codec=h264

ShawnOS.ai|theGTMOS.ai|theContentOS.ai
built with Next.js · Tailwind · Claude · Remotion