
remotion/vercel在 Vercel Sandbox 中渲染 Remotion 視頻的完整技術解析【免費下載鏈接】remotion Make videos programmatically with React項目地址: https://gitcode.com/GitHub_Trending/re/remotion本文圍繞 Remotion 倉庫中的remotion/vercel包packages/vercel/README.md展開講解如何在 Vercel Sandbox 中創(chuàng)建渲染環(huán)境、上傳項目 Bundle、執(zhí)行視頻/靜幀渲染、跟蹤進度并把產物上傳到 Vercel Blob 的完整鏈路所有結論均基于倉庫內 packages/vercel/src/index.ts 等源碼。包定位與公開 APIremotion/vercel的官方定位是“Render Remotion videos on Vercel Sandbox”在 Vercel Sandbox 上渲染 Remotion 視頻當前倉庫內版本為4.0.521License 為 Remotion License見 packages/vercel/package.json。它依賴remotion/renderer與remotion并以vercel/sandbox 1.0.0作為 peer dependency開發(fā)中固定使用1.6.0配套vercel/blob2.3.0。從 src/index.ts 的導出清單看該包對外暴露 6 個運行時 API 和一批類型導出類型作用createSandbox函數創(chuàng)建一個安裝好系統(tǒng)依賴、JS 依賴、headless 瀏覽器與渲染腳本的沙箱addBundleToSandbox函數把本地remotion bundle產物遞歸上傳進沙箱renderMediaOnVercel函數在沙箱內渲染視頻支持常規(guī)與 detached 兩種模式renderStillOnVercel函數在沙箱內渲染單幀靜圖getRenderProgress函數輪詢 detached 渲染任務的文件式進度uploadToVercelBlob函數把沙箱內產物上傳到 Vercel Blob返回 URL類型導出typeVercelSandbox、RenderProgress、VercelBlobUploadOptions、ChromiumOptions、Codec等大部分自 types.ts 與remotion/renderer再導出安裝與版本約束README 給出的安裝方式npm install remotion/vercel --save-exact兩條必須遵守的版本約束來自 README 與 package.json所有remotion與remotion/*包必須對齊同一版本需去掉版本號前的^使用精確版本vercel/sandbox是 peer dependency調用方需自行安裝1.0.0。另外從沙箱初始化邏輯看包內渲染腳本由構建產物generated/*-script注入包內部通過remotion/version讀取版本號在沙箱內以精確版本安裝remotion/rendererVERSION與remotion/compositor-linux-x64-gnuVERSION見 internals/install-js-dependencies.ts也就是說沙箱內的渲染器版本永遠與本地remotion/vercel版本一致這也是“版本必須對齊”這條約束的底層原因。createSandbox一步準備一個可渲染沙箱createSandbox是整個流程的入口完整實現在 src/create-sandbox.ts。簽名與默認值createSandbox({ onProgress?, // (update: {progress, message}) void | Promisevoid resources {vcpus: 4}, // Vercel Sandbox 的 resources 參數默認 4 vCPU timeoutInMilliseconds 5 * 60 * 1000, // 沙箱創(chuàng)建/初始化超時默認 5 分鐘 } {})它返回VercelSandbox——即Sandbox AsyncDisposable定義見 types.ts意味著可以用await using語法自動停止沙箱創(chuàng)建時通過 internals/disposable.ts 給沙箱掛了[Symbol.asyncDispose]dispose 時調用sandbox.stop()。沙箱的準備工作按兩個加權階段推進onProgress的進度權重系統(tǒng)依賴 75%、下載瀏覽器 25%創(chuàng)建沙箱runtime: node24即 Node 24 運行時安裝系統(tǒng)依賴75%通過sudo dnf install安裝 headless Chromium 在 Amazon Linux 2023 上運行所需的一組庫nss、atk、at-spi2-atk、cups-libs、libdrm、libXcomposite、libXdamage、libXrandr、mesa-libgbm、alsa-lib、pango、gtk3以及補丁工具鏈patchelf、zstd、binutils見 internals/install-system-dependencies.ts。進度是通過統(tǒng)計命令 stdout 行數源碼注釋說明經驗值為 272 行線性估算的安裝 JS 依賴在沙箱內執(zhí)行pnpm i remotion/renderer remotion/compositor-linux-x64-gnu vercel/blob版本鎖定為當前包版本修補 compositorVercel Sandbox 的 Amazon Linux 2023 自帶 glibc 2.34而 Remotion 的 compositor 二進制要求 glibc 2.35。internals/patch-compositor.ts 會下載 Ubuntu 22.04 的libc6 2.35deb 包主源為 Launchpad備用源為 remotion.media解壓后用patchelf把remotion二進制的動態(tài)鏈接指向捆綁的 glibc。源碼注釋明確指出Remotion 并不官方支持 glibc 2.34但可以通過這種方式打補丁且只有remotion二進制需要修補ffmpeg/ffprobe在 glibc 2.34 下工作正常下載 headless 瀏覽器25%寫入并執(zhí)行ensure-browser.mjs以 JSON 日志形式回報browser-progress百分比見 internals/install-browser.ts寫入渲染腳本向沙箱寫入package.json{type: module}以及render-video.mjs、render-still.mjs、upload-blob.mjs三個腳本后續(xù)渲染命令直接調用它們。addBundleToSandbox上傳項目 Bundle渲染前需要把npx remotion bundle生成的靜態(tài)產物傳進沙箱。src/add-bundle-to-sandbox.ts 的addBundleToSandbox({sandbox, bundleDir})行為如下遞歸讀取bundleDir下所有文件統(tǒng)一轉成 POSIX 分隔路徑先在沙箱內按祖先目錄逐一mkDir再批量writeFiles上傳所有文件統(tǒng)一放在沙箱內的remotion-bundle/目錄下常量REMOTION_SANDBOX_BUNDLE_DIR見 internals/add-bundle.ts。渲染時瀏覽器加載的 URL 因此固定為/vercel/sandbox/remotion-bundle目錄創(chuàng)建或文件上傳失敗時經由 internals/format-sandbox-error.ts 重新拋出帶操作上下文如“upload N bundle file(s)”的錯誤便于定位。renderMediaOnVercel渲染視頻完整實現在 src/render-media-on-vercel.ts。這是一個通過重載區(qū)分兩種模式的函數常規(guī)模式detached缺省或false阻塞等待渲染結束返回{sandboxFilePath, contentType}產物留在沙箱文件系統(tǒng)中等待后續(xù)uploadToVercelBlobdetached 模式detached: true必須同時提供vercelBlob: {blobToken, access, blobPath?}立即返回{sandboxId, cmdId, outputFile}由沙箱后臺繼續(xù)渲染并用getRenderProgress輪詢結果。完整參數與默認值以下參數表全部來自源碼中解構默認值參數默認值說明sandbox必填createSandbox返回的沙箱實例compositionId必填目標 Composition 的 idinputProps必填傳給 Composition 的 propsoutputFile/tmp/video.mp4沙箱內輸出路徑codech264視頻編碼類型Codec自remotion/renderer再導出crfnull恒定質量因子imageFormat/pixelFormatnull幀圖像格式與像素格式envVariables{}注入渲染進程的環(huán)境變量frameRangenull只渲染指定幀區(qū)間everyNthFrame1抽幀渲染步長proResProfilenullProRes 檔位chromiumOptions{}附加 Chromium 啟動參數scale1輸出縮放比例preferLosslessfalse偏好無損編碼enforceAudioTrackfalse強制包含音軌disallowParallelEncodingfalse禁止并行編碼concurrencynull并發(fā)幀數metadatanull寫入容器的元數據licenseKeynullRemotion 企業(yè)授權密鑰videoBitrate/audioBitrate/encodingMaxRate/encodingBufferSizenull碼率相關類型Bitratemutedfalse靜音輸出numberOfGifLoopsnullGIF 循環(huán)次數x264Preset/gopSizenullH.264 預設與 GOP 大小colorSpacedefault色彩空間jpegQuality80JPEG 幀質量audioCodecnull音頻編碼logLevelinfo日志級別timeoutInMilliseconds30000瀏覽器/Composition 打開超時forSeamlessAacConcatenationfalseAAC 無縫拼接separateAudioTonull單獨輸出音頻文件路徑hardwareAccelerationdisable硬件加速開關沙箱環(huán)境默認關閉offthreadVideoCacheSizeInBytes/mediaCacheSizeInBytes/offthreadVideoThreadsnull離屏視頻緩存與線程sampleRate48000音頻采樣率detachedfalse是否后臺渲染detachedSandboxTimeoutInMilliseconds30 * 60 * 1000detached 模式下沙箱超時延長時長30 分鐘底層執(zhí)行方式函數把上述參數組裝成renderConfig其中強制寫死了幾個與本地渲染不同的字段chromeMode: headless-shell、browserExecutable: null、binariesDirectory: null、repro: false以及serveUrl: /vercel/sandbox/remotion-bundle。隨后const renderCmd await sandbox.runCommand({ cmd: node, args: [render-video.mjs, JSON.stringify(renderConfig)], detached: true, env: vercelBlob ? {BLOB_READ_WRITE_TOKEN: vercelBlob.blobToken} : undefined, });即把整個渲染配置作為 JSON 傳給沙箱內的render-video.mjs腳本腳本內部再調用remotion/renderer完成渲染并以 JSON 行形式把進度打到 stdout。常規(guī)模式下客戶端逐行解析stdout日志非 JSON 的行直接忽略把opening-browser、selecting-composition、render-progress三個階段透傳給onProgress最后wait()等待命令結束退出碼非 0 時拋出Render failed: stderr stdout。detached 模式則先sandbox.extendTimeout(detachedSandboxTimeoutInMilliseconds)延長沙箱壽命然后立即返回{sandboxId, cmdId, outputFile}供后續(xù)輪詢。renderStillOnVercel渲染靜幀實現在 src/render-still-on-vercel.ts參數更精簡參數默認值outputFile/tmp/still.pngframe0imageFormatpng類型StillImageFormatjpegQuality80scale1logLevelinfotimeoutInMilliseconds30000chromiumOptions/envVariables{}/{}offthreadVideoCacheSizeInBytes/mediaCacheSizeInBytes/offthreadVideoThreads/licenseKey均可選執(zhí)行方式與視頻渲染一致node render-still.mjs jsonConfig同樣以 JSON 行協(xié)議回報opening-browser、selecting-composition、done攜帶size與contentType成功返回{sandboxFilePath, contentType}。getRenderProgress輪詢 detached 任務detached 模式下的進度追蹤實現在 src/get-render-progress.ts。它不依賴命令句柄而是按“文件 命令狀態(tài)”雙通道讀取Sandbox.get({sandboxId})重新附著沙箱失敗即返回{stage: expired}sandbox.getCommand(cmdId)獲取渲染命令對象識別sandbox_stopped一類錯誤碼同樣歸為expired讀取沙箱內固定路徑/vercel/sandbox/progress.json沙箱內渲染腳本把最新進度寫在這里文件不存在且命令尚未退出時返回{stage: starting, overallProgress: 0}文件存在但命令退出碼非 0 時收集stderr/stdout組裝錯誤信息返回error。返回值是聯合類型RenderProgresstypes.ts覆蓋完整生命周期starting → opening-browser → selecting-composition → render-progress → (detached 時沙箱內自動) uploading → done | error | expired其中done攜帶{url, size, contentType, overallProgress}——detached 模式下沙箱內的渲染腳本會使用BLOB_READ_WRITE_TOKEN直接把產物上傳到 Vercel Blob因此done里的url就是可直接下載的產物地址。uploadToVercelBlob上傳產物到 Blob常規(guī)模式渲染完產物只存在于沙箱文件系統(tǒng)中需要顯式上傳。src/upload-to-vercel-blob.ts 的uploadToVercelBlob({sandbox, sandboxFilePath, blobPath?, contentType, blobToken, access})blobPath缺省時自動生成renders/{uuid}{原文件擴展名}在沙箱內執(zhí)行node upload-blob.mjs jsonConfig沙箱內已裝好vercel/blobSDK從 stdout 的type: doneJSON 消息中取回{url, size}access為public | private類型VercelBlobAccess。典型端到端工作流把上述 API 串起來一個完整的服務端渲染流程大致如下基于倉庫內各函數的真實簽名編寫import { addBundleToSandbox, createSandbox, renderMediaOnVercel, uploadToVercelBlob, } from remotion/vercel; // 1. 創(chuàng)建并初始化沙箱可 await using 自動清理 await using sandbox await createSandbox({ onProgress: ({progress, message}) console.log(progress, message), resources: {vcpus: 4}, }); // 2. 上傳 npx remotion bundle 的產物如 out/remotion await addBundleToSandbox({sandbox, bundleDir: out/remotion}); // 3. 渲染視頻常規(guī)模式 const {sandboxFilePath, contentType} await renderMediaOnVercel({ sandbox, compositionId: MyComp, inputProps: {title: Hello}, codec: h264, scale: 1, onProgress: ({stage, overallProgress}) console.log(stage, overallProgress), }); // 4. 上傳到 Vercel Blob 并拿到 URL const {url, size} await uploadToVercelBlob({ sandbox, sandboxFilePath, contentType, blobToken: process.env.BLOB_READ_WRITE_TOKEN!, access: public, }); console.log(url, size);長任務或需要跨進程追蹤時改用 detached 模式const {sandboxId, cmdId, outputFile} await renderMediaOnVercel({ sandbox, compositionId: MyComp, inputProps: {title: Hello}, detached: true, vercelBlob: { blobToken: process.env.BLOB_READ_WRITE_TOKEN!, access: public, blobPath: renders/hello.mp4, }, }); // 在任意時機甚至另一個進程中輪詢 const progress await getRenderProgress({sandboxId, cmdId}); // progress.stage: starting | opening-browser | ... | done | expired適用前提與限制綜合源碼可以歸納出該包的使用前提與限制部署前需要確認平臺假設沙箱初始化腳本圍繞node24運行時 Amazon Linux 2023dnf包管理、glibc 2.34 補丁路徑編寫compositor 修補邏輯只處理node_modules/remotion/compositor-linux-x64-gnu即當前實現面向 Linux x64 沙箱環(huán)境瀏覽器固定為 headless-shellrenderConfig中chromeMode被硬編碼為headless-shell且browserExecutable、binariesDirectory恒為null無法指定自托管 Chromiumdetached 模式強依賴 Vercel Blobdetached: true時缺少vercelBlob會直接拋錯The vercelBlob option is required when detached is set to true.且沙箱默認只自動延長 30 分鐘超時DEFAULT_DETACHED_SANDBOX_TIMEOUT超長渲染需自行調大detachedSandboxTimeoutInMilliseconds版本一致性是硬約束沙箱內渲染器版本取自本地remotion/version本地remotion/remotion/*版本不一致會導致行為不確定因此 README 要求所有包使用--save-exact的同一版本。小結remotion/vercel把“打包 → 沙箱環(huán)境準備 → 渲染 → 產物分發(fā)”拆成了 6 個職責單一、可組合的 APIcreateSandbox負責一個開箱即用的 Node 24 渲染沙箱含系統(tǒng)依賴、glibc 2.35 補丁與 headless-shell 下載addBundleToSandbox負責 Bundle 分發(fā)renderMediaOnVercel/renderStillOnVercel負責以 JSON 配置驅動的無頭渲染getRenderProgress與uploadToVercelBlob分別覆蓋異步進度追蹤與產物上傳。對于需要在無狀態(tài)云端按需生成視頻的 Remotion 項目這是一條不依賴長期 GPU 實例的輕量渲染路徑實現細節(jié)可直接在 packages/vercel/src/ 下按上述文件名查閱?!久赓M下載鏈接】remotion Make videos programmatically with React項目地址: https://gitcode.com/GitHub_Trending/re/remotion創(chuàng)作聲明:本文部分內容由AI輔助生成(AIGC),僅供參考