From 2122a04b678c836a2d35a0439f65c96ddeab182f Mon Sep 17 00:00:00 2001 From: Achintya Veer Singh Date: Thu, 6 Mar 2025 12:43:42 +0530 Subject: [PATCH 01/11] Adding the apigw-lambda-transcribe-sam-js branch --- apigw-lambda-transcribe-sam-js/README.md | 86 +++++++++++++++++++ .../example-pattern.json | 62 +++++++++++++ apigw-lambda-transcribe-sam-js/src/app.mjs | 37 ++++++++ apigw-lambda-transcribe-sam-js/template.yaml | 50 +++++++++++ 4 files changed, 235 insertions(+) create mode 100644 apigw-lambda-transcribe-sam-js/README.md create mode 100644 apigw-lambda-transcribe-sam-js/example-pattern.json create mode 100644 apigw-lambda-transcribe-sam-js/src/app.mjs create mode 100644 apigw-lambda-transcribe-sam-js/template.yaml diff --git a/apigw-lambda-transcribe-sam-js/README.md b/apigw-lambda-transcribe-sam-js/README.md new file mode 100644 index 000000000..6f09668b5 --- /dev/null +++ b/apigw-lambda-transcribe-sam-js/README.md @@ -0,0 +1,86 @@ +# Amazon API Gateway to AWS Lambda to Amazon Transcribe using AWS SAM + +This pattern facilitates audio transcription by using Amazon Transcribe service through a serverless API endpoint. When audio files are uploaded to S3, they can be transcribed using Amazon Transcribe via an API Gateway endpoint backed by Lambda. + +This pattern enables speech-to-text transcription use cases by providing a serverless API endpoint that can process audio files stored in S3. The pattern uses AWS Lambda to coordinate with Amazon Transcribe service, making it easy to integrate transcription capabilities into your applications. + +Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the [AWS Pricing page](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred. No warranty is implied in this example. + +## Requirements + +* [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources. +* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured +* [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) +* [AWS Serverless Application Model](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) (AWS SAM) installed + +## Deployment Instructions + +1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository: + ``` + git clone https://github.com/aws-samples/serverless-patterns + ``` +1. Change directory to the pattern directory: + ``` + cd apigw-lambda-transcribe-sam-js + ``` +1. From the command line, use AWS SAM to deploy the AWS resources for the pattern as specified in the template.yaml file: + ``` + sam deploy --guided + ``` +1. During the prompts: + * Enter a stack name + * Enter the desired AWS Region + * Allow SAM CLI to create IAM roles with the required permissions. + + Once you have run `sam deploy --guided` mode once and saved arguments to a configuration file (samconfig.toml), you can use `sam deploy` in future to use these defaults. + +2. Note the outputs from the SAM deployment process. These contain the resource names and/or ARNs which are used for testing. + +## How it works + +The pattern creates an API Gateway endpoint that accepts POST requests with JSON payloads containing an S3 URL of an audio file. When a request is received: + +1. API Gateway forwards the request to AWS Lambda +2. Lambda function starts a transcription job using Amazon Transcribe +3. Amazon Transcribe processes the audio file and generates the transcription +4. The transcription results are stored in the specified S3 bucket + +## Testing + +To test the deployed API endpoint: + +1. Upload an audio file to the created S3 bucket: +``` +aws s3 cp audio.mp3 s3://your-bucket-name/ +``` +2. Get the S3 URL of the uploaded audio file +3. Make a POST request to the API Gateway endpoint with the following JSON payload: + +```bash +curl -X POST https://your-api-endpoint/Prod/transcribe \ + -H "Content-Type: application/json" \ + -d '{"audio_url": "s3://your-bucket-name/audio.mp3"}' +``` +4. The API will return a response with the transcription job name and status +```json +{ + "job_name": "transcribe-12345678-1234-5678-1234-567812345678", + "status": "IN_PROGRESS" +} +``` +5. You can check the transcription results in the S3 bucket once the job is complete: + +```bash +aws transcribe get-transcription-job --transcription-job-name "job-name-from-response" +``` +## Cleanup + +1. Delete the stack + ```bash + sam delete + ``` + +---- +Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +SPDX-License-Identifier: MIT-0 \ No newline at end of file diff --git a/apigw-lambda-transcribe-sam-js/example-pattern.json b/apigw-lambda-transcribe-sam-js/example-pattern.json new file mode 100644 index 000000000..d1fc7d0d9 --- /dev/null +++ b/apigw-lambda-transcribe-sam-js/example-pattern.json @@ -0,0 +1,62 @@ +{ + "title": "Amazon API Gateway to AWS Lambda to Amazon Transcribe using AWS SAM", + "description": "This pattern creates a serverless API endpoint using API Gateway and Lambda to transcribe audio files stored in S3 using Amazon Transcribe.", + "language": "Javascript", + "level": "200", + "framework": "SAM", + "introBox": { + "headline": "How it works", + "text": [ + "When a POST request is made to the API Gateway endpoint with an S3 audio file URL, it triggers a Lambda function that starts a transcription job using Amazon Transcribe. The Lambda function sends the audio file location to Amazon Transcribe service, which processes the audio and generates text transcription that can be retrieved from the specified S3 bucket." + ] + }, + "gitHub": { + "template": { + "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/apigw-lambda-transcribe-sam-js", + "templateURL": "serverless-patterns/apigw-lambda-transcribe-sam-js", + "projectFolder": "apigw-lambda-transcribe-sam-js", + "templateFile": "template.yaml" + } + }, + "resources": { + "bullets": [ + { + "text": "Amazon S3", + "link": "https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html" + }, + { + "text": "AWS Lambda", + "link": "https://docs.aws.amazon.com/lambda/latest/dg/welcome.html" + }, + { + "text": "Amazon Transcribe", + "link": "https://docs.aws.amazon.com/transcribe/latest/dg/what-is.html" + } + ] + }, + "deploy": { + "text": [ + "sam build", + "sam deploy --guided" + ] + }, + "testing": { + "text": [ + "See the GitHub repo for detailed testing instructions." + ] + }, + "cleanup": { + "text": [ + "sam delete" + ] + }, + "authors": [ + { + "name": "Achintya Veer Singh", + "image": "https://avatars.githubusercontent.com/u/55053737?v=4", + "bio": "Solutions Architect @ AWS", + "linkedin": "www.linkedin.com/in/achintya-veer-singh-493403193", + "twitter": "achintya_veer" + } + ] +} \ No newline at end of file diff --git a/apigw-lambda-transcribe-sam-js/src/app.mjs b/apigw-lambda-transcribe-sam-js/src/app.mjs new file mode 100644 index 000000000..3769a1f50 --- /dev/null +++ b/apigw-lambda-transcribe-sam-js/src/app.mjs @@ -0,0 +1,37 @@ +import { TranscribeClient, StartTranscriptionJobCommand } from "@aws-sdk/client-transcribe"; +import { randomUUID } from 'crypto'; + +export const lambda_handler = async (event, context) => { + try { + const requestBody = JSON.parse(event.body); + const s3_url = requestBody.audio_url; + + const transcribe = new TranscribeClient(); + const job_name = `transcribe-${randomUUID()}`; + + const command = new StartTranscriptionJobCommand({ + TranscriptionJobName: job_name, + Media: { MediaFileUri: s3_url }, + MediaFormat: 'mp3', // Adjust based on your needs + LanguageCode: 'en-US' // Adjust based on your needs + }); + + await transcribe.send(command); + + return { + statusCode: 200, + body: JSON.stringify({ + job_name: job_name, + status: 'IN_PROGRESS' + }) + }; + + } catch (e) { + return { + statusCode: 500, + body: JSON.stringify({ + error: e.toString() + }) + }; + } +}; \ No newline at end of file diff --git a/apigw-lambda-transcribe-sam-js/template.yaml b/apigw-lambda-transcribe-sam-js/template.yaml new file mode 100644 index 000000000..d3fb887c8 --- /dev/null +++ b/apigw-lambda-transcribe-sam-js/template.yaml @@ -0,0 +1,50 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: Audio transcription using Amazon Transcribe + +Resources: + TranscribeFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: src/ + Handler: app.lambda_handler + Runtime: nodejs20.x + Timeout: 900 + MemorySize: 128 + Policies: + - Statement: + - Effect: Allow + Action: + - transcribe:StartTranscriptionJob + - transcribe:GetTranscriptionJob + Resource: '*' + - Statement: + - Effect: Allow + Action: + - s3:GetObject + - s3:PutObject + Resource: !Sub 'arn:aws:s3:::${AudioBucket}/*' + Environment: + Variables: + BUCKET_NAME: !Ref AudioBucket + Events: + TranscribeAPI: + Type: Api + Properties: + Path: /transcribe + Method: post + + AudioBucket: + Type: AWS::S3::Bucket + Properties: + CorsConfiguration: + CorsRules: + - AllowedHeaders: ['*'] + AllowedMethods: [GET, PUT, POST] + AllowedOrigins: ['*'] + MaxAge: 3000 + +Outputs: + TranscribeApi: + Description: API Gateway endpoint URL + Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/transcribe" \ No newline at end of file From a217ea09bea39445dee044f2134de23952439f3e Mon Sep 17 00:00:00 2001 From: Achintya Veer Singh <55053737+Avs163@users.noreply.github.com> Date: Tue, 11 Mar 2025 12:46:40 +0530 Subject: [PATCH 02/11] Update template.yaml --- apigw-lambda-transcribe-sam-js/template.yaml | 118 +++++++++++++------ 1 file changed, 82 insertions(+), 36 deletions(-) diff --git a/apigw-lambda-transcribe-sam-js/template.yaml b/apigw-lambda-transcribe-sam-js/template.yaml index d3fb887c8..e747a3ef9 100644 --- a/apigw-lambda-transcribe-sam-js/template.yaml +++ b/apigw-lambda-transcribe-sam-js/template.yaml @@ -1,50 +1,96 @@ AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 -Description: Audio transcription using Amazon Transcribe +Description: S3 to Lambda to Transcription Job Resources: - TranscribeFunction: + AudioBucket: + Type: AWS::S3::Bucket + DependsOn: LambdaInvokePermission + Properties: + BucketName: !Sub "${AWS::StackName}-audio-uploads" + NotificationConfiguration: + LambdaConfigurations: + - Event: s3:ObjectCreated:* + Filter: + S3Key: + Rules: + - Name: suffix + Value: .mp3 + Function: !GetAtt TranscriptionFunction.Arn + - Event: s3:ObjectCreated:* + Filter: + S3Key: + Rules: + - Name: suffix + Value: .wav + Function: !GetAtt TranscriptionFunction.Arn + - Event: s3:ObjectCreated:* + Filter: + S3Key: + Rules: + - Name: suffix + Value: .flac + Function: !GetAtt TranscriptionFunction.Arn + + TranscriptionFunctionRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: lambda.amazonaws.com + Action: sts:AssumeRole + ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole + Policies: + - PolicyName: S3AndTranscribeAccess + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - s3:GetObject + - s3:PutObject + - s3:ListBucket + Resource: + - !Sub "arn:aws:s3:::${AWS::StackName}-audio-uploads" + - !Sub "arn:aws:s3:::${AWS::StackName}-audio-uploads/*" + - Effect: Allow + Action: + - transcribe:StartTranscriptionJob + - transcribe:GetTranscriptionJob + Resource: "*" + + TranscriptionFunction: Type: AWS::Serverless::Function Properties: - CodeUri: src/ - Handler: app.lambda_handler + CodeUri: ./src/ + Handler: app.handler Runtime: nodejs20.x - Timeout: 900 + Timeout: 30 MemorySize: 128 - Policies: - - Statement: - - Effect: Allow - Action: - - transcribe:StartTranscriptionJob - - transcribe:GetTranscriptionJob - Resource: '*' - - Statement: - - Effect: Allow - Action: - - s3:GetObject - - s3:PutObject - Resource: !Sub 'arn:aws:s3:::${AudioBucket}/*' + Role: !GetAtt TranscriptionFunctionRole.Arn Environment: Variables: - BUCKET_NAME: !Ref AudioBucket - Events: - TranscribeAPI: - Type: Api - Properties: - Path: /transcribe - Method: post + BUCKET_NAME: !Sub "${AWS::StackName}-audio-uploads" + REGION: !Ref AWS::Region - AudioBucket: - Type: AWS::S3::Bucket + LambdaInvokePermission: + Type: AWS::Lambda::Permission Properties: - CorsConfiguration: - CorsRules: - - AllowedHeaders: ['*'] - AllowedMethods: [GET, PUT, POST] - AllowedOrigins: ['*'] - MaxAge: 3000 + FunctionName: !Ref TranscriptionFunction + Action: lambda:InvokeFunction + Principal: s3.amazonaws.com + SourceAccount: !Ref AWS::AccountId + SourceArn: !Sub "arn:aws:s3:::${AWS::StackName}-audio-uploads" Outputs: - TranscribeApi: - Description: API Gateway endpoint URL - Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/transcribe" \ No newline at end of file + AudioBucketName: + Description: "S3 bucket for audio uploads" + Value: !Sub "${AWS::StackName}-audio-uploads" + + TranscriptionFunctionName: + Description: "Lambda function name" + Value: !Ref TranscriptionFunction From b9120a0916ba52709176f36691e8683a85f5a824 Mon Sep 17 00:00:00 2001 From: Achintya Veer Singh <55053737+Avs163@users.noreply.github.com> Date: Tue, 11 Mar 2025 12:47:40 +0530 Subject: [PATCH 03/11] Update app.mjs --- apigw-lambda-transcribe-sam-js/src/app.mjs | 109 ++++++++++++++------- 1 file changed, 74 insertions(+), 35 deletions(-) diff --git a/apigw-lambda-transcribe-sam-js/src/app.mjs b/apigw-lambda-transcribe-sam-js/src/app.mjs index 3769a1f50..121665c0b 100644 --- a/apigw-lambda-transcribe-sam-js/src/app.mjs +++ b/apigw-lambda-transcribe-sam-js/src/app.mjs @@ -1,37 +1,76 @@ -import { TranscribeClient, StartTranscriptionJobCommand } from "@aws-sdk/client-transcribe"; -import { randomUUID } from 'crypto'; +import { S3Client, GetObjectCommand } from '@aws-sdk/client-s3'; +import { TranscribeClient, StartTranscriptionJobCommand } from '@aws-sdk/client-transcribe'; -export const lambda_handler = async (event, context) => { - try { - const requestBody = JSON.parse(event.body); - const s3_url = requestBody.audio_url; - - const transcribe = new TranscribeClient(); - const job_name = `transcribe-${randomUUID()}`; - - const command = new StartTranscriptionJobCommand({ - TranscriptionJobName: job_name, - Media: { MediaFileUri: s3_url }, - MediaFormat: 'mp3', // Adjust based on your needs - LanguageCode: 'en-US' // Adjust based on your needs - }); - - await transcribe.send(command); - - return { - statusCode: 200, - body: JSON.stringify({ - job_name: job_name, - status: 'IN_PROGRESS' - }) - }; - - } catch (e) { - return { - statusCode: 500, - body: JSON.stringify({ - error: e.toString() - }) - }; +const s3Client = new S3Client({ region: process.env.REGION }); +const transcribeClient = new TranscribeClient({ region: process.env.REGION }); + +export const handler = async (event) => { + try { + // Get the S3 bucket and key from the event + const bucket = event.Records[0].s3.bucket.name; + const key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' ')); + + console.log(`Processing file: s3://${bucket}/${key}`); + + // Extract file name and extension for the transcription job + const fileName = key.split('/').pop(); + const fileNameWithoutExt = fileName.substring(0, fileName.lastIndexOf('.')) || fileName; + const fileExt = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase(); + + // Determine media format based on file extension + let mediaFormat; + switch (fileExt) { + case 'mp3': + mediaFormat = 'mp3'; + break; + case 'wav': + mediaFormat = 'wav'; + break; + case 'flac': + mediaFormat = 'flac'; + break; + default: + throw new Error(`Unsupported file format: ${fileExt}`); } -}; \ No newline at end of file + + const transcriptionJobName = `${fileNameWithoutExt}-${Date.now()}`; + + const mediaFileUri = `s3://${bucket}/${key}`; + + const startTranscriptionParams = { + TranscriptionJobName: transcriptionJobName, + LanguageCode: 'en-US', + MediaFormat: mediaFormat, + Media: { + MediaFileUri: mediaFileUri + }, + OutputBucketName: bucket, + OutputKey: `transcriptions/${fileNameWithoutExt}.json` + }; + + const transcriptionCommand = new StartTranscriptionJobCommand(startTranscriptionParams); + const transcriptionResponse = await transcribeClient.send(transcriptionCommand); + + console.log(`Started transcription job: ${transcriptionJobName}`); + console.log(`Transcription job response: ${JSON.stringify(transcriptionResponse)}`); + + return { + statusCode: 200, + body: JSON.stringify({ + message: 'Transcription job started successfully', + jobName: transcriptionJobName, + jobStatus: transcriptionResponse.TranscriptionJob.TranscriptionJobStatus + }) + }; + } catch (error) { + console.error('Error processing the file:', error); + + return { + statusCode: 500, + body: JSON.stringify({ + message: 'Error starting transcription job', + error: error.message + }) + }; + } +}; From f45789d592fc5d2f91bb63615271083e4b3d1f0b Mon Sep 17 00:00:00 2001 From: Achintya Veer Singh <55053737+Avs163@users.noreply.github.com> Date: Tue, 11 Mar 2025 12:50:36 +0530 Subject: [PATCH 04/11] Update example-pattern.json --- .../example-pattern.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/apigw-lambda-transcribe-sam-js/example-pattern.json b/apigw-lambda-transcribe-sam-js/example-pattern.json index d1fc7d0d9..1f2fa3479 100644 --- a/apigw-lambda-transcribe-sam-js/example-pattern.json +++ b/apigw-lambda-transcribe-sam-js/example-pattern.json @@ -1,20 +1,20 @@ { - "title": "Amazon API Gateway to AWS Lambda to Amazon Transcribe using AWS SAM", - "description": "This pattern creates a serverless API endpoint using API Gateway and Lambda to transcribe audio files stored in S3 using Amazon Transcribe.", + "title": "Amazon S3 to AWS Lambda to Amazon Transcribe using AWS SAM", + "description": "This pattern creates a serverless pipeline that automatically triggers an Amazon Transcribe job when audio files are uploaded to an S3 bucket, using Lambda to orchestrate the transcription process.", "language": "Javascript", "level": "200", "framework": "SAM", "introBox": { "headline": "How it works", "text": [ - "When a POST request is made to the API Gateway endpoint with an S3 audio file URL, it triggers a Lambda function that starts a transcription job using Amazon Transcribe. The Lambda function sends the audio file location to Amazon Transcribe service, which processes the audio and generates text transcription that can be retrieved from the specified S3 bucket." + "When audio files are uploaded to the S3 bucket, it automatically triggers a Lambda function that starts a transcription job using Amazon Transcribe. The Lambda function extracts information about the uploaded audio file and sends it to the Amazon Transcribe service, which processes the audio and generates a text transcription that is saved back to the specified S3 bucket in the "transcriptions" folder." ] }, "gitHub": { "template": { - "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/apigw-lambda-transcribe-sam-js", - "templateURL": "serverless-patterns/apigw-lambda-transcribe-sam-js", - "projectFolder": "apigw-lambda-transcribe-sam-js", + "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/lambda-transcribe-sam-js", + "templateURL": "serverless-patterns/lambda-transcribe-sam-js", + "projectFolder": "lambda-transcribe-sam-js", "templateFile": "template.yaml" } }, @@ -59,4 +59,4 @@ "twitter": "achintya_veer" } ] -} \ No newline at end of file +} From cec8cda53e6339725cfbc5900a2a503b2bb9d3e0 Mon Sep 17 00:00:00 2001 From: Achintya Veer Singh <55053737+Avs163@users.noreply.github.com> Date: Tue, 11 Mar 2025 12:56:23 +0530 Subject: [PATCH 05/11] Update README.md --- apigw-lambda-transcribe-sam-js/README.md | 25 ++++++++---------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/apigw-lambda-transcribe-sam-js/README.md b/apigw-lambda-transcribe-sam-js/README.md index 6f09668b5..0c0a826a8 100644 --- a/apigw-lambda-transcribe-sam-js/README.md +++ b/apigw-lambda-transcribe-sam-js/README.md @@ -1,8 +1,8 @@ -# Amazon API Gateway to AWS Lambda to Amazon Transcribe using AWS SAM +# Amazon AS3 to AWS Lambda to Amazon Transcribe using AWS SAM -This pattern facilitates audio transcription by using Amazon Transcribe service through a serverless API endpoint. When audio files are uploaded to S3, they can be transcribed using Amazon Transcribe via an API Gateway endpoint backed by Lambda. +This pattern facilitates automatic audio transcription by using the Amazon Transcribe service through a serverless event-driven architecture. When audio files are uploaded to S3, they are automatically transcribed using Amazon Transcribe via a Lambda function triggered by S3 events. -This pattern enables speech-to-text transcription use cases by providing a serverless API endpoint that can process audio files stored in S3. The pattern uses AWS Lambda to coordinate with Amazon Transcribe service, making it easy to integrate transcription capabilities into your applications. +This pattern enables speech-to-text transcription use cases by providing a serverless event-based pipeline that can process audio files uploaded to S3. The pattern uses AWS Lambda to coordinate with the Amazon Transcribe service, making it easy to integrate transcription capabilities into your applications without the need to manage infrastructure or manually initiate transcription jobs. Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the [AWS Pricing page](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred. No warranty is implied in this example. @@ -21,7 +21,7 @@ Important: this application uses various AWS services and there are costs associ ``` 1. Change directory to the pattern directory: ``` - cd apigw-lambda-transcribe-sam-js + cd lambda-transcribe-sam-js ``` 1. From the command line, use AWS SAM to deploy the AWS resources for the pattern as specified in the template.yaml file: ``` @@ -54,21 +54,12 @@ To test the deployed API endpoint: aws s3 cp audio.mp3 s3://your-bucket-name/ ``` 2. Get the S3 URL of the uploaded audio file -3. Make a POST request to the API Gateway endpoint with the following JSON payload: +3. You can list all transcription jobs using: ```bash -curl -X POST https://your-api-endpoint/Prod/transcribe \ - -H "Content-Type: application/json" \ - -d '{"audio_url": "s3://your-bucket-name/audio.mp3"}' +aws transcribe list-transcription-jobs ``` -4. The API will return a response with the transcription job name and status -```json -{ - "job_name": "transcribe-12345678-1234-5678-1234-567812345678", - "status": "IN_PROGRESS" -} -``` -5. You can check the transcription results in the S3 bucket once the job is complete: +4. You can check the transcription results in the S3 bucket once the job is complete: ```bash aws transcribe get-transcription-job --transcription-job-name "job-name-from-response" @@ -83,4 +74,4 @@ aws transcribe get-transcription-job --transcription-job-name "job-name-from-res ---- Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. -SPDX-License-Identifier: MIT-0 \ No newline at end of file +SPDX-License-Identifier: MIT-0 From c5e090c2f6e3dbb717402e33c55073f34f0c963f Mon Sep 17 00:00:00 2001 From: Achintya Veer Singh <55053737+Avs163@users.noreply.github.com> Date: Mon, 24 Mar 2025 11:09:49 +0530 Subject: [PATCH 06/11] Apply suggestions from code review Co-authored-by: ellisms <114107920+ellisms@users.noreply.github.com> --- apigw-lambda-transcribe-sam-js/README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/apigw-lambda-transcribe-sam-js/README.md b/apigw-lambda-transcribe-sam-js/README.md index 0c0a826a8..369162eab 100644 --- a/apigw-lambda-transcribe-sam-js/README.md +++ b/apigw-lambda-transcribe-sam-js/README.md @@ -1,6 +1,6 @@ -# Amazon AS3 to AWS Lambda to Amazon Transcribe using AWS SAM +# Amazon S3 to AWS Lambda to Amazon Transcribe using AWS SAM -This pattern facilitates automatic audio transcription by using the Amazon Transcribe service through a serverless event-driven architecture. When audio files are uploaded to S3, they are automatically transcribed using Amazon Transcribe via a Lambda function triggered by S3 events. +This pattern facilitates automatic audio transcription by using the Amazon Transcribe service through a serverless event-driven architecture. When audio files are uploaded to S3, they are automatically transcribed using Amazon Transcribe via a Lambda function invoked by S3 events. This pattern enables speech-to-text transcription use cases by providing a serverless event-based pipeline that can process audio files uploaded to S3. The pattern uses AWS Lambda to coordinate with the Amazon Transcribe service, making it easy to integrate transcription capabilities into your applications without the need to manage infrastructure or manually initiate transcription jobs. @@ -32,15 +32,14 @@ Important: this application uses various AWS services and there are costs associ * Enter the desired AWS Region * Allow SAM CLI to create IAM roles with the required permissions. - Once you have run `sam deploy --guided` mode once and saved arguments to a configuration file (samconfig.toml), you can use `sam deploy` in future to use these defaults. + After running `sam deploy --guided` mode once and savings arguments to a configuration file (samconfig.toml), you can use `sam deploy` in future to use these defaults. 2. Note the outputs from the SAM deployment process. These contain the resource names and/or ARNs which are used for testing. ## How it works -The pattern creates an API Gateway endpoint that accepts POST requests with JSON payloads containing an S3 URL of an audio file. When a request is received: +When an object is uploaded to S3: -1. API Gateway forwards the request to AWS Lambda 2. Lambda function starts a transcription job using Amazon Transcribe 3. Amazon Transcribe processes the audio file and generates the transcription 4. The transcription results are stored in the specified S3 bucket From 0fd6655b8cc6b4e060659998b430f0be0980907c Mon Sep 17 00:00:00 2001 From: Achintya Veer Singh <55053737+Avs163@users.noreply.github.com> Date: Mon, 24 Mar 2025 11:42:55 +0530 Subject: [PATCH 07/11] Updated README.md with suggested changes --- apigw-lambda-transcribe-sam-js/README.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/apigw-lambda-transcribe-sam-js/README.md b/apigw-lambda-transcribe-sam-js/README.md index 369162eab..fb3d086b4 100644 --- a/apigw-lambda-transcribe-sam-js/README.md +++ b/apigw-lambda-transcribe-sam-js/README.md @@ -31,7 +31,7 @@ Important: this application uses various AWS services and there are costs associ * Enter a stack name * Enter the desired AWS Region * Allow SAM CLI to create IAM roles with the required permissions. - + * Allow TranscribeFunction to operate without authentication. After running `sam deploy --guided` mode once and savings arguments to a configuration file (samconfig.toml), you can use `sam deploy` in future to use these defaults. 2. Note the outputs from the SAM deployment process. These contain the resource names and/or ARNs which are used for testing. @@ -48,7 +48,7 @@ When an object is uploaded to S3: To test the deployed API endpoint: -1. Upload an audio file to the created S3 bucket: +1. Upload an audio file to the created S3 bucket(Note: Bucket name would be {AWS::StackName}-audio-uploads): ``` aws s3 cp audio.mp3 s3://your-bucket-name/ ``` @@ -64,8 +64,12 @@ aws transcribe list-transcription-jobs aws transcribe get-transcription-job --transcription-job-name "job-name-from-response" ``` ## Cleanup - -1. Delete the stack + +1. Delete the audio.mp3 file from the S3 bucket. This is because the bucket must be empty before it can be deleted. + ```bash + aws s3 rm "s3://your-bucket-name/audio.mp3" + ``` +2. Delete the stack ```bash sam delete ``` From 8aa8be12227b504771b9bff0d5aae4a8f4fde999 Mon Sep 17 00:00:00 2001 From: Achintya Veer Singh <55053737+Avs163@users.noreply.github.com> Date: Mon, 24 Mar 2025 11:45:31 +0530 Subject: [PATCH 08/11] Updated template.yaml Upgraded version to 22.x --- apigw-lambda-transcribe-sam-js/template.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apigw-lambda-transcribe-sam-js/template.yaml b/apigw-lambda-transcribe-sam-js/template.yaml index e747a3ef9..d57e60117 100644 --- a/apigw-lambda-transcribe-sam-js/template.yaml +++ b/apigw-lambda-transcribe-sam-js/template.yaml @@ -68,7 +68,7 @@ Resources: Properties: CodeUri: ./src/ Handler: app.handler - Runtime: nodejs20.x + Runtime: nodejs22.x Timeout: 30 MemorySize: 128 Role: !GetAtt TranscriptionFunctionRole.Arn From e810484409d36d3544c06c8dae6a326a012685f5 Mon Sep 17 00:00:00 2001 From: Achintya Veer Singh Date: Mon, 24 Mar 2025 14:46:38 +0530 Subject: [PATCH 09/11] Renamed folder --- .../README.md | 0 .../example-pattern.json | 0 .../src/app.mjs | 0 .../template.yaml | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename {apigw-lambda-transcribe-sam-js => lambda-transcribe-sam-js}/README.md (100%) rename {apigw-lambda-transcribe-sam-js => lambda-transcribe-sam-js}/example-pattern.json (100%) rename {apigw-lambda-transcribe-sam-js => lambda-transcribe-sam-js}/src/app.mjs (100%) rename {apigw-lambda-transcribe-sam-js => lambda-transcribe-sam-js}/template.yaml (100%) diff --git a/apigw-lambda-transcribe-sam-js/README.md b/lambda-transcribe-sam-js/README.md similarity index 100% rename from apigw-lambda-transcribe-sam-js/README.md rename to lambda-transcribe-sam-js/README.md diff --git a/apigw-lambda-transcribe-sam-js/example-pattern.json b/lambda-transcribe-sam-js/example-pattern.json similarity index 100% rename from apigw-lambda-transcribe-sam-js/example-pattern.json rename to lambda-transcribe-sam-js/example-pattern.json diff --git a/apigw-lambda-transcribe-sam-js/src/app.mjs b/lambda-transcribe-sam-js/src/app.mjs similarity index 100% rename from apigw-lambda-transcribe-sam-js/src/app.mjs rename to lambda-transcribe-sam-js/src/app.mjs diff --git a/apigw-lambda-transcribe-sam-js/template.yaml b/lambda-transcribe-sam-js/template.yaml similarity index 100% rename from apigw-lambda-transcribe-sam-js/template.yaml rename to lambda-transcribe-sam-js/template.yaml From 5c471018bed90233886df5e832a98e05f0c45706 Mon Sep 17 00:00:00 2001 From: ellisms <114107920+ellisms@users.noreply.github.com> Date: Mon, 24 Mar 2025 08:24:16 -0400 Subject: [PATCH 10/11] publishing file --- .../lambda-transcribe-sam-js.json | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 lambda-transcribe-sam-js/lambda-transcribe-sam-js.json diff --git a/lambda-transcribe-sam-js/lambda-transcribe-sam-js.json b/lambda-transcribe-sam-js/lambda-transcribe-sam-js.json new file mode 100644 index 000000000..b2a5ee636 --- /dev/null +++ b/lambda-transcribe-sam-js/lambda-transcribe-sam-js.json @@ -0,0 +1,101 @@ +{ + "title": "Amazon S3 to AWS Lambda to Amazon Transcribe using AWS SAM", + "description": "This pattern creates a serverless pipeline that automatically invokes an Amazon Transcribe job when audio files are uploaded to an S3 bucket.", + "language": "Node.js", + "level": "200", + "framework": "SAM", + "introBox": { + "headline": "How it works", + "text": [ + "When audio files are uploaded to the S3 bucket, an AWS Lambda function starts a transcription job using Amazon Transcribe. The Lambda function extracts information about the uploaded audio file and sends it to the Amazon Transcribe service, which processes the audio and generates a text transcription that is saved back to the specified S3 bucket." + ] + }, + "gitHub": { + "template": { + "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/lambda-transcribe-sam-js", + "templateURL": "serverless-patterns/lambda-transcribe-sam-js", + "projectFolder": "lambda-transcribe-sam-js", + "templateFile": "template.yaml" + } + }, + "resources": { + "bullets": [ + { + "text": "Amazon S3", + "link": "https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html" + }, + { + "text": "AWS Lambda", + "link": "https://docs.aws.amazon.com/lambda/latest/dg/welcome.html" + }, + { + "text": "Amazon Transcribe", + "link": "https://docs.aws.amazon.com/transcribe/latest/dg/what-is.html" + } + ] + }, + "deploy": { + "text": [ + "sam build", + "sam deploy --guided" + ] + }, + "testing": { + "text": [ + "See the GitHub repo for detailed testing instructions." + ] + }, + "cleanup": { + "text": [ + "sam delete" + ] + }, + "authors": [ + { + "name": "Achintya Veer Singh", + "image": "https://avatars.githubusercontent.com/u/55053737?v=4", + "bio": "Solutions Architect @ AWS", + "linkedin": "www.linkedin.com/in/achintya-veer-singh-493403193", + "twitter": "achintya_veer" + } + ], + "patternArch": { + "icon1": { + "x": 10, + "y": 50, + "service": "s3", + "label": "Amazon S3" + }, + "icon2": { + "x": 40, + "y": 50, + "service": "lambda", + "label": "AWS Lambda" + }, + "icon3": { + "x": 65, + "y": 50, + "service": "transcribe", + "label": "Amazon Transcribe" + }, + "icon4": { + "x": 90, + "y": 50, + "service": "s3", + "label": "Amazon S3" + }, + "line1": { + "from": "icon1", + "to": "icon2", + "label": "Object Created" + }, + "line2": { + "from": "icon2", + "to": "icon3" + }, + "line3": { + "from": "icon3", + "to": "icon4" + } + } +} From 6b70fa9e2771a8096a6ff256b326d856d665ef1f Mon Sep 17 00:00:00 2001 From: ellisms <114107920+ellisms@users.noreply.github.com> Date: Mon, 24 Mar 2025 08:25:02 -0400 Subject: [PATCH 11/11] tagging --- lambda-transcribe-sam-js/template.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lambda-transcribe-sam-js/template.yaml b/lambda-transcribe-sam-js/template.yaml index d57e60117..b0434d619 100644 --- a/lambda-transcribe-sam-js/template.yaml +++ b/lambda-transcribe-sam-js/template.yaml @@ -1,6 +1,6 @@ AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 -Description: S3 to Lambda to Transcription Job +Description: S3 to Lambda to Transcription Job (uksb-1tthgi812) (tag:lambda-transcribe-sam-js) Resources: AudioBucket: