なつねこメモ

主にプログラミング関連のメモ帳 ♪(✿╹ヮ╹)ノ 書いてあるコードは自己責任でご自由にどうぞ。記事本文の無断転載は禁止です。

Cloudflare Workers でも画像のメタデータを取得したい

例えばサーバーレスな環境で、非同期的に画像のメタデータを取得してごにょごにょしたいこと、ありませんか?わたしはあります。 今回は、Cloudflare Workers を使って、画像のメタデータを取得してみようと思います。

まず最初に思いつくのが、Node.js 用画像処理パッケージである sharp を使うことだと思いますが、sharp は Cloudflare Workers では以下のようにエラーが出てデプロイできません:

$ wrangler deploy

> @natsuneko-laboratory/xxx@ deploy D:\ghq\github.com\mika-f\teyvat\packages\xxx
> wrangler deploy --minify --config ./wrangler.jsonc


 ⛅️ wrangler 4.5.0 (update available 4.24.0)
------------------------------------------------------

Total Upload: 2669.57 KiB / gzip: 989.25 KiB


X [ERROR] A request to the Cloudflare API (/accounts/xxx/workers/scripts/xxx/versions) failed.

  Uncaught Error: [unenv] process.report.getReport is not implemented yet!
    at createNotImplementedError
  (file:///D:/ghq/github.com/mika-f/teyvat/node_modules/.pnpm/unenv@2.0.0-rc.15/node_modules/unenv/dist/runtime/_internal/utils.mjs:25:9)
  in createNotImplementedError
    at null.<anonymous>
  (file:///D:/ghq/github.com/mika-f/teyvat/node_modules/.pnpm/unenv@2.0.0-rc.15/node_modules/unenv/dist/runtime/_internal/utils.mjs:30:9)
  in fn
    at getReport
  (file:///D:/ghq/github.com/mika-f/teyvat/node_modules/.pnpm/detect-libc@2.0.3/node_modules/detect-libc/lib/process.js:15:31)
  in getReport
    at familyFromReport
  (file:///D:/ghq/github.com/mika-f/teyvat/node_modules/.pnpm/detect-libc@2.0.3/node_modules/detect-libc/lib/detect-libc.js:62:18)
  in familyFromReport
    at familySync
  (file:///D:/ghq/github.com/mika-f/teyvat/node_modules/.pnpm/detect-libc@2.0.3/node_modules/detect-libc/lib/detect-libc.js:147:16)
  in familySync
    at null.<anonymous>
  (file:///D:/ghq/github.com/mika-f/teyvat/node_modules/.pnpm/detect-libc@2.0.3/node_modules/detect-libc/lib/detect-libc.js:167:48)
  in isNonGlibcLinuxSync
    at runtimeLibc
  (file:///D:/ghq/github.com/mika-f/teyvat/node_modules/.pnpm/sharp@0.34.1/node_modules/sharp/lib/libvips.js:40:38)
  in runtimeLibc
    at runtimePlatformArch
  (file:///D:/ghq/github.com/mika-f/teyvat/node_modules/.pnpm/sharp@0.34.1/node_modules/sharp/lib/libvips.js:42:57)
  in runtimePlatformArch
    at null.<anonymous>
  (file:///D:/ghq/github.com/mika-f/teyvat/node_modules/.pnpm/sharp@0.34.1/node_modules/sharp/lib/sharp.js:11:25)
    at null.<anonymous> (index.js:1:542)
   [code: 10021]


  If you think this is a bug, please open an issue at:
  https://github.com/cloudflare/workers-sdk/issues/new/choose


 ELIFECYCLE  Command failed with exit code 1.

これは、sharp が使っている Node.js の API がエッジランタイムに対応していないことが原因です。 今回、画像の処理というよりは、メタデータさえ取得できれば良いので、より軽量なパッケージを使うことで解決します。 そして、いろいろ試してみて快適に動いたのが、exifr というパッケージでした。

github.com

例えば、以下のようにすることで EXIF や XMP を簡単に取得することができます:

import exifr from "exifr";

// ...

const buffer = Buffer.from(await fetch("https://example.com/some/image.png").then(w => w.arrayBuffer()));
const metadata = await exifr.parse(buffer, { xmp: true });

console.log(metadata);
/*
 * Location: ボドゲ喫茶かっこう 毎週火曜日21:00~0:00"
 * LocationAccessLevel: Anyone
 * ...
 **/

簡単ですね。Buffer さえ渡せば、かなり高速にパースしてくれます。 あとはこれをごにょごにょするだけでやりたいことができます。めでたしめでたし。 ということで、Cloudflare Workers でも画像のメタデータを取得したい場合の解決策でした。