← Cloudflare Workers / workers / tutorials
Создание превью YouTube с помощью Workers и Cloudflare Image Resizing
В этом руководстве вы узнаете, как программно создать собственное превью для YouTube с помощью Cloudflare Workers и Cloudflare Image Resizing. Собственное превью для YouTube может понадобиться, чтобы настроить его дизайн, призывы к действию и изображения, которые побуждают больше зрителей посмотреть ваше видео.
Это руководство поможет вам разобраться в работе с Изображения,Image Resizing и Cloudflare Workers.
Прежде чем начать
Во всех руководствах предполагается, что вы уже выполнили Руководство по началу работы, который поможет вам настроить аккаунт Cloudflare Workers, C3 ↗, а также Wrangler.
Чтобы пройти это руководство, убедитесь, что у вас установлены Node, Cargo и Wrangler установлен на вашем компьютере.
Цели обучения
В этом руководстве вы узнаете, как:
- Загружайте изображения в Cloudflare через панель управления Cloudflare или API.
- Настройте проект Worker с помощью Wrangler.
- Преобразуйте изображения с помощью Image Transformations в своём Worker.
Загрузите изображение
Чтобы создать пользовательское изображение миниатюры, сначала загрузите фоновое изображение в Cloudflare Images. Оно будет использоваться как исходное изображение для преобразований при создании миниатюр.
Cloudflare Images позволяет хранить, изменять размер, оптимизировать и доставлять изображения быстро и безопасно. Чтобы начать, загрузите изображения в панель управления Cloudflare или используйте Upload API.
Загрузите через панель управления
Чтобы загрузить изображение через дашборд Cloudflare:
-
На панели управления Cloudflare перейдите к разделу Преобразования страницу.
Перейдите в Преобразования ↗ -
Используйте Quick Upload чтобы перетащить изображение или щелкнуть и выбрать файл на своем компьютере.
-
После загрузки изображения просмотрите его по сгенерированному URL.
Загрузите с помощью API
Чтобы загрузить изображение с помощью Загрузите по URL API см. пример ниже:
curl --request POST \
--url https://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/images/v1 \
--header 'Authorization: Bearer <API_TOKEN>' \
--form 'url=<PATH_TO_IMAGE>' \
--form 'metadata={"key":"value"}' \
--form 'requireSignedURLs=false'ACCOUNT_ID: Идентификатор аккаунта текущего пользователя, который можно найти в настройках вашего аккаунта.API_TOKEN: Нужно создать с правом доступа Images.PATH_TO_IMAGE: Указывает URL изображения, которое нужно загрузить.
После этого вы получите ответ, похожий на следующий:
{
"result": {
"id": "2cdc28f0-017a-49c4-9ed7-87056c83901",
"filename": "image.jpeg",
"metadata": {
"key": "value"
},
"uploaded": "2022-01-31T16:39:28.458Z",
"requireSignedURLs": false,
"variants": [
"https://imagedelivery.net/Vi7wi5KSItxGFsWRG2Us6Q/2cdc28f0-017a-49c4-9ed7-87056c83901/public",
"https://imagedelivery.net/Vi7wi5KSItxGFsWRG2Us6Q/2cdc28f0-017a-49c4-9ed7-87056c83901/thumbnail"
]
},
"success": true,
"errors": [],
"messages": []
}Теперь, когда изображение загружено, вы будете использовать его как фоновое изображение для миниатюры видео.
Создайте Worker для преобразования текста в изображение
После загрузки изображения создайте Worker, который позволит преобразовывать текст в изображение. Это изображение можно использовать как наложение на загруженное фоновое изображение. Используйте rustwasm-worker-template ↗.
Прежде чем начать, вам понадобится следующее:
-
Последняя версия Rust ↗.
-
Доступ к
cargo-generateподкоманда:cargo install cargo-generate
Создайте новый проект Worker с помощью worker-rust шаблон:
cargo generate https://github.com/cloudflare/rustwasm-worker-templateТеперь вы внесёте несколько изменений в файлы в каталоге проекта.
- В
lib.rsфайл, добавьте следующий блок кода:
use worker::*;
mod utils;
#[event(fetch)]
pub async fn main(req: Request, env: Env, _ctx: worker::Context) -> Result<Response> {
// Optionally, get more helpful error messages written to the console in the case of a panic.
utils::set_panic_hook();
let router = Router::new();
router
.get("/", |_, _| Response::ok("Hello from Workers!"))
.run(req, env)
.await
}- Обновите
Cargo.tomlфайл в вашемworker-to-textкаталог проекта для использования text-to-png ↗, пакет Rust для рендеринга текста в PNG. Добавьте пакет как зависимость, выполнив команду:
cargo add [email protected]- Импортируйте
text_to_pngбиблиотеку вworker-to-textпроектаlib.rsфайл.
use text_to_png::{TextPng, TextRenderer};
use worker::*;
mod utils;
#[event(fetch)]
pub async fn main(req: Request, env: Env, _ctx: worker::Context) -> Result<Response> {
// Optionally, get more helpful error messages written to the console in the case of a panic.
utils::set_panic_hook();
let router = Router::new();
router
.get("/", |_, _| Response::ok("Hello from Workers!"))
.run(req, env)
.await
}- Обновите
lib.rsчтобы создатьhandle-slashфункция, которая запускает преобразование изображения на основе текста, переданного в URL в качестве параметра запроса.
use text_to_png::{TextPng, TextRenderer};
use worker::*;
mod utils;
#[event(fetch)]
pub async fn main(req: Request, env: Env, _ctx: worker::Context) -> Result<Response> {
// Optionally, get more helpful error messages written to the console in the case of a panic.
utils::set_panic_hook();
let router = Router::new();
router
.get("/", |_, _| Response::ok("Hello from Workers!"))
.run(req, env)
.await
}
async fn handle_slash(text: String) -> Result<Response> {}- В
handle-slashфункция, вызовитеTextRendererприсвоив его значению renderer, указав, что нужно использовать пользовательский шрифт. Затем используйтеrender_text_to_png_dataметод для преобразования текста в изображение. В этом примере пользовательский шрифт (Inter-Bold.ttf) находится в/assetsпапка в корне проекта, которая будет использоваться для создания миниатюры. Вам нужно изменить эту часть кода, чтобы она указывала на ваш собственный файл шрифта.
use text_to_png::{TextPng, TextRenderer};
use worker::*;
mod utils;
#[event(fetch)]
pub async fn main(req: Request, env: Env, _ctx: worker::Context) -> Result<Response> {
// Optionally, get more helpful error messages written to the console in the case of a panic.
utils::set_panic_hook();
let router = Router::new();
router
.get("/", |_, _| Response::ok("Hello from Workers!"))
.run(req, env)
.await
}
async fn handle_slash(text: String) -> Result<Response> {
let renderer = TextRenderer::try_new_with_ttf_font_data(include_bytes!("../assets/Inter-Bold.ttf"))
.expect("Example font is definitely loadable");
let text_png: TextPng = renderer.render_text_to_png_data(text.replace("+", " "), 60, "003682").unwrap();
}- Перепишите
Routerфункцию для вызоваhandle_slashкогда в URL передан запрос, а иначе возвращать"Hello Worker!"в качестве ответа.
use text_to_png::{TextPng, TextRenderer};
use worker::*;
mod utils;
#[event(fetch)]
pub async fn main(req: Request, env: Env, _ctx: worker::Context) -> Result<Response> {
// Optionally, get more helpful error messages written to the console in the case of a panic.
utils::set_panic_hook();
let router = Router::new();
router
.get_async("/", |req, _| async move {
if let Some(text) = req.url()?.query() {
handle_slash(text.into()).await
} else {
handle_slash("Hello Worker!".into()).await
}
})
.run(req, env)
.await
}
async fn handle_slash(text: String) -> Result<Response> {
let renderer = TextRenderer::try_new_with_ttf_font_data(include_bytes!("../assets/Inter-Bold.ttf"))
.expect("Example font is definitely loadable");
let text_png: TextPng = renderer.render_text_to_png_data(text.replace("+", " "), 60, "003682").unwrap();
}- В вашем
lib.rsфайле присвойте заголовкам значениеcontent-type: image/pngчтобы ответ корректно отображался как изображение PNG.
use text_to_png::{TextPng, TextRenderer};
use worker::*;
mod utils;
#[event(fetch)]
pub async fn main(req: Request, env: Env, _ctx: worker::Context) -> Result<Response> {
// Optionally, get more helpful error messages written to the console in the case of a panic.
utils::set_panic_hook();
let router = Router::new();
router
.get_async("/", |req, _| async move {
if let Some(text) = req.url()?.query() {
handle_slash(text.into()).await
} else {
handle_slash("Hello Worker!".into()).await
}
})
.run(req, env)
.await
}
async fn handle_slash(text: String) -> Result<Response> {
let renderer = TextRenderer::try_new_with_ttf_font_data(include_bytes!("../assets/Inter-Bold.ttf"))
.expect("Example font is definitely loadable");
let text_png: TextPng = renderer.render_text_to_png_data(text.replace("+", " "), 60, "003682").unwrap();
let mut headers = Headers::new();
headers.set("content-type", "image/png")?;
Ok(Response::from_bytes(text_png.data)?.with_headers(headers))
}Финальный lib.rs файл должен выглядеть следующим образом. Полный код в виде примера репозитория можно найти на GitHub ↗.
use text_to_png::{TextPng, TextRenderer};
use worker::*;
mod utils;
#[event(fetch)]
pub async fn main(req: Request, env: Env, _ctx: worker::Context) -> Result<Response> {
// Optionally, get more helpful error messages written to the console in the case of a panic.
utils::set_panic_hook();
let router = Router::new();
router
.get_async("/", |req, _| async move {
if let Some(text) = req.url()?.query() {
handle_slash(text.into()).await
} else {
handle_slash("Hello Worker!".into()).await
}
})
.run(req, env)
.await
}
async fn handle_slash(text: String) -> Result<Response> {
let renderer = TextRenderer::try_new_with_ttf_font_data(include_bytes!("../assets/Inter-Bold.ttf"))
.expect("Example font is definitely loadable");
let text = if text.len() > 128 {
"Nope".into()
} else {
text
};
let text = urlencoding::decode(&text).map_err(|_| worker::Error::BadEncoding)?;
let text_png: TextPng = renderer.render_text_to_png_data(text.replace("+", " "), 60, "003682").unwrap();
let mut headers = Headers::new();
headers.set("content-type", "image/png")?;
Ok(Response::from_bytes(text_png.data)?.with_headers(headers))
}После завершения обновления проекта запустите локальный сервер для разработки Worker, выполнив:
npx wrangler devВ результате должен запуститься localhost экземпляр с отображаемым изображением:
При добавлении параметра запроса с произвольным текстом вы должны получить:
Чтобы развернуть Worker, откройте файл Wrangler и обновите name ключ с именем вашего проекта. Ниже приведён пример с именем проекта из этого руководства:
{
"$schema": "./node_modules/wrangler/config-schema.json",
"name": "worker-to-text"
}"$schema" = "./node_modules/wrangler/config-schema.json"
name = "worker-to-text"Затем выполните npx wrangler deploy команду, чтобы развернуть Worker.
npx wrangler deployA .workers.dev домен будет создан для вашего Worker после выполнения wrangler deploy. Этот домен будет использоваться в главном изображении миниатюры.
Создайте Worker, который отображает исходное изображение
Создайте Worker, который отдаёт изображение, загруженное в Images, выполнив:
npm create cloudflare@latest -- thumbnail-imageДля настройки выберите следующие параметры:
- Для С чего вы хотите начать?, выберите
Hello World example. - Для Какой шаблон вы хотите использовать?, выберите
Worker only. - Для Какой язык вы хотите использовать?, выберите
JavaScript. - Для Хотите использовать git для контроля версий?, выберите
Yes. - Для Хотите развернуть приложение?, выберите
No(мы внесём некоторые изменения перед развёртыванием).
Чтобы начать разработку Worker, cd в каталог вашего нового проекта:
cd thumbnail-imageЭто создаст новый проект Worker с именем thumbnail-image. В src/index.js файл, добавьте следующий блок кода:
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (url.pathname === "/original-image") {
const image = await fetch(
`https://imagedelivery.net/${env.CLOUDFLARE_ACCOUNT_HASH}/${IMAGE_ID}/public`,
);
return image;
}
return new Response("Image Resizing with a Worker");
},
};Обновите env.CLOUDFLARE_ACCOUNT_HASH с вашим Cloudflare account ID. Обновите env.IMAGE_ID с вашим ID образа.
Запустите ваш Worker и перейдите к /original-image маршрут для проверки изображения.
Добавление произвольного текста на изображение
Теперь вы используете Преобразования изображений Cloudflare, с fetch метод, чтобы добавить динамическое текстовое изображение как наложение поверх фонового изображения. Сначала выведите итоговое изображение на отдельном маршруте. Назовите новый маршрут /thumbnail.
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (url.pathname === "/original-image") {
const image = await fetch(
`https://imagedelivery.net/${env.CLOUDFLARE_ACCOUNT_HASH}/${IMAGE_ID}/public`,
);
return image;
}
if (url.pathname === "/thumbnail") {
}
return new Response("Image Resizing with a Worker");
},
};Затем используйте fetch метод, чтобы применить изменения трансформации изображения поверх фонового изображения. Параметры наложения вложены в options.cf.image.
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (url.pathname === "/original-image") {
const image = await fetch(
`https://imagedelivery.net/${env.CLOUDFLARE_ACCOUNT_HASH}/${IMAGE_ID}/public`,
);
return image;
}
if (url.pathname === "/thumbnail") {
fetch(imageURL, {
cf: {
image: {},
},
});
}
return new Response("Image Resizing with a Worker");
},
}; imageURL это URL изображения, которое вы хотите использовать в качестве фонового изображения. В cf.image объект, укажите параметры, которые нужно применить к фоновому изображению.
Добавьте фоновое изображение в каталог assets на GitHub и отправьте изменения в GitHub. Скопируйте URL загруженного изображения: кликните по нему левой кнопкой мыши и выберите Копировать URL удаленного файла опцию.
Замените imageURL значение на скопированный удаленный URL.
if (url.pathname === "/thumbnail") {
const imageURL =
"https://github.com/lauragift21/social-image-demo/blob/1ed9044463b891561b7438ecdecbdd9da48cdb03/assets/cover.png?raw=true";
fetch(imageURL, {
cf: {
image: {},
},
});
}Затем добавьте параметры наложения в объект изображения. Измените размер изображения до нужной ширины и высоты для миниатюр YouTube и используйте draw параметр, чтобы добавить наложенный текст с использованием развёрнутого URL вашего text-to-image Worker.
fetch(imageURL, {
cf: {
image: {
width: 1280,
height: 720,
draw: [
{
url: "https://text-to-image.examples.workers.dev",
left: 40,
},
],
},
},
});Преобразования изображений можно протестировать только после развёртывания Worker.
Чтобы развернуть Worker, откройте файл Wrangler и обновите name ключ с именем вашего проекта. Ниже приведён пример с именем проекта из этого руководства:
{
"$schema": "./node_modules/wrangler/config-schema.json",
"name": "thumbnail-image"
}"$schema" = "./node_modules/wrangler/config-schema.json"
name = "thumbnail-image"Разверните ваш Worker, выполнив команду:
npx wrangler deployКоманда развёртывает ваш Worker на пользовательских workers.dev поддомен. Перейдите в .workers.dev поддомен и перейдите в /thumbnail маршрут.
Вы должны увидеть изображение изменённого размера с текстом Hello Workers!.
Теперь вы сделаете применяемый текст динамическим. Динамический текст позволит вам изменять текст, и он будет автоматически обновляться на изображении.
Чтобы добавить динамический текст, добавьте любой текст к /thumbnail URL с помощью параметров запроса и передайте его в text-to-image URL Worker в качестве параметра.
for (const title of url.searchParams.values()) {
try {
const editedImage = await fetch(imageURL, {
cf: {
image: {
width: 1280,
height: 720,
draw: [
{
url: `https://text-to-image.examples.workers.dev/?${title}`,
left: 50,
},
],
},
},
});
return editedImage;
} catch (error) {
console.log(error);
}
}Пройдя это руководство, вы успешно создали собственный генератор превью для YouTube.
Дополнительные материалы
В этом руководстве вы узнали, как использовать Cloudflare Workers и Cloudflare Image Transformations для создания собственных превью для YouTube. Подробнее о Cloudflare Workers и Image Transformations читайте в Изменение размера изображения с помощью Worker.