Develop an Asset Compute metadata worker
Custom Asset Compute workers can produce XMP (XML) data that is sent back to AEM and stored as metadata on an asset.
Common use cases include:
- Integrations with 3rd party systems, such as a PIM (Product Information Management system), where additional metadata must be retrieved and stored on the asset
- Integrations with Adobe services, such as Content and Commerce AI to augment asset metadata with additional machine learning attributes
- Deriving metadata about the asset from its binary and storing it as asset metadata in AEM as a Cloud Service
What you will do
In this tutorial we’ll create an Asset Compute metadata worker that derives the most commonly used colors in an image asset, and writes the names of the colors back to the asset’s metadata in AEM. While the worker itself is basic, this tutorial uses it to explore how Asset Compute workers can be used to write back metadata to assets in AEM as a Cloud Service.
Logical flow of a Asset Compute metadata worker invocation
The invocation of Asset Compute metadata workers is nearly identical to that of binary rendition generating workers, with the primary difference being the return type is an XMP (XML) rendition whose values are also written to the asset’s metadata.
Asset Compute workers implement the Asset Compute SDK worker API contract, in the renditionCallback(...)
function, which is conceptually:
- Input: An AEM asset’s original binary and Processing Profile parameters
- Output: An XMP (XML) rendition persisted to the AEM asset as a rendition and to the asset’s metadata
- AEM Author service invokes the Asset Compute metadata worker, providing the asset’s (1a) original binary, and (1b) any parameters defined in the Processing Profile.
- The Asset Compute SDK orchestrates the execution of the custom Asset Compute metadata worker’s
renditionCallback(...)
function, deriving an XMP (XML) rendition, based on the asset’s binary (1a) and any Processing Profile parameters (1b). - The Asset Compute worker saves the XMP (XML) representation to
rendition.path
. - The XMP (XML) data written to
rendition.path
is transported via the Asset Compute SDK to AEM Author Service and exposes it as (4a) a text rendition and (4b) persisted to the asset’s metadata node.
Configure the manifest.yml manifest
All Asset Compute workers must be registered in the manifest.yml.
Open the project’s manifest.yml
and add a worker entry that configures the new worker, in this case metadata-colors
.
Remember .yml
is whitespace sensitive.
packages:
__APP_PACKAGE__:
license: Apache-2.0
actions:
worker:
function: actions/worker/index.js
web: 'yes'
runtime: 'nodejs:12'
limits:
timeout: 60000 # in ms
memorySize: 512 # in MB
concurrency: 10
annotations:
require-adobe-auth: true
metadata-colors:
function: actions/metadata-colors/index.js
web: 'yes'
runtime: 'nodejs:12'
limits:
memorySize: 512 # in MB
function
points to the worker implementation created in the next step. Name workers semantically (for example, the actions/worker/index.js
might have been better named actions/rendition-circle/index.js
), as these show in the worker’s URL and also determine the worker’s test suite folder name.
The limits
and require-adobe-auth
are configured discretely per worker. In this worker, 512 MB
of memory is allocated as the code inspects (potentially) large binary image data. The other limits
are removed to use defaults.
Develop a metadata worker metadata-worker
Create a new metadata worker JavaScript file in the Asset Compute project at the path defined manifest.yml for the new worker, at /actions/metadata-colors/index.js
Install npm modules
Install the extra npm modules (@adobe/asset-compute-xmp, get-image-colors, and color-namer) that is used in this Asset Compute worker.
$ npm install @adobe/asset-compute-xmp
$ npm install get-image-colors
$ npm install color-namer
Metadata worker code
This worker looks very similar to the rendition-generating worker, the the primary difference is it writes XMP (XML) data to the rendition.path
to get saved back to AEM.
"use strict";
const { worker, SourceCorruptError } = require("@adobe/asset-compute-sdk");
const fs = require("fs").promises;
// Require the @adobe/asset-compute-xmp module to create XMP
const { serializeXmp } = require("@adobe/asset-compute-xmp");
// Require supporting npm modules to derive image colors from image data
const getColors = require("get-image-colors");
// Require supporting npm modules to convert image colors to color names
const namer = require("color-namer");
exports.main = worker(async (source, rendition, params) => {
// Perform any necessary source (input) checks
const stats = await fs.stat(source.path);
if (stats.size === 0) {
// Throw appropriate errors whenever an erring condition is met
throw new SourceCorruptError("source file is empty");
}
const MAX_COLORS = 10;
const DEFAULT_COLORS_FAMILY = 'basic';
// Read the color family parameter to use to derive the color names
let colorsFamily = rendition.instructions.colorsFamily || DEFAULT_COLORS_FAMILY;
if (['basic', 'hex', 'html', 'ntc', 'pantone', 'roygbiv'].indexOf(colorsFamily) === -1) {
colorsFamily = DEFAULT_COLORS_FAMILY;
}
// Use the `get-image-colors` module to derive the most common colors from the image
let colors = await getColors(source.path, { options: MAX_COLORS });
// Convert the color Chroma objects to their closest names
let colorNames = colors.map((color) => getColorName(colorsFamily, color));
// Serialize the data to XMP metadata
// These properties are written to the [dam:Asset]/jcr:content/metadata resource
// This stores
// - The list of color names is stored in a JCR property named `wknd:colors`
// - The colors family used to derive the color names is stored in a JCR property named `wknd:colorsFamily`
const xmp = serializeXmp({
// Use a Set to de-duplicate color names
"wknd:colors": [...new Set(colorNames)],
"wknd:colorsFamily": colorsFamily
}, {
// Define any property namespaces used in the above property/value definition
// These namespaces are automatically registered in AEM if they do not yet exist
namespaces: {
wknd: "https://wknd.site/assets/1.0/",
},
}
);
// Save the XMP metadata to be written back to the asset's metadata node
await fs.writeFile(rendition.path, xmp, "utf-8");
});
/**
* Helper function that derives the closest color name for the color, based on the colors family
*
* @param {*} colorsFamily the colors name family to use
* @param {*} color the color to convert to a name
*/
function getColorName(colorsFamily, color) {
if ('hex' === colorsFamily) { return color; }
let names = namer(color.rgb())[colorsFamily];
if (names.length >= 1) { return names[0].name; }
}
Run the metadata worker locally development-tool
With the worker code complete, it can be executed using the local Asset Compute Development Tool.
Because our Asset Compute project contains two workers (the previous circle rendition and this metadata-colors
worker), the Asset Compute Development Tool’s profile definition lists execution profiles for both workers. The second profile definition points to the new metadata-colors
worker.
-
From the root of the Asset Compute project
-
Execute
aio app run
to start the Asset Compute Development Tool -
In the Select a file… drop down, pick a sample image to process
-
In the second profile definition configuration, which points to the
metadata-colors
worker, update"name": "rendition.xml"
as this worker generates an XMP (XML) rendition. Optionally, add acolorsFamily
parameter (supported valuesbasic
,hex
,html
,ntc
,pantone
,roygbiv
).code language-json { "renditions": [ { "worker": "...", "name": "rendition.xml", "colorsFamily": "pantone" } ] }
-
Tap Run and wait for the XML rendition to generate
- Since both workers are listed in the profile definition, both renditions will generate. Optionally, the top profile definition pointing at the circle rendition worker can be deleted, to avoid executing it from Development Tool.
-
The Renditions section previews the generated rendition. Tap the
rendition.xml
to download it, and open it in VS Code (or your favorite XML/text editor) to review.
Test the worker test
Metadata workers can be tested using the same Asset Compute testing framework as binary renditions. The only difference is the rendition.xxx
file in the test case must be the expected XMP (XML) rendition.
-
Create the following structure in the Asset Compute project:
code language-none /test/asset-compute/metadata-colors/success-pantone/ file.jpg params.json rendition.xml
-
Use the sample file as the test case’s
file.jpg
. -
Add the following JSON to the
params.json
.code language-none { "fmt": "xml", "colorsFamily": "pantone" }
Note the
"fmt": "xml"
is required to instruct the test suite to generate an.xml
text-based rendition. -
Provide the expected XML in the
rendition.xml
file. This can be obtained by:- Running the test input file through Development Tool and saving the (validated) XML rendition out.
code language-none <?xml version="1.0" encoding="UTF-8"?><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:wknd="https://wknd.site/assets/1.0/"><rdf:Description><wknd:colors><rdf:Seq><rdf:li>Silver</rdf:li><rdf:li>Black</rdf:li><rdf:li>Outer Space</rdf:li></rdf:Seq></wknd:colors><wknd:colorsFamily>pantone</wknd:colorsFamily></rdf:Description></rdf:RDF>
-
Execute
aio app test
from the root of the Asset Compute project to execute all test suites.
Deploy the worker to Adobe I/O Runtime deploy
To invoke this new metadata worker from AEM Assets, it must be deployed to Adobe I/O Runtime, using the command:
$ aio app deploy
Note this will deploy all the workers in the project. Review the unabridged deploy instructions for how to deploy to Stage and Production workspaces.
Integrate with AEM Processing Profiles processing-profile
Invoke the worker from AEM by creating a new, or modifying an existing, custom Processing Profile service that invokes this deployed worker.
-
Login to AEM as a Cloud Service Author service as an AEM Administrator
-
Navigate to Tools > Assets > Processing Profiles
-
Create a new, or edit and existing, Processing Profile
-
Tap the Custom tab, and tap Add New
-
Define the new service
-
Create Metadata Rendition: Toggle to active
-
Endpoint:
https://...adobeioruntime.net/api/v1/web/wkndAemAssetCompute-0.0.1/metadata-colors
- This is the URL to the worker obtained during the deploy or using the command
aio app get-url
. Ensure the URL points at the correct workspace based on the AEM as a Cloud Service environment.
- This is the URL to the worker obtained during the deploy or using the command
-
Service Parameters
-
Tap Add Parameter
- Key:
colorFamily
- Value:
pantone
- Supported values:
basic
,hex
,html
,ntc
,pantone
,roygbiv
- Supported values:
- Key:
-
-
Mime Types
- Includes:
image/jpeg
,image/png
,image/gif
,image/svg
- These are the only MIME types supported by the 3rd party npm modules used to derive the colors.
- Excludes:
Leave blank
- Includes:
-
-
Tap Save in the top right
-
Apply the Processing Profile to an AEM Assets folder if not done so already
Update the Metadata Schema metadata-schema
To review the colors metadata, map two new fields on the image’s metadata schema to the new metadata data properties the worker populates.
-
In the AEM Author service, navigate to Tools > Assets > Metadata Schemas
-
Navigate into default and select and edit image and add read-only form fields to expose the generated color metadata
-
Add a Single Line Text
- Field Label:
Colors Family
- Map to property:
./jcr:content/metadata/wknd:colorsFamily
- Rules > Field > Disable edit: Checked
- Field Label:
-
Add a Multi Value Text
- Field Label:
Colors
- Map to property:
./jcr:content/metadata/wknd:colors
- Field Label:
-
Tap Save in the top right
Processing assets
- In the AEM Author service, navigate to Assets > Files
- Navigate to the folder, or sub-folder, the Processing Profile is applied to
- Upload a new image (JPEG, PNG, GIF or SVG) to the folder, or re-process existing images using the updated Processing Profile
- When processing is complete, select the asset, and tap properties in the top action bar to display its metadata
- Review the
Colors Family
andColors
metadata fields for the metadata written back from the custom Asset Compute metadata worker.
With the color metadata written to the asset’s metadata, on the [dam:Asset]/jcr:content/metadata
resource, this metadata is indexed increased asset discover-ability using these terms via search, and they can even be written back to the asset’s binary if then DAM Metadata Writeback workflow is invoked on it.
Metadata rendition in AEM Assets
The actual XMP file generated by the Asset Compute metadata worker is also stored as a discrete rendition on the asset. This file is generally not used, rather the applied values to the asset’s metadata node is used, but the raw XML output from the worker is available in AEM.
metadata-colors worker code on Github
The final metadata-colors/index.js
is available on Github at:
The final test/asset-compute/metadata-colors
test suite is available on Github at: