asset compute 작업자 개발

Asset compute 작업자는 에셋에서 새 렌디션을 만들기 위해 수행한 작업을 수행하거나 조정하는 사용자 지정 기능을 제공하는 Asset compute 프로젝트의 핵심입니다.

asset compute 프로젝트는 아무런 변형 없이 에셋의 원본 바이너리를 명명된 렌디션으로 복사하는 간단한 작업자를 자동으로 생성합니다. 이 튜토리얼에서는 Asset compute 작업자의 기능을 보여주기 위해 보다 흥미로운 렌디션을 만들기 위해 이 작업자를 수정합니다.

asset compute 작업자를 만들어 에셋 렌디션의 왼쪽과 오른쪽에 있는 빈 공간과 흐릿한 버전의 에셋을 포함하는 새 가로 이미지 렌디션을 생성합니다. 최종 렌디션의 너비, 높이 및 흐림 효과는 매개 변수화됩니다.

asset compute 작업자 호출의 논리 흐름

Asset compute 작업자는 Asset compute SDK 작업자 API 계약을 renditionCallback(...) 함수(개념적으로 정의됨):

  • 입력: AEM 자산의 원본 이진 및 처리 프로필 매개 변수
  • 출력: AEM 에셋에 추가할 하나 이상의 렌디션

Asset compute 작업자 논리 흐름

  1. AEM Author 서비스는 Asset compute 작업자를 호출하여 (1a) 원본 이진 파일(source 매개 변수), 및 (1b) 처리 프로필에 정의된 모든 매개 변수(rendition.instructions 매개 변수)를 참조하십시오.

  2. asset compute SDK는 사용자 지정 Asset compute 메타데이터 작업자의 실행을 조정합니다. renditionCallback(...) 함수, 에셋의 원래 바이너리를 기반으로 새 바이너리 렌디션 생성 (1a) 및 모든 매개 변수 (1b).

    • 이 자습서에서는 렌디션이 "처리 중"으로 작성됩니다. 즉, 작업자가 렌디션을 작성하지만 소스 바이너리를 다른 웹 서비스 API로 전송하여 렌디션을 생성할 수도 있습니다.
  3. asset compute 작업자는 새 렌디션의 이진 데이터를 rendition.path.

  4. 에 기록된 이진 데이터 rendition.path 는 Asset compute SDK를 통해 AEM Author 서비스로 전송되고 로 노출됩니다. (4a) 텍스트 렌디션 및 (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() { ... }

작업자 index.js 열기

index.js 자동 생성

  1. asset compute 프로젝트가 VS 코드에서 열려 있는지 확인합니다.
  2. 다음 위치로 이동 /actions/worker 폴더
  3. 를 엽니다. index.js 파일

이 자습서에서 수정할 작업자 JavaScript 파일입니다.

지원 npm 모듈 설치 및 가져오기

Node.js를 기반으로 하는 Asset compute 프로젝트는 강력한 이점을 제공합니다 npm 모듈 에코시스템. npm 모듈을 활용하려면 먼저 Asset compute 프로젝트에 설치해야 합니다.

이 작업자에서는 집게 를 사용하여 Node.js 코드에서 직접 렌디션 이미지를 만들고 조작할 수 있습니다.

WARNING
에셋 조작을 위한 모든 npm 모듈이 Asset compute에서 지원되는 것은 아닙니다. ImageMagick 또는 기타 OS 종속 라이브러리와 같은 애플리케이션의 존재 여부에 의존하는 npm 모듈은 지원되지 않습니다. JavaScript 전용 npm 모듈 사용으로 제한하는 것이 가장 좋습니다.
  1. asset compute 프로젝트의 루트에서 명령줄을 엽니다(다음을 통해 VS 코드에서 수행할 수 있음). 터미널 > 새 터미널) 다음 명령을 실행합니다.

    code language-none
    $ npm install jimp
    
  2. 가져오기 jimp 를 통해 사용할 수 있도록 작업자 코드에 모듈을 추가합니다. Jimp JavaScript 개체입니다.
    업데이트 require 작업자의 상단에 있는 지시문 index.js 을(를) 가져오려면 Jimp 의 오브젝트 jimp 모듈:

    code language-javascript
    '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 as a Cloud Service 작성자 서비스에 정의된 처리 프로필 을 통해 전달될 수 있는 매개 변수를 읽을 수 있습니다. 매개 변수는 를 통해 작업자에게 전달됩니다. rendition.instructions 개체.

에 액세스하여 읽을 수 있습니다 rendition.instructions.<parameterName> 를 입력합니다.

