npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@vvfx/export-media

v0.0.1-beta.20261103.9ec4c789

Published

浏览器端 Galacean Effects 场景媒体导出工具,支持 MP4、GIF、APNG、WebP、WebM、PNG 序列帧及 AlphaMaskVideo。

Readme

@vvfx/export-media

浏览器中的 Galacean Effects 场景媒体导出工具。当前版本 0.0.1-alpha.0,输入 JSONScene,可生成 MP4、GIF、APNG、动画 WebP、WebM、PNG 序列帧 ZIP 和 AlphaMaskVideo。

更新记录见 CHANGELOG。

安装

npm install @vvfx/export-media

包发布在 npm 官方源,0.0.1-alpha.0 为 alpha 预览版本,安装时可按需追加 @0.0.1-alpha.0 或 -alpha 标签。本包为浏览器端工具;运行环境要求见文末部署前提。

开发与验证

以下命令在已安装依赖的完整仓库根目录执行,开发环境要求 Node.js >= 22.12.0、pnpm >= 10。npm 安装包只包含构建产物和使用说明,不包含测试源码与配置。

# SDK 构建
pnpm --filter @vvfx/export-media build

发布校验

本包与 @vvfx/artis 一样配置为发布到 npm 官方源,访问级别为 public。发布前执行上面的构建命令。

files 只包含 dist,npm 自动包含 README 与 package.json。

使用方式

发布产物的 ESM / CJS 入口首次执行时,会通过 console.info 显示包版本,例如:

[@vvfx/export-media] v0.0.1-alpha.0

提示由构建配置自动读取版本信息,同一模块重复导入不会重复打印。源码开发入口、仅类型导入,以及被宿主打包器移除的导入不会触发提示;宿主若配置删除 console,也会移除提示。Artis 将 Effects 及其插件作为外部依赖,本包仍内嵌 runtime;宿主覆盖依赖版本或通过 CDN 加载 runtime 时,仍需确保版本与包声明一致。

import { Exporter } from '@vvfx/export-media';
import type { ExportItemParams, FileBuffer } from '@vvfx/export-media';

// 在浏览器中调用,传入合法的 Galacean Effects JSONScene。
export async function exportMp4 (scene: ExportItemParams['scene']): Promise<Blob> {
  const exporter = new Exporter({ mediaType: 'MP4', isOutputBuffer: true });
  let succeeded = false;
  let outputs: FileBuffer[] | undefined;

  exporter.on('progress', value => console.info('progress', value));
  exporter.on('complete', (success, _infos, buffers) => {
    succeeded = success;
    outputs = buffers;
  });

  try {
    await exporter.onExport([{
      scene,
      size: [640, 360],
      name: 'animation',
      folderName: 'exports',
      fps: 30,
      backgroundColor: '#ffffff',
    }]);
    if (!succeeded || !outputs?.[0]) {
      throw new Error('媒体导出失败');
    }
    return new Blob([new Uint8Array(outputs[0])], { type: 'video/mp4' });
  } finally {
    exporter.dispose();
  }
}

onExport() 的 Promise 表示导出任务已结算;任务失败时通常仍会 resolve,必须检查 complete 的 success。它不等待自动下载 ZIP 的生成或浏览器保存完成。正在运行、已销毁等误用可能同步抛错。

isOutputBuffer: true 用于自行预览、上传或保存原始媒体字节。省略时默认自动下载 ${folderName}.zip,ZIP 内使用各任务的 ${name}.${格式后缀},即使只导出一个 MP4 也会包一层 ZIP;Images 的产物本身也是 ZIP,因此自动下载时形成两层 ZIP。complete 在自动下载前触发,两种模式都能通过该事件取得 buffers。

同一实例串行导出;不同实例可以独立工作。运行中不能 setOptions() 或再次 onExport()。取消用 onCancel(),彻底结束用 dispose()。取消和参数错误后可以重新提交任务;取消会保留此前完成的产物,包括在 done 回调中立即取消的情况。不要在 done/complete 回调中同步开始新任务;应等待上一次 onExport() 结算。

格式与限制

