payload-plugin-media-metadata
v0.9.2
Published
Payload CMS plugin for media metadata utilities.
Maintainers
Readme
payload-plugin-media-metadata
Adds optional fields and beforeChange hooks on media collections for thumbhash placeholders, SVG
content/viewBox extraction, and video dimensions / frame thumbhash using bundled libraries (sharp,
ffmpeg-static, mp4box, etc.).
Install
pnpm add payload-plugin-media-metadatanpm install payload-plugin-media-metadataPeer dependencies
payload^3.80.0@payloadcms/ui^3.80.0next^15.0.0 || ^16.0.0— optional (forpayload-plugin-media-metadata/next)react/react-dom— optional for admin client pieces (>=18)
payload.config.ts
Reference layout for every PayloadPluginMediaMetadataOptions field (collections, shared
fields) plus per-collection images / videos shapes (false or flags):
import { buildConfig } from "payload"
import { mediaMetadataPlugin } from "payload-plugin-media-metadata"
export default buildConfig({
plugins: [
mediaMetadataPlugin({
// Shared `FieldOptions` merged into each matched collection (`name` / `overrides` / other Partial<Field> keys)
fields: {
thumbhash: {
name: "thumbhash",
overrides: { label: "Thumbhash placeholder" },
},
svgContent: {
name: "svgContent",
overrides: {},
},
svgViewbox: {
name: "svgContentViewbox",
overrides: { label: "SVG viewBox" },
},
},
collections: [
{
slug: "media",
// Object branch (defaults enable all listed flags when keys omitted)
images: {
thumbhash: true,
svgContent: true,
svgViewbox: true,
},
videos: {
dimensions: true,
thumbhash: false,
},
// Per-collection overrides layered on top of `fields` above
fields: {
thumbhash: { overrides: { admin: { readOnly: true } } },
svgContent: { name: "svgContent" },
svgViewbox: { overrides: {} },
},
},
{
slug: "legacy-uploads",
images: false, // disables SVG + image thumbhash hooks derived from `images`
videos: false, // disables video dimension / frame thumbhash hooks
},
],
}),
],
})The plugin merges admin.dependencies so Payload can load field UI from
payload-plugin-media-metadata/client.
Pass no options (or omit the plugin) for a no-op transform.
Generated defaults (when you do not set fields.*.name) include thumbhash, svgContent,
and svgContentViewbox text fields; hooks fill thumbhash/video metadata on upload/change.
Options (PayloadPluginMediaMetadataOptions)
| Field | Purpose |
| ------------- | ------------------------------------------------------------------------------------- |
| collections | Array of MediaMetadataCollectionOptions (each matched collection gets hooks/fields) |
| fields | Shared MediaMetadataFieldOptions merged into each collection |
Per collection (MediaMetadataCollectionOptions):
| Field | Purpose |
| -------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| slug | Target collection |
| images | false or { svgContent?, svgViewbox?, thumbhash? } — omitting keys defaults them on in the object branch |
| videos | false or { dimensions?, thumbhash? } — same defaulting behavior |
| fields | Per-collection field overrides (svgContent, svgViewbox, thumbhash with optional name / overrides / other Partial<Field> keys) |
Manual fields / overrides
Use the factories when you need fields outside the plugin matcher list:
createThumbhashField,createSvgContentField,createSvgContentViewBoxField- Hooks:
createGenerateImageMetaHook,createGenerateVideoMetaHook,createSvgContentHook mediaMetadataAdminFieldComponentslists the{ path, exportName }pairs the plugin uses (ThumbhashField,SvgContentField,SvgContentViewboxFieldonpayload-plugin-media-metadata/client).
Utilities: getMediaUrl, getPayloadMediaUrl, isMedia, optimizeSvgWithViewbox, thumbhash
helpers (thumbhashFromImageBuffer, decodeThumbhash, …), video helpers
(extractFirstFramePngFromVideo, getDimensionsFromMp4Buffer, …).
Admin UI (payload-plugin-media-metadata/client)
React field components and previews: ThumbhashField, SvgContentField, SvgContentViewboxField,
SvgContentAdminPreview, Svg. You normally rely on the plugin to wire these; import them when
building custom field layouts.
Next.js (payload-plugin-media-metadata/next)
import { CmsImage } from "payload-plugin-media-metadata/next"
const asset = {
alt: "Team photo",
url: "/api/media/file/photo.jpg",
width: 1600,
height: 900,
thumbhash: "…",
svgContent: null,
}
export function HeroImage() {
return (
<CmsImage
src={asset}
alt={asset.alt}
width={asset.width}
height={asset.height}
sizes="(max-width: 768px) 100vw, 50vw"
priority
trimSvgWhitespace
/>
)
}Exports: CmsImage, CmsMedia, CmsVideo (and their props types). CmsImage accepts Payload
media, URLs, or static image data and renders stored svgContent as inline SVG when present.
License
Apache-2.0 (see repository root).
