asset compute 작업자는 자산에서 새 변환을 만들기 위해 수행한 작업을 수행하거나 조정하는 사용자 정의 기능을 제공하는 Asset compute 프로젝트의 핵심입니다.
asset compute 프로젝트는 변형 없이 자산의 원래 바이너리를 명명된 변환으로 복사하는 간단한 작업자를 자동으로 생성합니다. 이 자습서에서는 Asset compute 작업자의 기능을 보여주기 위해 이 작업자를 수정하여 보다 흥미로운 표현물을 만들어 보겠습니다.
자산의 흐릿한 버전이 있는 자산 표현물의 왼쪽 및 오른쪽에 있는 빈 공간을 포함하는 새 가로 이미지 표현물을 생성하는 Asset compute 작업자를 만듭니다. 최종 표현물의 폭, 높이 및 흐림 효과가 매개 변수화됩니다.
asset compute 작업자는 개념적으로 renditionCallback(...)
함수에서 Asset compute SDK 작업자 API 계약을 구현합니다.
AEM 작성자 서비스는 Asset compute 작업자를 호출하여 자산의 (1a) 원래 이진(source
매개 변수) 및 처리 프로필에 정의된 모든 매개 변수를 제공합니다(rendition.instructions
매개 변수).____
asset compute SDK는 사용자 지정 Asset compute 메타데이터 작업자의 renditionCallback(...)
함수 실행을 오케스트레이션하고, 자산의 원래 이진 (1a) 및 모든 매개 변수 (1b)에 따라 새 이진 변환을 생성합니다.
asset compute 작업자가 새 표현물의 이진 데이터를 rendition.path
에 저장합니다.
rendition.path
에 작성된 이진 데이터는 Asset compute SDK를 통해 AEM 작성자 서비스로 전송되고, (4a) 텍스트 표현물과 (4b)(4b) 자산의 메타데이터 노드로 노출됩니다.
위의 다이어그램은 Asset compute 개발자 대면 관련 문제와 Asset compute 작업자 호출을 설명하는 논리 흐름을 보여줍니다. 궁금하신 경우 Asset compute 실행에 대한 내부 세부 정보를 사용할 수 있지만 공개 Asset compute SDK 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 프로젝트에 모듈을 설치해야 합니다.
이 작업자는 zip을 활용하여 Node.js 코드에서 직접 표현물 이미지를 만들고 조작합니다.
자산 조작에 대한 모든 npm 모듈이 Asset compute에서 지원되는 것은 아닙니다. ImageMagick 또는 기타 OS 종속 라이브러리와 같은 응용 프로그램이 있는 npm 모듈은 지원되지 않습니다. JavaScript 전용 npm 모듈 사용을 제한하는 것이 가장 좋습니다.
asset compute 프로젝트의 루트에서 명령줄을 열고(이 작업은 터미널 > New Terminal을 통해 VS 코드에서 수행할 수 있음) 명령을 실행합니다.
$ npm install jimp
Jimp
JavaScript 개체를 통해 사용할 수 있도록 jimp
모듈을 작업자 코드로 가져옵니다.
작업자의 index.js
맨 위에 있는 require
지시어를 업데이트하여 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 작업자는 AEM에서 Cloud Service 작성자 서비스로 정의된 처리 프로필을 통해 전달할 수 있는 매개 변수를 읽을 수 있습니다. 매개 변수는 rendition.instructions
개체를 통해 작업자에 전달됩니다.
작업자 코드에서 rendition.instructions.<parameterName>
에 액세스하여 읽을 수 있습니다.
여기에서는 구성 가능한 표현물의 SIZE
, BRIGHTNESS
및 CONTRAST
에서 읽어볼 수 있으며, 처리 프로필을 통해 제공된 것이 없는 경우 기본값을 제공합니다. AEM에서 Cloud Service 처리 프로필로 호출될 때 renditions.instructions
이 문자열로 전달되므로 작업자 코드에서 올바른 데이터 유형으로 변환되었는지 확인합니다.
'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 작업자는 오류가 발생하는 상황이 발생할 수 있습니다. Adobe Asset compute SDK는 사전 정의된 오류 세트를 제공하며, 이 오류는 이러한 상황이 발생할 때 발생할 수 있습니다. 특정 오류 유형이 적용되지 않으면 GenericError
을 사용하거나 특정 사용자 지정 ClientErrors
을 정의할 수 있습니다.
변환 처리를 시작하기 전에 이 작업자 컨텍스트에서 모든 매개 변수가 유효하고 지원되는지 확인합니다.
SIZE
, CONTRAST
및 BRIGHTNESS
에 대한 변환 명령 매개 변수가 유효한지 확인합니다. 그렇지 않으면 사용자 지정 오류 RenditionInstructionsError
를 실행합니다.
ClientError
을(를) 확장하는 사용자 지정 RenditionInstructionsError
클래스가 이 파일의 하단에 정의되어 있습니다. 특정 사용자 지정 오류를 사용하면 작업자에 대한 테스트를 작성할 때 유용합니다.'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);
}
}
매개 변수를 읽고, 정리하고, 유효성을 검사하면 변환을 생성하기 위해 코드가 작성됩니다. 변환 생성에 대한 의사 코드는 다음과 같습니다.
size
매개 변수를 통해 지정된 정사각형 차원에 새 renditionImage
캔버스를 만듭니다.image
개체를 만듭니다SIZE
매개 변수 값으로 정의된 차원 내에 맞게 비율 조정CONTRAST
매개 변수 값을 기준으로 대비 조정BRIGHTNESS
매개 변수 값을 기준으로 밝기 조정image
을 투명한 배경이 있는 renditionImage
의 중앙에 배치합니다renditionImage
을 rendition.path
에 작성하면 다시 AEM에 자산 변환으로 저장할 수 있습니다.이 코드는 Jimp API를 사용하여 이러한 이미지 변형을 수행합니다.
asset compute 작업자는 동기식으로 작업을 완료해야 하며, rendition.path
은 작업자의 renditionCallback
이 완료되기 전에 완전히 다시 작성해야 합니다. 이렇게 하려면 비동기 함수 호출이 await
연산자를 사용하여 동기식으로 수행되어야 합니다. JavaScript 비동기 함수와 비동기 함수를 동기식으로 실행하는 방법을 잘 모를 경우 JavaScript의 대기 연산자를 숙지하십시오.
완료된 작업자 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"
}
]
}
실행을 탭하고 표현물이 생성될 때까지 기다립니다
표현물 섹션은 생성된 표현물을 미리 봅니다. 변환 미리 보기를 탭하여 전체 변환을 다운로드합니다
처리 프로필 구성을 통해 전달된 매개 변수는 변환 매개 변수 JSON에서 키/값 쌍으로 제공하여 Asset compute 개발 도구에서 시뮬레이션할 수 있습니다.
로컬 개발 중에 AEM에서 Cloud Service 처리 프로필로 전달된 경우 다양한 데이터 유형을 사용하여 값을 전달할 수 있으므로 필요한 경우 올바른 데이터 유형을 구문 분석해야 합니다.
예를 들어 Jimp의 crop(width, height)
함수에는 해당 매개 변수가 int
'여야 합니다. parseInt(rendition.instructions.size)
를 int로 구문 분석하지 않으면 매개 변수가 호환되지 않는 'String' 유형이 되므로 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"
}
]
}
실행을 다시 누릅니다
변환 미리 보기를 탭하여 생성된 변환을 다운로드하고 검토합니다. 기본 표현물과 비교하여 해당 차원과 대비 및 명도가 어떻게 변경되었는지 확인합니다.
다른 이미지를 소스 파일 드롭다운에 업로드하고 다른 매개 변수로 작업자를 실행해 보십시오!
최종 index.js
은 Github에서 사용할 수 있습니다.