| mediaType | 主产物 | 编码方式 | 特性与当前限制 | | --- | --- | --- | --- | | Images | ZIP 内 PNG 序列帧 | Canvas + JSZip | 可保留透明度;帧名从 image-0001.png 起,目录使用合成名称 | | MP4 | H.264 MP4 | FFmpeg WASM | yuv420p;奇数宽高向上补为偶数;支持目标时长、末帧 JPEG;音轨仅为静音 | | GIF | GIF 动图 | FFmpeg WASM | 可调帧率、尺寸、四档质量和循环;GIF 无半透明 alpha | | APNG | APNG 动图 | FFmpeg WASM | 可调帧率、尺寸、压缩等级和循环 | | WebP | WebP 动图 | img2webp WASM | 相邻重复画面可能合帧;每个输入帧的时长取整到毫秒 | | WebM | VP9 WebM | Canvas captureStream + MediaRecorder | 通过 requestFrame() 按任务调度逐帧采集;时间戳取墙上时钟,受浏览器调度影响,不能保证离线编码级别的时间精度;不捕获音轨 | | AlphaMaskVideo | H.264 MP4 | Canvas 通道拼接 + FFmpeg | 输出宽度约为输入两倍;左侧 RGB、右侧 alpha 灰度;必须提供 extraCanvas |

透明格式必须显式设置 backgroundColor: '';省略时默认合成黑色不透明背景。AlphaMaskVideo 是通道拼接约定,不是原生带透明通道的视频,需要播放端自行还原。audioEnable 不保留场景里的原始声音。

捕获帧数为 max(1, round(场景时长 × fps)),从 t=0 开始按 1/fps 采样;末帧 JPEG 对应最后一张采样帧。WebP 使用 round(1000/fps) 毫秒作为每帧时长,例如 12 FPS 的 12 帧总计 0.996 秒;相同画面合帧不应改变总时长。GIF 的时间量化、APNG 的无损压缩和 AAC 的编码填充也应分别判断,不能只凭文件大小或严格等于十进制秒数判错。

公共 API

运行时顶层导出仅有 Exporter 和 loadFFmpegHelper。内部 ExportMedia、MEDIA_TYPE、状态常量和内部工具不是公共 API,也不能通过包 exports 深路径导入。

loadFFmpegHelper(options?)

返回 Promise<FFmpeg>,其中 FFmpeg 来自 @ffmpeg/ffmpeg,成功返回时已加载编码内核。唯一选项是 multiThreading?: boolean,默认 false;每次调用都会创建新的 FFmpeg 实例。需要自行执行 FFmpeg 命令时可使用它,结束后由调用方调用 terminate() 释放 Worker 和加载时创建的 Blob URL。多线程资源 URL 会保留到终止时,供后续编码创建线程使用。

Exporter 会按导出格式自行加载内核,使用它不需要提前调用此函数。helper 当前没有加载超时、重试或自定义资源 URL 参数。初始化中取消/销毁 Exporter 不会中断已经开始的资源下载;迟到的内核会在初始化返回后释放,不会重新激活实例。

初始化选项 ExportMediaInitOptions

| 字段 | 默认 | 说明 | | --- | --- | --- | | mediaType | 必填 | 上表七个区分大小写的值 | | isOutputBuffer | false | true 时不自动下载;完成事件仍提供 buffers | | imageQuality | 捕获时回落为 1 | Canvas 图片编码质量,0–1;主要影响 MP4 中间 JPEG、WebP 输入帧 | | extraCanvas | 无 | AlphaMaskVideo 使用的辅助 HTMLCanvasElement | | loggerInTranscoding | false | 打印捕获及 FFmpeg 日志;不是结构化业务事件 | | multiThreading | false | 请求 FFmpeg MT;要求跨源隔离和 SharedArrayBuffer,否则明确拒绝加载 |

任务 ExportItemParams

| 字段 | 默认 | 说明 | | --- | --- | --- | | scene | 必填 | 合法 JSONScene,加载场景时会深复制 | | size | 必填 | 完整场景的渲染尺寸 [width, height];调用方应保证为正整数且满足内存预算 | | crop | 无 | { x, y, width, height };以 size 的左上角为原点逐帧裁剪,范围必须在完整画面内;输出为裁剪尺寸(向上取整,MP4 再补齐偶数),不改变相机与布局 | | name / folderName | 必填 | 文件名 / 自动下载 ZIP 名;批量 ZIP 使用第一项 folderName | | fps | 30 | 正有限数;决定场景捕获帧数 | | time | 无 | 正有限的目标时长,单位秒;MP4/AlphaMaskVideo 保留全部采样帧,按“帧数 / 目标时长”设置编码帧率;不是裁剪区间,其他格式不使用此选项 | | backgroundColor | '#000000' | 空字符串用于保留透明背景 | | loop | true | GIF/APNG/WebP 的循环播放设置 | | audioEnable | false | 仅 MP4 为当前任务生成匹配时长的静音 WAV,再封装 AAC;AAC 解码可能带少量编码填充 | | mp4Config.isExportLastFrameJPEG | false | 末帧 JPEG 放在 extras 对应位置 | | gifConfig / apngConfig | 可省略 | { fps?, scale?, quality? };输出 fps 默认跟随任务 FPS,scale 默认 '-1:-1',quality 默认 'highest';质量可选 highest/high/medium/low |

任务 fps 决定捕获帧数,gifConfig.fps / apngConfig.fps 只在编码时调整输出帧率。scale 使用 FFmpeg 的尺寸表达式,例如 '320:-1';四档 quality 与初始化选项 imageQuality 是不同参数。

time、scale、尺寸、质量与资源 URL 的防御性校验尚不完整。不要把用户输入未经校验直接作为这些配置。

方法与事件

| API | 含义 | | --- | --- | | status | default / exporting / success / error | | setOptions(partial) | 空闲时更新选项;改变 mediaType 或 multiThreading 时重新准备相应 helper | | onExport(params): Promise<void> | 串行执行一批任务;结果由事件提供 | | onCancel() | 取消活动任务;没有活动任务时直接返回 | | dispose() | 幂等释放资源;实例随后不再可用 | | downloadByMediaBuffers(params, buffers, extras) | 将主文件与额外 JPEG 打包成 ZIP 并下载;无额外文件时传 null;返回 void,不能用 await 等待下载完成 | | on/off/getListeners | 注册、移除、查询事件监听器 | | progress(value) | 数值通常为 0–1;取消/失败也可能发出 1,不能将 1 等同成功 | | done(item, success, buffer?, extra?) | 单项结果;部分异常路径没有 done | | complete(success, taskInfos, buffers, extras) | 整批结果;失败的批量结果可能含空缺,取消保留已完成产物 |

Exporter 没有公开 error/ready 事件。可直接导入的类型有 ExporterEvent、ExportItemParams、ExportMediaCrop、ExportParams、ExportMediaInitOptions、ExportMediaItemDownloadInfo、FileBuffer、Buffers、Extras、LoadFFmpegHelperOptions。配置子类型尚未从顶层导出,可通过 ExportItemParams['gifConfig'] 等索引获取。

部署前提

  • 浏览器具备 DOM、Canvas、WebGL、WebAssembly、Worker;此包不是 Node.js 服务端转码器。
  • WebM 还需要 canvas.captureStream()、CanvasCaptureMediaStreamTrack.requestFrame() 和 MediaRecorder 的 VP9 支持,当前没有能力降级。
  • 单线程 FFmpeg 不要求跨源隔离。多线程要求安全上下文、SharedArrayBuffer 和正确的 COOP/COEP。
  • 当前 helper 地址集中在 src/media-export/config.ts,来自 gw.alipayobjects.com、mdn.alipayobjects.com;没有公共自托管 URL 配置、下载进度、超时和重试参数。
  • CSP 需要允许相关网络请求、Blob Worker,以及 WebP 脚本;根据实际部署策略配置,不建议笼统放开全部源。
  • 跨域图片、视频需正确设置 CORS,否则画布编码可能失败;大型项目还需要评估帧缓冲、WASM 和 ZIP 的峰值内存。
  • 包声明了多种 GE 插件依赖,但没有主动注册这些插件,dist 还内联了 GE runtime。不能假定“依赖已安装”或“宿主已导入插件”就能为内嵌 runtime 完成注册;应验证真实插件素材。此次只验证了基础 Sprite 场景。

仓库当前有两处直接使用本包:Agent Web 在 apps/web/src/features/canvas/canvas-export-service.ts 中完成画布截图与视频导出;Artis 演示(web-packages/artis)在 artis-page-shell 的 media-export.ts / export.ts 中提供场景与特效元素的视频导出入口,分别通过 createSceneVideoExportParams / createEffectsVideoExportParams 构造任务参数,安全区导出使用 crop 裁剪实现。Artis 包内的旧导出门面(src/features/export-media.ts 及 export-operations.ts 中的相关逻辑)仍处于注释状态。