コンテンツにスキップ

WorkersとCloudflare Image Resizingを使用してYouTubeサムネイルを生成する

Last reviewed: over 1 year ago

このチュートリアルでは、Cloudflare WorkersとCloudflare Image Resizingを使用して、プログラム的にカスタムYouTubeサムネイルを生成する方法を学びます。サムネイルのデザイン、コール・トゥ・アクション、視聴者を動画に引き込むために使用する画像をカスタマイズするために、カスタムYouTubeサムネイルを生成したい場合があります。

このチュートリアルでは、ImagesImage ResizingおよびCloudflare Workersを使用する方法を理解するのに役立ちます。

Before you start

All of the tutorials assume you have already completed the Get started guide, which gets you set up with a Cloudflare Workers account, C3, and Wrangler.

このチュートリアルに従うには、Node、Cargo、およびWranglerがマシンにインストールされていることを確認してください。

学習目標

このチュートリアルでは、以下のことを学びます:

  • CloudflareダッシュボードまたはAPIを使用してCloudflareに画像をアップロードする。
  • Wranglerを使用してWorkerプロジェクトをセットアップする。
  • Worker内で画像変換を使用して画像を操作する。

画像をアップロードする

カスタムサムネイル画像を生成するには、まずCloudflare Imagesに背景画像をアップロードする必要があります。これがサムネイルを生成するための変換に使用する画像となります。

Cloudflare Imagesを使用すると、画像を迅速かつ安全に保存、リサイズ、最適化、配信できます。始めるには、Cloudflareダッシュボードに画像をアップロードするか、Upload APIを使用します。

ダッシュボードを使用してアップロード

Cloudflareダッシュボードを使用して画像をアップロードするには:

  1. Cloudflare Dashboardにログインし、アカウントを選択します。
  2. Imagesを選択します。
  3. Quick Uploadを使用して、画像をドラッグアンドドロップするか、クリックしてローカルファイルからファイルを選択します。
  4. 画像がアップロードされたら、生成されたURLを使用して表示します。

APIを使用してアップロード

Upload via URL APIを使用して画像をアップロードするには、以下の例を参照してください:

Terminal window
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: 現在のユーザーのアカウント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サブコマンドへのアクセス:

    Terminal window
    cargo install cargo-generate

worker-rustテンプレートを使用して新しいWorkerプロジェクトを作成します:

Terminal window
cargo generate https://github.com/cloudflare/rustwasm-worker-template

プロジェクトディレクトリ内のファイルにいくつかの変更を加えます。

  1. lib.rsファイルに以下のコードブロックを追加します:
use worker::*;
mod utils;
#[event(fetch)]
pub async fn main(req: Request, env: Env, _ctx: worker::Context) -> Result<Response> {
// パニックが発生した場合にコンソールに役立つエラーメッセージを表示するオプション。
utils::set_panic_hook();
let router = Router::new();
router
.get("/", |_, _| Response::ok("Hello from Workers!"))
.run(req, env)
.await
}
  1. worker-to-textプロジェクトディレクトリ内のCargo.tomlファイルを更新して、テキストをPNGにレンダリングするためのRustパッケージであるtext-to-pngを使用します。以下のコマンドを実行してパッケージを依存関係として追加します:
Terminal window
cargo add text-to-png@0.2.0
  1. worker-to-textプロジェクトのlib.rsファイルにtext_to_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> {
// パニックが発生した場合にコンソールに役立つエラーメッセージを表示するオプション。
utils::set_panic_hook();
let router = Router::new();
router
.get("/", |_, _| Response::ok("Hello from Workers!"))
.run(req, env)
.await
}
  1. lib.rsを更新して、URLのクエリパラメータとして渡されたテキストに基づいて画像変換をアクティブにするhandle-slash関数を作成します。
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> {
// パニックが発生した場合にコンソールに役立つエラーメッセージを表示するオプション。
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> {}
  1. 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> {
// パニックが発生した場合にコンソールに役立つエラーメッセージを表示するオプション。
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();
}
  1. Router関数を再構成して、URLにクエリが渡されたときにhandle_slashを呼び出し、そうでない場合は"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> {
// パニックが発生した場合にコンソールに役立つエラーメッセージを表示するオプション。
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();
}
  1. lib.rsファイル内で、レスポンスがPNG画像として正しくレンダリングされるようにcontent-type: image/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> {
// パニックが発生した場合にコンソールに役立つエラーメッセージを表示するオプション。
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> {
// パニックが発生した場合にコンソールに役立つエラーメッセージを表示するオプション。
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のローカルサーバーを起動します:

Terminal window
npx wrangler dev

これにより、画像が表示されるlocalhostインスタンスが起動します:

Run wrangler dev to start a local server for your Worker

カスタムテキストを含むクエリパラメータを追加すると、次のような画像が得られます:

Follow the instructions above to receive an output image

Workerをデプロイするには、wrangler.tomlファイルを開き、nameキーをプロジェクト名に更新します。以下は、このチュートリアルのプロジェクト名の例です:

name = "worker-to-text"

次に、npx wrangler deployコマンドを実行してWorkerをデプロイします。

Terminal window
npx wrangler deploy

wrangler deployを実行すると、Worker用の.workers.devドメインが生成されます。このドメインをメインのサムネイル画像で使用します。

元の画像を表示するWorkerを作成する

アップロードした画像をImagesから提供するWorkerを作成するには、次のコマンドを実行します:

Terminal window
npm create cloudflare@latest -- thumbnail-image

For setup, select the following options:

  • For What would you like to start with?, choose Hello World example.
  • For Which template would you like to use?, choose Hello World Worker.
  • For Which language do you want to use?, choose JavaScript.
  • For Do you want to use git for version control?, choose Yes.
  • For Do you want to deploy your application?, choose No (we will be making some changes before deploying).

Workerの開発を開始するには、新しいプロジェクトディレクトリにcdします:

Terminal window
cd thumbnail-image

これにより、thumbnail-imageという新しいWorkerプロジェクトが作成されます。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_HASHCloudflareアカウント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("ワーカーによる画像リサイズ");
},
};

次に、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("ワーカーによる画像リサイズ");
},
};

imageURLは、背景画像として使用したい画像のURLです。cf.imageオブジェクト内で、背景画像に適用したいオプションを指定します。

背景画像をGitHubのassetsディレクトリに追加し、変更をGitHubにプッシュします。画像を左クリックしてCopy Remote File 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オプションを使用して、デプロイされたtext-to-imageワーカーのURLを使用してオーバーレイテキストを追加します。

fetch(imageURL, {
cf: {
image: {
width: 1280,
height: 720,
draw: [
{
url: "https://text-to-image.examples.workers.dev",
left: 40,
},
],
},
},
});

画像変換は、ワーカーをデプロイしたときにのみテストできます。

ワーカーをデプロイするには、wrangler.tomlファイルを開き、nameキーをプロジェクト名で更新します。以下は、このチュートリアルのプロジェクト名の例です:

name = "thumbnail-image"

次のコマンドを実行してワーカーをデプロイします:

Terminal window
npx wrangler deploy

このコマンドは、ワーカーをカスタムworkers.devサブドメインにデプロイします。.workers.devサブドメインに移動し、/thumbnailルートにアクセスします。

リサイズされた画像にHello Workers!というテキストが表示されるはずです。

上記の手順に従ってリサイズされた画像を生成します。

これで、適用されたテキストを動的にします。テキストを動的にすることで、テキストを変更し、画像に自動的に更新させることができます。

動的テキストを追加するには、クエリパラメータを使用して/thumbnail URLに付随するテキストを追加し、それをtext-to-imageワーカーのURLにパラメータとして渡します。

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);
}
}

これにより、生成された画像にクエリ文字列として渡したテキストが常に返されます。この例のURL、https://socialcard.cdnuptime.com/thumbnail?Getting%20Started%20With%20Cloudflare%20Imagesは、次の画像を生成します:

サムネイルの例。

このチュートリアルを完了することで、カスタムYouTubeサムネイルジェネレーターを成功裏に作成しました。

関連リソース

このチュートリアルでは、Cloudflare WorkersとCloudflareの画像変換を使用してカスタムYouTubeサムネイルを生成する方法を学びました。Cloudflare Workersと画像変換について詳しく学ぶには、ワーカーで画像をリサイズするを参照してください。