여기에서는 구성 가능한 렌디션의 SIZE, BRIGHTNESSCONTRAST을 클릭하고, 처리 프로필을 통해 아무 것도 제공되지 않은 경우 기본값을 제공합니다. 참고: renditions.instructions AEM as 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
}

오류 발생 errors

Asset compute 작업자는 오류가 발생하는 상황에 직면할 수 있습니다. Adobe Asset compute SDK는 다음을 제공합니다 사전 정의된 오류 세트 이러한 상황이 발생할 때 throw될 수 있습니다. 특정 오류 유형이 적용되지 않는 경우 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);
    }
}

렌디션 만들기

매개 변수를 읽고, 정리하고, 유효성을 검사하면 렌디션을 생성하기 위한 코드가 작성됩니다. 렌디션 생성을 위한 의사 코드는 다음과 같습니다.

  1. 새로 만들기 renditionImage 을 통해 지정된 정사각형 차원의 캔버스 size 매개 변수.

  2. 만들기 image 원본 자산의 바이너리에서 개체

  3. 사용 지프 이미지를 변환할 라이브러리:

    • 원본 이미지를 가운데 사각형으로 자르기
    • "사각형" 이미지의 가운데에서 원을 자릅니다
    • 로 정의된 치수 내에 맞게 배율 조정 SIZE 매개 변수 값
    • 다음을 기반으로 대비 조정 CONTRAST 매개 변수 값
    • 다음을 기반으로 밝기 조정 BRIGHTNESS 매개 변수 값
  4. 변형을 배치합니다. image 의 가운데로 renditionImage 배경이 투명한 것

  5. 작성된 항목 작성, renditionImagerendition.path AEM에 에셋 렌디션으로 다시 저장할 수 있습니다.

이 코드는 Jim 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 개발 도구를 사용하여 실행하여 결과를 확인할 수 있습니다.

  1. asset compute 프로젝트의 루트에서

  2. 실행 aio app run

  3. asset compute 개발 도구가 새 창에서 열릴 때까지 대기

  4. 다음에서 파일 선택… 드롭다운에서 처리할 샘플 이미지를 선택합니다.

    • 소스 자산 바이너리로 사용할 샘플 이미지 파일 선택
    • 아직 존재하지 않는 경우 (+) 을(를) 왼쪽에 업로드합니다. 샘플 이미지 파일을 만들고 개발 도구 브라우저 창을 새로 고칩니다.
  5. 업데이트 "name": "rendition.png" 이 작업자로 사용하여 투명한 PNG를 생성합니다.

    • 이 "name" 매개 변수는 개발 도구에만 사용되며 를 사용하지 않아야 합니다.
    code language-json
    {
        "renditions": [
            {
                "worker": "...",
                "name": "rendition.png"
            }
        ]
    }
    
  6. 누르기 실행 렌디션이 생성될 때까지 대기

  7. 다음 표현물 섹션은 생성된 렌디션을 미리 봅니다. 렌디션 미리 보기를 탭하여 전체 렌디션 다운로드

    기본 PNG 렌디션

매개 변수를 사용하여 작업자 실행

처리 프로필 구성을 통해 전달된 매개 변수는 렌디션 매개 변수 JSON에서 키/값 쌍으로 제공하여 Asset compute 개발 도구에서 시뮬레이션할 수 있습니다.

WARNING
로컬 개발 중에 AEM에서 문자열로 Cloud Service 처리 프로필로 전달될 때 다양한 데이터 유형을 사용하여 값을 전달할 수 있으므로 필요한 경우 올바른 데이터 유형을 구문 분석해야 합니다.
예를 들어 Jimp의 crop(width, height) 함수의 매개 변수는 다음과 같아야 합니다. int's. If 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
  1. 렌디션 매개 변수를 업데이트하여 크기, 대비 및 밝기를 사용자 지정합니다.

    code language-json
    {
        "renditions": [
            {
                "worker": "...",
                "name": "rendition.png",
                "size": "450",
                "contrast": "0.30",
                "brightness": "0.15"
            }
        ]
    }
    
  2. 누르기 실행 다시

  3. 렌디션 미리 보기를 탭하여 생성된 렌디션을 다운로드하고 검토합니다. 해당 차원과 대비 및 밝기가 기본 렌디션과 비교하여 어떻게 변경되었는지 확인합니다.

    매개 변수가 있는 PNG 렌디션

  4. 에 다른 이미지 업로드 소스 파일 드롭다운을 실행하고 다른 매개 변수를 사용하여 작업자를 실행해 보십시오.

Github의 작업자 index.js

최종 index.js 의 Github에서 사용할 수 있습니다.

문제 해결

recommendation-more-help
4859a77c-7971-4ac9-8f5c-4260823c6f69