asset compute背景工作是Asset compute專案的核心,因為提供可執行或協調資產所執行工作以建立新轉譯的自訂功能。
asset compute專案會自動產生一個簡單背景工作,將資產的原始二進位檔複製到指定的轉譯中,不需進行任何轉換。 在本教學課程中,我們將修改此背景工作,以製作更有趣的轉譯,以說明Asset compute背景工作的強大功能。
我們將建立一個Asset compute背景工作,產生新的水準影像轉譯,在資產轉譯的左側和右側覆蓋空白空間,但資產版本模糊。 最終格式副本的寬度、高度和模糊都是參數化的。
asset compute背景工作實作Asset computeSDK背景工作API合約,位於 renditionCallback(...)
功能,其概念上:
AEM製作服務會叫用Asset compute背景工作,提供資產的 (1a) 原始二進位(source
參數),和 (1b) 處理設定檔中定義的任何參數(rendition.instructions
參數)。
asset computeSDK可協調自訂Asset compute中繼資料背景工作的執行 renditionCallback(...)
函式,根據資產的原始二進位格式副本產生新的二進位格式副本 (1a) 和任何參數 (1b).
asset compute工作器會將新格式副本的二進位資料儲存至 rendition.path
.
寫入的二進位資料 rendition.path
會透過Asset computeSDK傳輸至AEM作者服務,並公開為 (4a) 文字轉譯及 (4b) 保存至資產的中繼資料節點。
上圖闡述了Asset compute開發人員所關心的問題,以及Asset compute工作人員調用的邏輯流程。 對於好奇的人, asset compute執行的內部詳細資訊 不過,只有公開Asset computeSDK API合約可依賴。
所有Asset compute工人都遵循相同的基本結構和投入/產出合同。
'use strict';
// Any npm module imports used by the worker
const { worker, SourceCorruptError } = require('@adobe/asset-compute-sdk');
const fs = require('fs').promises;
/**
Exports the worker implemented by a custom rendition callback function, which parametrizes the input/output contract for the worker.
+ `source` represents the asset's original binary used as the input for the worker.
+ `rendition` represents the worker's output, which is the creation of a new asset rendition.
+ `params` are optional parameters, which map to additional key/value pairs, including a sub `auth` object that contains Adobe I/O access credentials.
**/
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');
}
// Access any custom parameters provided via the Processing Profile configuration
let param1 = rendition.instructions.exampleParam;
/**
Perform all work needed to transform the source into the rendition.
The source data can be accessed:
+ In the worker via a file available at `source.path`
+ Or via a presigned GET URL at `source.url`
**/
if (success) {
// A successful worker must write some data back to `renditions.path`.
// This example performs a trivial 1:1 copy of the source binary to the rendition
await fs.copyFile(source.path, rendition.path);
} else {
// Upon failure an Asset Compute Error (exported by @adobe/asset-compute-commons) should be thrown.
throw new GenericError("An error occurred!", "example-worker");
}
});
/**
Optionally create helper classes or functions the worker's rendition callback function invokes to help organize code.
Code shared across workers, or to complex to be managed in a single file, can be broken out across supporting JavaScript files in the project and imported normally into the worker.
**/
function customHelperFunctions() { ... }
/actions/worker
資料夾index.js
檔案這是我們在本教學課程中將修改的背景JavaScript檔案。
以Node.js為基礎的Asset compute專案,可善用強大的 npm模組生態系統. 若要運用npm模組,我們必須先將它們安裝至我們的Asset compute專案。
在這個工人中,我們利用 jimp 直接在Node.js程式碼中建立和操控轉譯影像。
並非所有npm模組都支援Asset compute操作資產。 不支援依賴應用程式(如ImageMagick或其他OS相關庫)存在的npm模組。 最好限制為僅限JavaScriptnpm模組的使用。
在Asset compute專案的根目錄中開啟命令列(可透過以VS程式碼執行) 終端機>新終端機)並執行命令:
$ npm install jimp
匯入 jimp
模組放入背景工作程式碼中,以便透過 Jimp
JavaScript物件。
更新 require
在工人的 index.js
若要匯入 Jimp
物件 jimp
模組:
'use strict';
const Jimp = require('jimp');
const { worker, SourceCorruptError } = require('@adobe/asset-compute-sdk');
const fs = require('fs').promises;
exports.main = worker(async (source, rendition, params) => {
// Check handle a corrupt input source
const stats = await fs.stat(source.path);
if (stats.size === 0) {
throw new SourceCorruptError('source file is empty');
}
// Do work here
});
asset compute背景工作可讀取參數,這些參數可透過AEMas a Cloud Service製作服務中定義的處理設定檔傳入。 參數會透過 rendition.instructions
物件。
可透過存取 rendition.instructions.<parameterName>
在背景代碼中。
在此處,我們將閱讀可設定轉譯的 SIZE
, BRIGHTNESS
和 CONTRAST
,若未透過處理設定檔提供任何值,則會提供預設值。 請注意 renditions.instructions
從AEMas a Cloud Service處理設定檔叫用時,會以字串形式傳入,因此請確定這些設定檔在背景程式碼中已轉換為正確的資料類型。
'use strict';
const Jimp = require('jimp');
const { worker, SourceCorruptError } = require('@adobe/asset-compute-sdk');
const fs = require('fs').promises;
exports.main = worker(async (source, rendition, params) => {
const stats = await fs.stat(source.path);
if (stats.size === 0) {
throw new SourceCorruptError('source file is empty');
}
// Read in parameters and set defaults if parameters are provided
// Processing Profiles pass in instructions as Strings, so make sure to parse to correct data types
const SIZE = parseInt(rendition.instructions.size) || 800;
const CONTRAST = parseFloat(rendition.instructions.contrast) || 0;
const BRIGHTNESS = parseFloat(rendition.instructions.brightness) || 0;
// Do work here
}
asset compute工作人員可能會遇到導致錯誤的情況。 AdobeAsset computeSDK提供 一組預先定義的錯誤 在遇到這種情況時可以拋出。 若未套用特定錯誤類型,則 GenericError
可使用,或特定自訂 ClientErrors
可定義。
開始處理轉譯之前,請檢查以確保此工作器的上下文中所有參數都有效且受支援:
SIZE
, CONTRAST
,和 BRIGHTNESS
有效。 否則,傳回自訂錯誤 RenditionInstructionsError
.
RenditionInstructionsError
擴展類 ClientError
是在此檔案底部定義。 使用特定的自訂錯誤,在 寫入測試 為工人。'use strict';
const Jimp = require('jimp');
// Import the Asset Compute SDK provided `ClientError`
const { worker, SourceCorruptError, ClientError } = require('@adobe/asset-compute-sdk');
const fs = require('fs').promises;
exports.main = worker(async (source, rendition, params) => {
const stats = await fs.stat(source.path);
if (stats.size === 0) {
throw new SourceCorruptError('source file is empty');
}
// Read in parameters and set defaults if parameters are provided
const SIZE = parseInt(rendition.instructions.size) || 800;
const CONTRAST = parseFloat(rendition.instructions.contrast) || 0;
const BRIGHTNESS = parseFloat(rendition.instructions.brightness) || 0;
if (SIZE <= 10 || SIZE >= 10000) {
// Ensure size is within allowable bounds
throw new RenditionInstructionsError("'size' must be between 10 and 1,0000");
} else if (CONTRAST <= -1 || CONTRAST >= 1) {
// Ensure contrast is valid value
throw new RenditionInstructionsError("'contrast' must between -1 and 1");
} else if (BRIGHTNESS <= -1 || BRIGHTNESS >= 1) {
// Ensure contrast is valid value
throw new RenditionInstructionsError("'brightness' must between -1 and 1");
}
// Do work here
}
// Create a new ClientError to handle invalid rendition.instructions values
class RenditionInstructionsError extends ClientError {
constructor(message) {
// Provide a:
// + message: describing the nature of this erring condition
// + name: the name of the error; usually same as class name
// + reason: a short, searchable, unique error token that identifies this error
super(message, "RenditionInstructionsError", "rendition_instructions_error");
// Capture the strack trace
Error.captureStackTrace(this, RenditionInstructionsError);
}
}
在讀取、淨化和驗證參數後,會寫入程式碼以產生轉譯。 產生轉譯的虛擬碼如下:
renditionImage
透過 size
參數。image
來源資產的二進位物件SIZE
參數值CONTRAST
參數值BRIGHTNESS
參數值image
進入 renditionImage
有透明背景renditionImage
to rendition.path
如此一來,資產就能以資產轉譯形式儲存回AEM。此程式碼採用 Jimp API 執行這些影像轉換。
asset compute工作者必須同步完成工作, rendition.path
必須在工人之前寫回 renditionCallback
完成。 這需要使用 await
運算元。 如果您不熟悉JavaScript非同步函式,以及如何讓這些函式以同步方式執行,請熟悉 JavaScript的await運算子.
已完成的工作人員 index.js
看起來應該像這樣:
'use strict';
const Jimp = require('jimp');
const { worker, SourceCorruptError, ClientError } = require('@adobe/asset-compute-sdk');
const fs = require('fs').promises;
exports.main = worker(async (source, rendition, params) => {
const stats = await fs.stat(source.path);
if (stats.size === 0) {
throw new SourceCorruptError('source file is empty');
}
// Read/parse and validate parameters
const SIZE = parseInt(rendition.instructions.size) || 800;
const CONTRAST = parseFloat(rendition.instructions.contrast) || 0;
const BRIGHTNESS = parseFloat(rendition.instructions.brightness) || 0;
if (SIZE <= 10 || SIZE >= 10000) {
throw new RenditionInstructionsError("'size' must be between 10 and 1,0000");
} else if (CONTRAST <= -1 || CONTRAST >= 1) {
throw new RenditionInstructionsError("'contrast' must between -1 and 1");
} else if (BRIGHTNESS <= -1 || BRIGHTNESS >= 1) {
throw new RenditionInstructionsError("'brightness' must between -1 and 1");
}
// Create target rendition image
let renditionImage = new Jimp(SIZE, SIZE, 0x0);
// Read and perform transformations on the source binary image
let image = await Jimp.read(source.path);
// Crop a circle from the source asset, and then apply contrast and brightness
image.crop(
image.bitmap.width < image.bitmap.height ? 0 : (image.bitmap.width - image.bitmap.height) / 2,
image.bitmap.width < image.bitmap.height ? (image.bitmap.height - image.bitmap.width) / 2 : 0,
image.bitmap.width < image.bitmap.height ? image.bitmap.width : image.bitmap.height,
image.bitmap.width < image.bitmap.height ? image.bitmap.width : image.bitmap.height
)
.circle()
.scaleToFit(SIZE, SIZE)
.contrast(CONTRAST)
.brightness(BRIGHTNESS);
// Place the transformed image onto the transparent renditionImage to save as PNG
renditionImage.composite(image, 0, 0)
// Write the final transformed image to the asset's rendition
await renditionImage.writeAsync(rendition.path);
});
// Custom error used for renditions.instructions parameter checking
class RenditionInstructionsError extends ClientError {
constructor(message) {
super(message, "RenditionInstructionsError", "rendition_instructions_error");
Error.captureStackTrace(this, RenditionInstructionsError);
}
}
現在工作程式碼已完成,且先前已在 manifest.yml,則可使用本機Asset compute開發工具執行,以查看結果。
從Asset compute專案的根目錄
執行 aio app run
等待Asset compute開發工具在新視窗中開啟
在 選擇檔案…… 下拉式清單,選取要處理的範例影像
更新 "name": "rendition.png"
作為生成透明PNG的工作器。
{
"renditions": [
{
"worker": "...",
"name": "rendition.png"
}
]
}
點選 執行 並等待格式副本產生
此 轉譯 區段會預覽產生的轉譯。 點選轉譯預覽以下載完整轉譯
透過處理設定檔設定傳入的參數,可在「Asset compute開發工具」中模擬,方法是在轉譯參數JSON上提供索引鍵/值配對。
在本機開發期間,當從AEM以Cloud Service處理設定檔的形式傳入為字串時,可以使用各種資料類型來傳入值,因此請務必視需要剖析正確的資料類型。
比如,Jimp crop(width, height)
函式需要其參數 int
s.若 parseInt(rendition.instructions.size)
不會剖析為int,則對的呼叫 jimp.crop(SIZE, SIZE)
失敗,因為參數是不相容的「字串」類型。
我們的程式碼接受下列項目的參數:
size
會將轉譯的大小(高度和寬度定義為整數)contrast
定義對比度調整,必須介於–1和1之間,作為浮點brightness
定義亮度調整,必須介於–1和1之間,作為浮點這些在工作人員中讀 index.js
透過:
const SIZE = parseInt(rendition.instructions.size) || 800
const CONTRAST = parseFloat(rendition.instructions.contrast) || 0
const BRIGHTNESS = parseFloat(rendition.instructions.brightness) || 0
更新轉譯參數以自訂大小、對比度和亮度。
{
"renditions": [
{
"worker": "...",
"name": "rendition.png",
"size": "450",
"contrast": "0.30",
"brightness": "0.15"
}
]
}
點選 執行 an
點選轉譯預覽以下載並檢閱產生的轉譯。 請注意其尺寸,以及與預設轉譯相比對比度和亮度的變更方式。
將其他影像上傳至 源檔案 下拉式清單,然後嘗試使用不同參數對工作人員執行作業!
最後 index.js
可在Github上取得,網址為: