绑定(binding) 将您的 Worker 连接到 Developer Platform 上的外部资源,如 Media Transformations、R2 存储桶 或 KV 命名空间。
您可以将 Media Transformations API 绑定到 Worker,以转换、调整大小和从视频中提取内容,而无需通过 URL 访问它们。
例如,在 Workers 中使用 Media Transformations 时,您可以:
- 转换存储在私有 R2 存储桶或其他受保护源中的视频
- 优化视频并将输出直接存储回 R2,而无需提供给浏览器
- 从视频中提取静态帧和 spritesheet,并使用 Workers AI 进行分类或描述
- 从视频文件中提取音轨,使用 Workers AI 进行动态转录
Media 绑定按 Worker 启用。
绑定(binding) 可在 Cloudflare 仪表板中为 Worker 配置,或在项目目录的 Wrangler 配置文件中配置。
要将 Media Transformations 绑定到 Worker,请在 Wrangler 配置文件末尾添加以下内容:
{
"$schema": "./node_modules/wrangler/config-schema.json",
"media": {
"binding": "MEDIA"
}
}[media]
binding = "MEDIA" # available in your Worker on env.MEDIA在 Worker 代码中,您可以使用 env.MEDIA.input() 构建可操作视频(作为 ReadableStream 传递)的对象来与此绑定交互。
Media Transformations 绑定类似于 Images 绑定,但方法链顺序固定,且 input() 的结果不能跨多个转换重用。
Media 绑定的起点,接受原始内容。
- 接受包含视频字节的
ReadableStream<Uint8Array>。
定义如何通过对视频调整大小或裁剪来转换输入。此方法为可选——如果不需要调整大小或裁剪,可以直接在 .input() 的结果上调用 .output()。
- 接受以下参数(均为可选):
width:目标宽度(像素,10-2000)。height:目标高度(像素,10-2000)。fit:如何将视频调整大小以适应指定尺寸。contain:保持宽高比,将视频缩放以完全包含在输出尺寸内。cover:保持宽高比,将视频缩放以完全覆盖输出尺寸并进行居中裁剪。scale-down:与contain相同,但仅缩小。不放大。
- 请参阅 转换视频选项 了解更多详情。
定义从视频中提取什么以及输出如何格式化。请参阅 源视频要求 和 限制 了解输入和输出约束。
- 接受以下参数:
mode:要生成的输出类型。video:输出 H.264/AAC 优化的 MP4 文件。frame:输出静态图像(JPEG 或 PNG)。spritesheet:输出包含多帧的 JPEG。audio:输出 AAC 编码的 M4A 文件。
time:提取的起始时间戳(例如"2s"、"1m")。默认值:"0s"。duration:video、audio或spritesheet模式的输出时长(例如"5s")。imageCount:spritesheet 中包含的帧数。format:frame模式(jpg、png)或audio模式(m4a)的输出格式。audio:在video模式中是否包含音频的布尔值。默认值:true。
配置输出后,有三种方法可用于接收结果。这些方法返回 Promise,必须 await:
.response():返回Promise<Response>——转换后的媒体作为 HTTP Response 对象,可直接返回给客户端或存储到缓存。.media():返回Promise<ReadableStream<Uint8Array>>——转换后的媒体作为字节流。.contentType():返回Promise<string>——输出的 MIME 类型(例如video/mp4、image/jpeg、audio/mp4)。
调整视频大小并提取 5 秒片段:
export default {
async fetch(request, env) {
const video = await env.R2_BUCKET.get("input.mp4");
const result = env.MEDIA.input(video.body)
.transform({ width: 480, height: 270 })
.output({ mode: "video", time: "0s", duration: "5s" });
return await result.response();
},
};提取单帧作为 JPEG 缩略图:
export default {
async fetch(request, env) {
const video = await env.R2_BUCKET.get("input.mp4");
const result = env.MEDIA.input(video.body)
.transform({ width: 640, height: 360 })
.output({ mode: "frame", time: "2s", format: "jpg" });
return await result.response();
},
};从视频中提取帧(静态图像),然后使用 Workers AI 上的 UForm-Gen 等模型生成标题。
export default {
async fetch(request, env) {
// First, load the video file from a source like R2 (or a fetch)
// Loading from R2
const video = await env.R2_BUCKET.get("input.mp4");
// Or using a fetch:
// const video = await fetch('https://example.com/video.mp4');
// Isolate a frame (still image)
const frame = await env.MEDIA.input(video.body)
.transform({ width: 720 })
.output({
mode: 'frame',
time: '3s',
})
.response();
// Set up the payload for Workers AI
const payload = {
image: [...new Uint8Array(await frame.arrayBuffer())],
prompt: "Generate a caption for this image",
max_tokens: 512,
};
const response = await env.AI.run(
"@cf/unum/uform-gen2-qwen-500m",
payload
);
return new Response(JSON.stringify(response));
}
}从视频中提取音轨为 M4A 文件。此示例演示跳过 .transform(),因为不需要调整大小:
export default {
async fetch(request, env) {
const video = await env.R2_BUCKET.get("input.mp4");
const result = env.MEDIA.input(video.body).output({
mode: "audio",
time: "0s",
duration: "30s",
});
return await result.response();
},
};提取音频,然后使用 Workers AI 上的 Whisper 进行转录。
export default {
async fetch(request, env) {
// First, load the video file from a source like R2 (or a fetch)
// Loading from R2
const video = await env.R2_BUCKET.get("input.mp4");
// Or using a fetch:
// const video = await fetch('https://example.com/video.mp4');
// Extract audio using the media transformations binding:
const audio = await env.MEDIA.input(video.body)
.transform()
.output({
mode: 'audio',
})
.response();
// Prepare and run Workers AI inference
const payload = {
audio: [...new Uint8Array(await audio.arrayBuffer())],
};
const response = await env.AI.run(
"@cf/openai/whisper",
payload
);
// response will have props {text, word_count, vtt, words}
return new Response(
JSON.stringify(response, null, 2),
{
headers: {'Content-Type': 'application/json'}
}
);
}
}转换视频并将结果直接存储到 R2:
export default {
async fetch(request, env) {
const video = await env.R2_BUCKET.get("input.mp4");
const result = env.MEDIA.input(video.body)
.transform({ width: 480, height: 270, fit: "contain" })
.output({ mode: "video", time: "0s", duration: "10s", audio: false });
// Store the transformed video directly in R2
await env.R2_BUCKET.put("output-480p.mp4", await result.media(), {
httpMetadata: { contentType: await result.contentType() },
});
return new Response("Video transformed and stored", { status: 200 });
},
};错误可能在方法链的不同点抛出:
.input()可能抛出与账户限制(免费层或订阅)或服务中断相关的错误。.output()可能抛出与转换操作本身相关的错误,例如无效参数或不支持的输入格式。
错误抛出 MediaError,它扩展标准 Error 接口并提供额外信息:
code:数字错误代码。message:错误描述。stack:可选堆栈跟踪。
使用 try...catch 块处理错误:
export default {
async fetch(request, env) {
const video = await env.R2_BUCKET.get("input.mp4");
try {
const result = env.MEDIA.input(video.body)
.transform({ width: 480, height: 270 })
.output({ mode: "video", time: "0s", duration: "5s" });
return await result.response();
} catch (e) {
if (e instanceof Error && "code" in e) {
// Handle MediaError
return new Response(`Transformation failed: ${e.message}`, {
status: 500,
});
}
throw e;
}
},
};与通过 URL 的转换不同,Media 绑定的响应 不会 自动缓存。Workers 让您直接与 Cache API 交互以自定义缓存行为。您可以在脚本中实现逻辑,将转换存储到 Cloudflare 缓存或 R2 存储。
请参阅 Stream 的 定价 信息了解费用。通过绑定执行的转换按每次操作计费,而非基于请求唯一性。为获得最佳成本和性能优化,请缓存或存储输出以供重用。
Media Transformations API 通过 Wrangler(Workers 命令行界面)在本地开发中以 远程模式 可用。转换操作将使用远程资源执行,超出包含的免费层后将产生用量费用。
要在本地开发中启用,请在绑定配置中添加 remote:
{
"$schema": "./node_modules/wrangler/config-schema.json",
"media": {
"binding": "MEDIA",
"remote": true
}
}[media]
binding = "MEDIA" # available in your Worker on env.MEDIA
remote = true然后运行:
npx wrangler dev