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 작성자 서비스는 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 작성자 서비스로 전송되고, (4) 가 텍스트 표현물과 (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 프로젝트에 모듈을 설치해야 합니다.

이 작업자는 gimp 변환 이미지를 직접 만들어 Node.js 코드에서 조작할 수 있습니다.

경고

자산 조작에 대한 모든 npm 모듈이 Asset compute에서 지원되는 것은 아닙니다. ImageMagick 또는 기타 OS 종속 라이브러리와 같은 응용 프로그램이 있는 npm 모듈은 지원되지 않습니다. JavaScript 전용 npm 모듈 사용을 제한하는 것이 가장 좋습니다.

  1. asset compute 프로젝트의 루트에서 명령줄을 엽니다(이 작업은 를 통해 VS 코드에서 수행할 수 있습니다.) 터미널 > 새 터미널)을 클릭하고 다음 명령을 실행합니다.

    $ npm install jimp
    
  2. 가져오기 jimp 를 통해 사용할 수 있도록 작업자 코드에 모듈 Jimp JavaScript 개체.
    업데이트 require 노동자의 맨 위에 있는 지시 index.jsJimp 개체 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 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
}

오류 발생

asset compute 작업자는 오류가 발생하는 상황이 발생할 수 있습니다. Adobe Asset compute SDK가 제공하는 사전 정의된 오류 세트 이 이벤트는 이러한 상황이 발생할 때 발생할 수 있습니다. 특정 오류 유형이 적용되지 않으면 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. 를 사용하십시오 Jimp 라이브러리를 사용하여 이미지를 변환합니다.
    • 원본 이미지를 가운데 사각형으로 자릅니다
    • "사각형" 이미지의 중심에서 원을 잘라냅니다
    • 에 의해 정의된 차원 내에 맞게 비율 조정 SIZE 매개 변수 값
    • 을 기준으로 대비 조정 CONTRAST 매개 변수 값
    • 을 기준으로 밝기 조정 BRIGHTNESS 매개 변수 값
  4. 변형된 배치 image 중앙으로 renditionImage 투명한 배경이 있는
  5. 작문, renditionImage to 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.html를 실행하면 로컬 Asset compute 개발 도구를 사용하여 결과를 확인할 수 있습니다.

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

  2. 실행 aio app run

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

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

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

    • 이 "name" 매개 변수는 개발 도구용으로만 사용되며 의존해서는 안 됩니다.
    {
        "renditions": [
            {
                "worker": "...",
                "name": "rendition.png"
            }
        ]
    }
    
  6. 실행 변환을 생성할 때까지 기다립니다.

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

    기본 PNG 표현물

매개 변수로 작업자 실행

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

경고

로컬 개발 중에 AEM에서 Cloud Service 처리 프로필로 전달된 경우 다양한 데이터 유형을 사용하여 값을 전달할 수 있으므로 필요한 경우 올바른 데이터 유형을 구문 분석해야 합니다.
예를 들어, Jimp는 crop(width, height) 함수에는 해당 매개 변수가 필요합니다 ints. 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. 변환 매개 변수를 업데이트하여 크기, 대비 및 밝기를 사용자 정의합니다.

    {
        "renditions": [
            {
                "worker": "...",
                "name": "rendition.png",
                "size": "450",
                "contrast": "0.30",
                "brightness": "0.15"
            }
        ]
    }
    
  2. 실행 다시

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

    매개 변수화된 PNG 표현물

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

Github의 Worker index.js

마지막 index.js 은 Github에서 사용할 수 있는 위치:

문제 해결

이 페이지에서는