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:
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.
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:
renditionCallback(...)
function, deriving an XMP (XML) rendition, based on the asset’s binary (1a) and any Processing Profile parameters (1b).rendition.path
.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.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.
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 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
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; }
}
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 a colorsFamily
parameter (supported values basic
, hex
, html
, ntc
, pantone
, roygbiv
).
{
"renditions": [
{
"worker": "...",
"name": "rendition.xml",
"colorsFamily": "pantone"
}
]
}
Tap Run and wait for the XML rendition to generate
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.
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:
/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
.
{
"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:
<?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.
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.
Invoke the worker from AEM by creating a new, or modifying an existing, custom Processing Profile service that invokes this deployed worker.
https://...adobeioruntime.net/api/v1/web/wkndAemAssetCompute-0.0.1/metadata-colors
aio app get-url
. Ensure the URL points at the correct workspace based on the AEM as a Cloud Service environment.colorFamily
pantone
basic
, hex
, html
, ntc
, pantone
, roygbiv
image/jpeg
, image/png
, image/gif
, image/svg
Leave blank
To review the colors metadata, map two new fields on the image’s metadata schema to the new metadata data properties the worker populates.
Colors Family
./jcr:content/metadata/wknd:colorsFamily
Colors
./jcr:content/metadata/wknd:colors
Colors Family
and Colors
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.
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.
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: