Remotion LabRemotion Lab
其他React Native

React Native

在 React Native 應用程式中使用 Remotion 概念與工具的說明。

React Native

Remotion 是專為 Web 瀏覽器環境設計的影片製作工具,但它的某些概念和工具可以延伸至 React Native 的開發場景。本文說明 Remotion 與 React Native 的關係,以及可以共用的技術。

Remotion 與 React Native 的差異

Remotion 和 React Native 雖然都基於 React,但它們的渲染目標完全不同:

特性RemotionReact Native
渲染環境Chromium 瀏覽器原生 iOS/Android 元件
輸出格式MP4、WebM、GIF 等影片行動應用程式
動畫引擎CSS 動畫、requestAnimationFrameReanimated、Animated API
佈局系統CSS(Flexbox、Grid)StyleSheet(Flexbox)

哪些功能在 React Native 中可用?

數學工具函式

interpolate()spring() 等純 JavaScript 函式可以在 React Native 中使用:

npm install remotion
// React Native 元件中
import { interpolate, spring } from "remotion";
 
// interpolate 可用於計算數值映射
const opacity = interpolate(scrollY, [0, 200], [1, 0], {
  extrapolateLeft: "clamp",
  extrapolateRight: "clamp",
});

但請注意,useCurrentFrame()useVideoConfig() 這些 Hook 依賴 Remotion 的 React Context,在 React Native 環境中無法直接使用。

顏色插值

import { interpolateColors } from "remotion";
 
// 在手勢動畫中計算顏色
const backgroundColor = interpolateColors(
  gestureProgress, // 0 到 1
  [0, 1],
  ["#ffffff", "#000000"]
);

Remotion Player 在 React Native 中

Remotion Player 目前不支援 React Native。 @remotion/player 依賴 DOM API,無法在 React Native 的原生環境中運作。

若你需要在 React Native 應用中播放由 Remotion 生成的影片,可以使用:

// React Native
import Video from "react-native-video";
 
function RemotionVideoPlayer() {
  return (
    <Video
      source={{ uri: "https://cdn.example.com/remotion-output.mp4" }}
      style={{ width: "100%", aspectRatio: 16 / 9 }}
      controls
    />
  );
}

在 React Native 應用中觸發 Remotion 渲染

透過 API 呼叫,React Native 應用可以觸發伺服器端的 Remotion 渲染:

// React Native 呼叫渲染 API
async function generatePersonalizedVideo(userProps: UserProps) {
  const response = await fetch("https://api.example.com/render", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      compositionId: "PersonalizedVideo",
      inputProps: userProps,
    }),
  });
 
  const { videoUrl } = await response.json();
  return videoUrl;
}

伺服器端(Node.js)處理渲染:

// 伺服器端
import { renderMedia, selectComposition } from "@remotion/renderer";
import { bundle } from "@remotion/bundler";
 
app.post("/render", async (req, res) => {
  const { compositionId, inputProps } = req.body;
 
  const bundleUrl = await bundle({ entryPoint: "./src/index.ts" });
 
  const composition = await selectComposition({
    serveUrl: bundleUrl,
    id: compositionId,
    inputProps,
  });
 
  await renderMedia({
    composition,
    serveUrl: bundleUrl,
    codec: "h264",
    outputLocation: `out/${Date.now()}.mp4`,
    inputProps,
  });
 
  res.json({ videoUrl: "https://cdn.example.com/output.mp4" });
});

使用 Expo 與 Remotion

若使用 Expo 開發 React Native 應用,可以考慮以下架構:

[Expo App]
    ↓ 觸發渲染請求
[Remotion Lambda / 渲染 API]
    ↓ 生成影片
[S3 / CDN]
    ↓ 提供影片 URL
[Expo App 播放]
// Expo 應用中的完整流程
import { useState } from "react";
import { Button, Text, View } from "react-native";
import Video from "expo-video";
 
export default function App() {
  const [videoUrl, setVideoUrl] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);
 
  async function handleGenerate() {
    setLoading(true);
    try {
      const response = await fetch("https://api.example.com/render", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ name: "小明", theme: "birthday" }),
      });
      const { videoUrl } = await response.json();
      setVideoUrl(videoUrl);
    } finally {
      setLoading(false);
    }
  }
 
  return (
    <View>
      <Button title="生成個人化影片" onPress={handleGenerate} disabled={loading} />
      {loading && <Text>渲染中...</Text>}
      {videoUrl && (
        <Video
          source={{ uri: videoUrl }}
          style={{ width: 320, height: 180 }}
        />
      )}
    </View>
  );
}

共用動畫邏輯

若你同時維護 Remotion 影片和 React Native 應用,可以將動畫計算邏輯抽取為共用的純函式:

// shared/animations.ts(可在 Remotion 和 React Native 共用)
export function calculateFadeIn(progress: number): number {
  return Math.min(1, progress * 2);
}
 
export function calculateSlideUp(
  progress: number,
  distance: number = 100
): number {
  return (1 - progress) * distance;
}
// Remotion 中使用
import { calculateFadeIn } from "../shared/animations";
const opacity = calculateFadeIn(frame / 30);
 
// React Native 中使用(搭配 Animated API)
import Animated from "react-native-reanimated";
const opacity = calculateFadeIn(animatedValue.value);

小結

  • Remotion 目前不直接支援 React Native 渲染。
  • 純 JavaScript 的工具函式(如 interpolatespring)可以在 React Native 中使用。
  • 典型的整合模式是:React Native 觸發渲染請求,伺服器執行 Remotion 渲染,再將影片 URL 回傳給應用程式播放。
  • 可以將動畫計算邏輯抽取為純函式,在兩個平台之間共用。