← Cloudflare Stream / stream / transform-videos
Propojení s API Workers
A binding propojuje váš Worker na externí zdroje na Developer Platform, například Media Transformations, R2 buckety, nebo KV namespaces.
Rozhraní Media Transformations API můžete připojit ke svému Workeru, a transformovat tak videa, měnit jejich velikost a extrahovat z nich obsah, aniž by musela být dostupná přes URL.
Například při použití Media Transformations ve Workers můžete:
- Transformace videa uloženého v privátním bucketu R2 nebo jiném chráněném zdroji
- Optimalizujte videa a ukládejte výstup přímo zpět do R2, aniž by se zobrazoval v prohlížeči
- Extrahování statických snímků a spritesheetů z videí a jejich použití pro klasifikaci nebo popis pomocí Workers AI
- Extrahování zvukových stop z video souborů pro dynamický přepis pomocí Workers AI
Nastavení
Binding Media se povoluje pro každý Worker zvlášť.
Bindings lze nakonfigurovat na Cloudflare dashboardu pro váš Worker nebo v konfiguračním souboru Wrangler ve složce vašeho projektu.
Chcete-li k Workeru připojit Media Transformations, přidejte na konec konfiguračního souboru Wrangler následující:
{
"$schema": "./node_modules/wrangler/config-schema.json",
"media": {
"binding": "MEDIA"
}
}[media]
binding = "MEDIA" # available in your Worker on env.MEDIAV kódu svého Workeru můžete s touto vazbou pracovat pomocí env.MEDIA.input() a sestavte objekt, který dokáže video ovládat (předaný jako ReadableStream).
Metody
Binding Media Transformations je podobný Vazba Images binding, s tím rozdílem, že pořadí zřetězených metod je pevně dané a výsledkem volání input() nelze znovu použít pro více transformací.
.input()
Výchozí bod pro binding Media, který přijímá nezpracovaný obsah.
- Přijímá
ReadableStream<Uint8Array>obsahující bajty videa.
.transform() (volitelné)
Určuje, jak se má vstupní video transformovat změnou velikosti nebo oříznutím. Tato metoda je volitelná: pokud velikost měnit ani ořezávat nepotřebujete, můžete zavolat .output() přímo na výsledek .input().
- Přijímá následující parametry (všechny volitelné):
width: Cílová šířka v pixelech (10-2000).height: Cílová výška v pixelech (10-2000).fit: Jak změnit velikost videa tak, aby odpovídalo zadaným rozměrům.contain: Zvětší nebo zmenší video tak, aby se celé vešlo do výstupních rozměrů při zachování poměru stran.cover: Zvětší nebo zmenší video tak, aby celé pokrylo výstupní rozměry, s oříznutím zaměřeným na střed.scale-down: Stejné jakocontain, ale pouze zmenšuje. Nezvětšuje.
- Viz Možnosti transformace videí pro další podrobnosti.
.output()
Určuje, co se má z videa extrahovat a jak bude výstup formátován. Přečtěte si požadavky na zdrojové video a omezení pro omezení vstupu a výstupu.
- Přijímá následující parametry:
mode: Typ výstupu, který se má vygenerovat.video: Výstupem je soubor MP4 optimalizovaný pro H.264/AAC.frame: Výstupem je statický obrázek (JPEG nebo PNG).spritesheet: Výstupem je JPEG obsahující více snímků.audio: Výstupem je soubor M4A kódovaný ve formátu AAC.
time: Počáteční časové razítko pro extrakci (například"2s","1m"). Výchozí hodnota:"0s".duration: Délka výstupu provideo,audio, nebospritesheetrežimy (například"5s").imageCount: Počet snímků zahrnutých do spritesheetu.format: Výstupní formát proframerežim (jpg,png) neboaudiorežim (m4a).audio: Booleovská hodnota určující, zda zahrnout zvuk vvideorežim. Výchozí:true.
Metody s návratovou hodnotou
Po nakonfigurování výstupu máte nakonec k dispozici tři metody pro získání výsledků. Tyto metody vracejí objekty Promise a je nutné na ně čekat pomocí await:
.response(): VracíPromise<Response>: transformovaná média jako objekt HTTP Response, připravený k vrácení klientovi nebo uložení do mezipaměti..media(): VracíPromise<ReadableStream<Uint8Array>>: transformovaná média jako proud bajtů..contentType(): VracíPromise<string>: typ MIME výstupu (napříkladvideo/mp4,image/jpeg,audio/mp4).
Příklady
Generování optimalizovaného videoklipu
Změňte velikost videa a extrahujte pětisekundový klip:
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();
},
};Extrahování statického snímku
Extrahování jednoho snímku jako náhledu 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();
},
};Identifikace obsahu pomocí Media Transformations a Workers AI
Extrahujte snímek (statický obrázek) z videa a poté použijte model, jako je UForm-Gen na Workers AI k vygenerování titulků.
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));
}
}Extrahování zvuku
Extrahování zvukové stopy z videa jako souboru M4A. Tento příklad ukazuje přeskočení .transform() protože není potřeba žádné změny velikosti:
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();
},
};Přepis zvuku pomocí Media Transformations a Workers AI
Extrahujte zvuk a poté jej přepište pomocí Whisper on Workers AI.
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'}
}
);
}
}Uložte transformovaný výstup do R2
Transformace videa a uložení výsledku přímo do 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 });
},
};Zpracování chyb
Chyby mohou nastat v různých bodech řetězce metod:
.input()může vyvolat chyby související s limity účtu (bezplatná úroveň nebo předplatné) nebo výpadky služby..output()může vyvolat chyby související se samotnou transformační operací, například neplatné parametry nebo nepodporované vstupní formáty.
Chyby vyvolávají MediaError, které rozšiřuje standardní Error rozhraní s dalšími informacemi:
code: Číselný kód chyby.message: Popis chyby.stack: Volitelný stack trace.
Použijte try...catch blok pro zpracování chyb:
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;
}
},
};Ukládání do mezipaměti
Na rozdíl od transformací přes URL odpovědi z Media binding jsou ne automaticky ukládány do mezipaměti. Workers vám umožňuje přímo pracovat s Cache API a přizpůsobte tak chování mezipaměti. Ve svém skriptu můžete implementovat logiku, která bude ukládat transformace do mezipaměti Cloudflare nebo úložiště R2.
Billing
Viz Stream Ceny informace o nákladech. Transformace prováděné prostřednictvím bindingu se účtují za jednotlivé operace, nikoli podle jedinečnosti požadavků. Pro co nejlepší optimalizaci nákladů a výkonu si výstupy ukládejte do mezipaměti nebo je uchovávejte pro opakované použití.
Lokální vývoj
Rozhraní Media Transformations API je k dispozici ve vzdáleném režimu pro lokální vývoj prostřednictvím Wrangler, rozhraní příkazové řádky pro Workers. Operace transformace se provádějí pomocí vzdáleného prostředku a podléhají poplatkům za využití nad rámec zahrnutého bezplatného tarifu.
Chcete-li povolit použití v lokálním vývoji, přidejte remote do konfigurace vazby:
{
"$schema": "./node_modules/wrangler/config-schema.json",
"media": {
"binding": "MEDIA",
"remote": true
}
}[media]
binding = "MEDIA" # available in your Worker on env.MEDIA
remote = truePoté spusťte:
npx wrangler dev