

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# Lambda を使用してファイルをサーバーレスで処理する
<a name="tutorial-process-files-with-lambda"></a>

ファイル処理ワークフローは、多くの場合、NFS または SMB ファイル共有に到着するファイルから始まります。ブランチオフィスからスキャンされたドキュメント、フィールドチームによってアップロードされたイメージ、コンタクトセンターからキャプチャされたオーディオ、またはパートナーが配信したデータファイルです。

Amazon S3 アクセスポイントを FSx for ONTAP ボリュームにアタッチすると、 AWS Lambda 関数は Amazon S3 API を使用してファイルを直接読み書きします。ファイルレベルのオペレーションは、ユーザーとアプリケーションが NFS と SMB 経由でアクセスするのと同じデータに対してサーバーレスで処理できます。

このチュートリアルでは、3 つの一般的なファイル処理パターンを示します。各例では、アクセスポイントを介してボリュームからファイルを読み取り、 AWS サービスまたはライブラリで処理して、結果をボリュームに書き込みます。


| 例 | Input | Processing | Output | 
| --- | --- | --- | --- | 
| [例 1: イメージサムネイルを生成する](#tutorial-lambda-thumbnail) | JPEG イメージ | 枕 (イメージライブラリ) | サムネイルのサイズ変更 | 
| [例 2: ドキュメントからテキストを抽出する](#tutorial-lambda-textract) | PDF ドキュメント | Amazon Textract | 抽出されたテキスト (JSON) | 
| [例 3: オーディオファイルの文字起こし](#tutorial-lambda-transcribe) | MP3 オーディオ | Amazon Transcribe | 文字起こし (JSON) | 

**注記**  
このチュートリアルの所要時間は約 **40～60 分**です。 AWS のサービス 使用する には、作成したリソースの料金が発生します。**クリーンアップ**セクションを含むすべてのステップをすぐに完了すると、米国東部 (バージニア北部) の予想コストは **1 USD** 未満になります AWS リージョン。この見積もりには、FSx for ONTAP ボリューム自体の継続的な料金は含まれません。

## 前提条件
<a name="tutorial-lambda-prerequisites"></a>

作業を開始する前に、次の項目があることを確認します。
+ Amazon S3 アクセスポイントがアタッチされた FSx for ONTAP ボリューム。 Amazon S3 アクセスポイントの作成手順については、「」を参照してください[アクセスポイントの作成](fsxn-creating-access-points.md)。
+ アクセスポイントのアクセスポイントエイリアス。これは、Amazon FSx コンソールまたは を実行して確認できます`aws fsx describe-s3-access-point-attachments`。
+ AWS CLI バージョン 1 またはバージョン 2 がインストールされ、設定されています。このチュートリアルの`aws lambda invoke`コマンドには、raw JSON ペイロードが base64 として解釈されないように、 AWS CLI バージョン 2 で必要な `--cli-binary-format raw-in-base64-out`オプションが含まれています。 AWS CLI バージョン 1 を使用する場合は、このオプションを省略します。
+ 発信者 (このチュートリアルを実行するユーザーまたはロール) が Lambda 関数 (`lambda:CreateFunction`、`lambda:InvokeFunction`) を呼び出し、Amazon S3 アクセスポイント (`s3:GetObject`、`s3:PutObject`) にアクセスし、Lambda 実行ロール () を渡すための IAM アクセス許可`iam:PassRole`。

**注記**  
このチュートリアルでは、関数が VPC 外のマネージドネットワークで実行されるデフォルトの Lambda 設定を使用します。その場合、アクセスポイントには**インターネット**ネットワークオリジンが必要です。これにより、関数はそれに到達できます。Lambda 関数を VPC にアタッチする場合、代わりにアクセスポイントで VPC ネットワークオリジンを使用できます。VPC には Amazon S3 Gateway またはインターフェイスエンドポイントが必要です。詳細については、「[Amazon S3 アクセスポイントのネットワークアクセスの設定](configuring-network-access-for-s3-access-points.md)」を参照してください。

## ステップ 1: サンプルファイルをアップロードする
<a name="tutorial-lambda-upload-samples"></a>

次のサンプルファイルをダウンロードし、アクセスポイントを介して FSx for ONTAP ボリュームにアップロードします。このチュートリアル全体で、 をアクセスポイントエイリアス`{{my-ap-alias-ext-s3alias}}`に置き換えます。
+ **サンプルイメージ:** [NASA Blue Marble イメージ](https://eoimages.gsfc.nasa.gov/images/imagerecords/73000/73909/world.topo.bathy.200412.3x5400x2700.jpg) (パブリックドメイン、2.4 MB) をダウンロードし、 として保存します`sample-image.jpg`。
+ **サンプルオーディオ:** [Amazon Transcribe 入門チュートリアル](https://docs.aws.amazon.com/hands-on/latest/create-audio-transcript-transcribe/create-audio-transcript-transcribe.html) (410 KB) から[サンプルオーディオファイル](https://d1.awsstatic.com/tmt/create-audio-transcript-transcribe/transcribe-sample.5fc2109bb28268d10fbc677e64b7e59256783d3c.mp3)をダウンロードし、 として保存します`sample-audio.mp3`。

サンプルファイルをアクセスポイント経由で FSx for ONTAP ボリュームにアップロードします。

```
$ aws s3 cp sample-image.jpg s3://{{my-ap-alias-ext-s3alias}}/samples/images/sample-image.jpg
aws s3 cp sample-audio.mp3 s3://{{my-ap-alias-ext-s3alias}}/samples/audio/sample-audio.mp3
```

**注記**  
サンプルイメージは、NASA ブルーマーブル写真 (パブリックドメイン、2.4 MB) です。サンプルオーディオは、[Amazon Transcribe 入門チュートリアル](https://docs.aws.amazon.com/hands-on/latest/create-audio-transcript-transcribe/create-audio-transcript-transcribe.html) (410 KB) のものです。サンプル PDF は で生成されます[例 2: ドキュメントからテキストを抽出する](#tutorial-lambda-textract)。

## ステップ 2: Lambda 実行ロールを作成する
<a name="tutorial-lambda-create-role"></a>

Lambda 関数は、他の関数とやり取りするための実行ロールを引き受けます AWS のサービス。このチュートリアルでは、CloudWatch Logs ログ記録用の AWSマネージド`AWSLambdaBasicExecutionRole`ポリシーをアタッチし、Amazon S3 アクセスポイントと、例が使用する Textract API と Transcribe APIs へのアクセスを許可するインラインポリシーを追加します。

### Lambda 実行ロールを作成するには
<a name="tutorial-lambda-create-role-steps"></a>

`{{region}}`、`{{account-id}}`、 を自分の値`{{access-point-name}}`に置き換えます。

1. 次の信頼ポリシーを として保存します`trust-policy.json`。

   ```
   {
       "Version": "2012-10-17", 		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Principal": {"Service": "lambda.amazonaws.com"},
               "Action": "sts:AssumeRole"
           }
       ]
   }
   ```

1. 次のインラインアクセス許可ポリシーを として保存します`permissions-policy.json`。これにより、アクセスポイントと、サンプルが使用する追加サービスへのアクセスが許可されます。

   ```
   {
       "Version": "2012-10-17", 		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": ["s3:GetObject", "s3:PutObject", "s3:ListBucket"],
               "Resource": [
                   "arn:aws:s3:{{region}}:{{account-id}}:accesspoint/{{access-point-name}}",
                   "arn:aws:s3:{{region}}:{{account-id}}:accesspoint/{{access-point-name}}/object/*"
               ]
           },
           {
               "Effect": "Allow",
               "Action": ["textract:DetectDocumentText"],
               "Resource": "*"
           },
           {
               "Effect": "Allow",
               "Action": [
                   "transcribe:StartTranscriptionJob",
                   "transcribe:GetTranscriptionJob"
               ],
               "Resource": "*"
           }
       ]
   }
   ```

1. ロールを作成し、マネージドログ記録ポリシーをアタッチし、インラインポリシーをアタッチします。

   ```
   $ aws iam create-role \
       --role-name {{fsxn-lambda-file-processor}} \
       --assume-role-policy-document file://trust-policy.json
   
   aws iam attach-role-policy \
       --role-name {{fsxn-lambda-file-processor}} \
       --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
   
   aws iam put-role-policy \
       --role-name {{fsxn-lambda-file-processor}} \
       --policy-name fsxn-access-point-policy \
       --policy-document file://permissions-policy.json
   ```

## ワークフローへの統合
<a name="tutorial-lambda-workflow-integration"></a>

このチュートリアルの例では、テストイベントで手動呼び出しを使用します。本番環境では、以下のアプローチを使用してこれらの関数を自動的にトリガーできます。
+ **Amazon EventBridge スケジュール。**関数を定期的に (1 時間ごとや毎日など) 実行して、新しいファイルを処理します。関数は、アクセスポイントを介してファイルを一覧表示し、まだ処理されていないファイルを処理できます。詳細については、「Amazon [ EventBridge ユーザーガイド」の「EventBridge を使用して Lambda 関数をスケジュール](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-run-lambda-schedule.html)する」を参照してください。 * EventBridge *
+ **Amazon API Gateway。**ユーザーまたはアプリケーションが特定のファイルの処理をオンデマンドでリクエストできるように、関数を HTTP API として公開します。詳細については、「Amazon [API Gateway デベロッパーガイド」の「Lambda 統合を使用して API Gateway REST](https://docs.aws.amazon.com/apigateway/latest/developerguide/getting-started-with-lambda-integration.html) API を構築する」を参照してください。 *Amazon API Gateway *
+ **Step Functions。**複数の Lambda 関数を組み合わせた複数ステップのファイル処理パイプラインをオーケストレーションします。たとえば、ドキュメントからテキストを抽出し、翻訳して、結果をボリュームに書き戻すワークフローです。詳細については、「 *AWS Step Functions デベロッパーガイド*」の[「Step Functions で Lambda を呼び](https://docs.aws.amazon.com/step-functions/latest/dg/connect-lambda.html)出す」を参照してください。

## 例 1: イメージサムネイルを生成する
<a name="tutorial-lambda-thumbnail"></a>

この例では、FSx for ONTAP ボリュームから JPEG イメージを読み取り、Pillow イメージライブラリを使用して 200 ピクセルのサムネイルにサイズ変更し、サムネイルをボリュームに書き込みます。

**Lambda 関数コード**

次のコードを として保存します`lambda_function.py`。

```
import boto3
from io import BytesIO
from PIL import Image

s3 = boto3.client('s3')

def lambda_handler(event, context):
    bucket = event['access_point_alias']
    key = event['key']

    # Read the image from FSx through the access point
    response = s3.get_object(Bucket=bucket, Key=key)
    image_data = response['Body'].read()

    # Resize to thumbnail
    img = Image.open(BytesIO(image_data))
    img.thumbnail((200, 200))

    # Write the thumbnail back to FSx
    buffer = BytesIO()
    img.save(buffer, format='JPEG', quality=85)
    buffer.seek(0)

    thumbnail_key = key.rsplit('.', 1)[0] + '_thumbnail.jpg'
    s3.put_object(
        Bucket=bucket,
        Key=thumbnail_key,
        Body=buffer.getvalue(),
        ContentType='image/jpeg'
    )

    return {
        'original_size': len(image_data),
        'thumbnail_size': len(buffer.getvalue()),
        'thumbnail_key': thumbnail_key
    }
```

**関数を作成して呼び出す**

この関数には Pillow ライブラリが必要です。Lambda Linux ランタイム用に構築された Pillow を含むデプロイパッケージを作成します。

```
$ # Create a deployment package with Pillow for Lambda (Linux)
mkdir package && pip install Pillow -t package/ \
    --platform manylinux2014_x86_64 --only-binary=:all:
cd package && zip -r ../thumbnail-function.zip .
cd .. && zip thumbnail-function.zip lambda_function.py

# Create the function
aws lambda create-function \
    --function-name {{fsxn-thumbnail-generator}} \
    --runtime python3.12 \
    --handler lambda_function.lambda_handler \
    --role arn:aws:iam::{{account-id}}:role/{{fsxn-lambda-file-processor}} \
    --zip-file fileb://thumbnail-function.zip \
    --timeout 30 \
    --memory-size 256

# Invoke with a test event
aws lambda invoke \
    --function-name {{fsxn-thumbnail-generator}} \
    --cli-binary-format raw-in-base64-out \
    --payload '{"access_point_alias": "{{my-ap-alias-ext-s3alias}}", "key": "samples/images/sample-image.jpg"}' \
    response.json

cat response.json
```

**結果を確認する**

```
$ aws s3 ls s3://{{my-ap-alias-ext-s3alias}}/samples/images/
2024-01-23 12:19:32    2566770 sample-image.jpg
2024-01-23 12:25:49       7065 sample-image_thumbnail.jpg
```

元の 2.4 MB イメージ (5400 x 2700 ピクセル) は、7 KB のサムネイル (200 x 100 ピクセル) にサイズ変更されました。

## 例 2: ドキュメントからテキストを抽出する
<a name="tutorial-lambda-textract"></a>

この例では、FSx for ONTAP ボリュームから PDF ドキュメントを読み取り、Amazon Textract に送信してテキストを抽出し、抽出したテキストを JSON ファイルとしてボリュームに書き込みます。

**サンプル PDF を作成してアップロードする**

この例では、FSx for ONTAP ボリュームに PDF ドキュメントが必要です。次の Python スクリプトは、シンプルな請求書 PDF を生成し、アクセスポイントを介してアップロードします。このスクリプトをローカルマシン (Lambda ではない) で実行します。

```
$ pip install fpdf2 boto3
```

```
# create_invoice.py — run locally to generate and upload a sample PDF
from fpdf import FPDF
import boto3

pdf = FPDF()
pdf.add_page()
pdf.set_font("Helvetica", "B", 24)
pdf.cell(0, 15, "INVOICE", new_x="LMARGIN", new_y="NEXT", align="C")
pdf.set_font("Helvetica", "", 12)
pdf.cell(0, 8, "Invoice Number: INV-2024-00142", new_x="LMARGIN", new_y="NEXT")
pdf.cell(0, 8, "Date: January 15, 2024", new_x="LMARGIN", new_y="NEXT")
pdf.cell(0, 8, "Customer: Example Corp", new_x="LMARGIN", new_y="NEXT")
pdf.ln(5)
pdf.set_font("Helvetica", "B", 12)
pdf.cell(80, 8, "Description", border=1)
pdf.cell(30, 8, "Qty", border=1, align="C")
pdf.cell(40, 8, "Unit Price", border=1, align="R")
pdf.cell(40, 8, "Amount", border=1, align="R")
pdf.ln()
pdf.set_font("Helvetica", "", 12)
for desc, qty, price, amt in [
    ("Cloud Storage Service", "1", "$2,400.00", "$2,400.00"),
    ("Data Transfer (TB)", "5", "$90.00", "$450.00"),
    ("Technical Support", "1", "$500.00", "$500.00"),
]:
    pdf.cell(80, 8, desc, border=1)
    pdf.cell(30, 8, qty, border=1, align="C")
    pdf.cell(40, 8, price, border=1, align="R")
    pdf.cell(40, 8, amt, border=1, align="R")
    pdf.ln()

s3 = boto3.client('s3')
s3.put_object(
    Bucket='{{my-ap-alias-ext-s3alias}}',
    Key='samples/documents/invoice.pdf',
    Body=pdf.output(),
    ContentType='application/pdf'
)
print("Uploaded invoice.pdf")
```

```
$ python3 create_invoice.py
```

**Lambda 関数コード**

次のコードを として保存します`lambda_function.py`。

```
import boto3
import json

s3 = boto3.client('s3')
textract = boto3.client('textract')

def lambda_handler(event, context):
    bucket = event['access_point_alias']
    key = event['key']

    # Read the PDF from FSx through the access point
    response = s3.get_object(Bucket=bucket, Key=key)
    document_bytes = response['Body'].read()

    # Extract text with Textract
    textract_response = textract.detect_document_text(
        Document={'Bytes': document_bytes}
    )

    lines = [
        block['Text']
        for block in textract_response['Blocks']
        if block['BlockType'] == 'LINE'
    ]

    # Write extracted text as JSON back to FSx
    result = {
        'source_file': key,
        'total_lines': len(lines),
        'extracted_text': lines
    }

    output_key = key.rsplit('.', 1)[0] + '_extracted.json'
    s3.put_object(
        Bucket=bucket,
        Key=output_key,
        Body=json.dumps(result, indent=2),
        ContentType='application/json'
    )

    return {
        'lines_extracted': len(lines),
        'output_key': output_key
    }
```

**関数を作成して呼び出す**

```
$ zip textract-function.zip lambda_function.py

aws lambda create-function \
    --function-name {{fsxn-text-extractor}} \
    --runtime python3.12 \
    --handler lambda_function.lambda_handler \
    --role arn:aws:iam::{{account-id}}:role/{{fsxn-lambda-file-processor}} \
    --zip-file fileb://textract-function.zip \
    --timeout 30 \
    --memory-size 256

aws lambda invoke \
    --function-name {{fsxn-text-extractor}} \
    --cli-binary-format raw-in-base64-out \
    --payload '{"access_point_alias": "{{my-ap-alias-ext-s3alias}}", "key": "samples/documents/invoice.pdf"}' \
    response.json

cat response.json
```

出力の例:

```
{"lines_extracted": 22, "output_key": "samples/documents/invoice_extracted.json"}
```

## 例 3: オーディオファイルの文字起こし
<a name="tutorial-lambda-transcribe"></a>

この例では、FSx for ONTAP ボリュームに保存されているオーディオファイルの Amazon Transcribe ジョブを開始します。Amazon Transcribe は、メディアファイル URI のアクセスポイントエイリアスを使用して、アクセスポイントから直接オーディオファイルを読み取ります。ジョブが完了すると、関数はトランスクリプトをボリュームに書き込みます。

**Lambda 関数コード**

次のコードを として保存します`lambda_function.py`。

```
import boto3
import json
import time
import urllib.request

s3 = boto3.client('s3')
transcribe = boto3.client('transcribe')

def lambda_handler(event, context):
    bucket = event['access_point_alias']
    key = event['key']
    media_format = key.rsplit('.', 1)[-1]  # mp3, wav, etc.

    # Start a Transcribe job pointing to the file on FSx
    job_name = f"fsxn-{int(time.time())}"
    transcribe.start_transcription_job(
        TranscriptionJobName=job_name,
        Media={'MediaFileUri': f's3://{bucket}/{key}'},
        MediaFormat=media_format,
        LanguageCode='en-US'
    )

    # Wait for the job to complete
    while True:
        status = transcribe.get_transcription_job(
            TranscriptionJobName=job_name
        )
        state = status['TranscriptionJob']['TranscriptionJobStatus']
        if state in ('COMPLETED', 'FAILED'):
            break
        time.sleep(5)

    if state == 'FAILED':
        raise Exception(
            status['TranscriptionJob'].get('FailureReason', 'Unknown error')
        )

    # Download the transcript
    transcript_uri = status['TranscriptionJob']['Transcript']['TranscriptFileUri']
    with urllib.request.urlopen(transcript_uri) as resp:
        transcript_data = json.loads(resp.read())

    transcript_text = transcript_data['results']['transcripts'][0]['transcript']

    # Write the transcript back to FSx
    result = {
        'source_file': key,
        'job_name': job_name,
        'transcript': transcript_text
    }

    output_key = key.rsplit('.', 1)[0] + '_transcript.json'
    s3.put_object(
        Bucket=bucket,
        Key=output_key,
        Body=json.dumps(result, indent=2),
        ContentType='application/json'
    )

    return {
        'transcript_length': len(transcript_text),
        'output_key': output_key
    }
```

**関数を作成して呼び出す**

```
$ zip transcribe-function.zip lambda_function.py

aws lambda create-function \
    --function-name {{fsxn-audio-transcriber}} \
    --runtime python3.12 \
    --handler lambda_function.lambda_handler \
    --role arn:aws:iam::{{account-id}}:role/{{fsxn-lambda-file-processor}} \
    --zip-file fileb://transcribe-function.zip \
    --timeout 120

aws lambda invoke \
    --function-name {{fsxn-audio-transcriber}} \
    --cli-binary-format raw-in-base64-out \
    --payload '{"access_point_alias": "{{my-ap-alias-ext-s3alias}}", "key": "samples/audio/sample-audio.mp3"}' \
    --cli-read-timeout 180 \
    response.json

cat response.json
```

**注記**  
Transcribe ジョブの完了には通常 15～45 秒かかります。これを可能にするために、関数のタイムアウトは 120 秒に設定されます。

## 考慮事項
<a name="tutorial-lambda-considerations"></a>
+ **デフォルト設定に必要なインターネットオリジン。**デフォルトでは、Lambda は VPC 外のマネージドインフラストラクチャから Amazon S3 にアクセスします。これにはインターネットオリジンアクセスポイントが必要です。Lambda 関数を VPC にアタッチする場合は、代わりに VPC オリジンアクセスポイントを使用できます。詳細については、前提条件を参照してください。
+ **ファイルサイズ制限。**Lambda 関数の最大メモリは 10 GB、最大実行時間は 15 分です。大きなファイルの場合は、範囲読み取り (`GetObject` `Range`ヘッダー付き) を使用するか、レスポンスをストリーミングすることを検討してください。
+ **抽出の制限。**同期 `DetectDocumentText` API は、最大 10 MB のドキュメントと 1 ページを受け入れます。マルチページドキュメントの場合は、非同期 `StartDocumentTextDetection` API を使用します。
+ **書き起こしはアクセスポイントから直接読み取ります。**Amazon Transcribe は、 `MediaFileUri`パラメータ () でアクセスポイントエイリアスを受け入れます`s3://{{ap-alias}}/{{key}}`。Lambda 関数は、オーディオファイルをダウンロードして再アップロードする必要はありません。
+ **ファイルシステムのユーザーアクセス許可。**アクセスポイントに関連付けられたファイルシステムユーザーには、入力ファイルに対する読み取りアクセス許可と、出力ディレクトリに対する書き込みアクセス許可が必要です。

## クリーンアップ
<a name="tutorial-lambda-clean-up"></a>

継続的な課金を回避するには、このチュートリアルで作成したリソースを削除します。

```
$ # Delete Lambda functions
aws lambda delete-function --function-name {{fsxn-thumbnail-generator}}
aws lambda delete-function --function-name {{fsxn-text-extractor}}
aws lambda delete-function --function-name {{fsxn-audio-transcriber}}

# Delete the IAM role and policies
aws iam delete-role-policy \
    --role-name {{fsxn-lambda-file-processor}} \
    --policy-name fsxn-access-point-policy
aws iam detach-role-policy \
    --role-name {{fsxn-lambda-file-processor}} \
    --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
aws iam delete-role --role-name {{fsxn-lambda-file-processor}}

# Delete sample files from your FSx volume
aws s3 rm s3://{{my-ap-alias-ext-s3alias}}/samples/ --recursive
```