The Amazon SDK for JavaScript V3 API
Reference Guide
Prepare the browser script
This topic is part of a tutorial about building an app that transcribes and displays voice messages for authenticated users. To start at the beginning of the tutorial, see Build a transcription app with authenticated users.
There are three files, index.html
,
recorder.js
, and helper.js
, which you are
required to bundle into a single main.js
using Webpack. This topic
describes in detail only the functions in index.js
that use the
SDK for JavaScript, which is available here on GitHub
Note
First, define the parameters. COGNITO_ID
is the
endpoint for the Amazon Cognito User Pool you created in the Create the Amazon resources topic of this tutorial.
It is formattedcognito-idp.
.
The user pool id is AWS_REGION
.amazonaws.com/USER_POOL_ID
ID_TOKEN
in the Amazon credentials token,
which is stripped from the app URL by the getToken
function in the 'helper.js' file. This
token is passed to the loginData
variable, which provides the Amazon Transcribe and Amazon S3 client objects with logins. Replace "REGION"
with the Amazon Region, and "BUCKET"
with the Replace "IDENTITY_POOL_ID"
with the IdentityPoolId
from the Sample page of the
Amazon Cognito identity pool you created for this example. This is also passed to each client
object.
// Import the required AWS SDK clients and commands for Node.js import "./helper.js"; import "./recorder.js"; import { CognitoIdentityClient } from "@aws-sdk/client-cognito-identity"; import { fromCognitoIdentityPool } from "@aws-sdk/credential-provider-cognito-identity"; import { CognitoIdentityProviderClient, GetUserCommand, } from "@aws-sdk/client-cognito-identity-provider"; import { S3RequestPresigner } from "@aws-sdk/s3-request-presigner"; import { createRequest } from "@aws-sdk/util-create-request"; import { formatUrl } from "@aws-sdk/util-format-url"; import { TranscribeClient, StartTranscriptionJobCommand, } from "@aws-sdk/client-transcribe"; import { S3Client, PutObjectCommand, GetObjectCommand, ListObjectsCommand, DeleteObjectCommand, } from "@aws-sdk/client-s3"; import fetch from "node-fetch"; // Set the parameters. // 'COGINTO_ID' has the format 'cognito-idp.eu-west-1.amazonaws.com/COGNITO_ID'. let COGNITO_ID = "COGNITO_ID"; // Get the Amazon Cognito ID token for the user. 'getToken()' is in 'helper.js'. let idToken = getToken(); let loginData = { [COGNITO_ID]: idToken, }; const params = { Bucket: "BUCKET", // The Amazon Simple Storage Solution (S3) bucket to store the transcriptions. Region: "REGION", // The AWS Region identityPoolID: "IDENTITY_POOL_ID", // Amazon Cognito Identity Pool ID. }; // Create an Amazon Transcribe service client object. const client = new TranscribeClient({ region: params.Region, credentials: fromCognitoIdentityPool({ client: new CognitoIdentityClient({ region: params.Region }), identityPoolId: params.identityPoolID, logins: loginData, }), }); // Create an Amazon S3 client object. const s3Client = new S3Client({ region: params.Region, credentials: fromCognitoIdentityPool({ client: new CognitoIdentityClient({ region: params.Region }), identityPoolId: params.identityPoolID, logins: loginData, }), });
When the HTML page loads, the updateUserInterface
creates a folder with
the user's name in the Amazon S3 bucket if its the first time they've signed in to the app.
If not, it updates the user interface with any transcripts from the user's previous
sessions.
window.onload = async () => { // Set the parameters. const userParams = { // Get the access token. 'GetAccessToken()' is in 'helper.js'. AccessToken: getAccessToken(), }; // Create a CognitoIdentityProviderClient client object. const client = new CognitoIdentityProviderClient({ region: params.Region }); try { const data = await client.send(new GetUserCommand(userParams)); const username = data.Username; // Export username for use in 'recorder.js'. exports.username = username; try { // If this is user's first sign-in, create a folder with user's name in Amazon S3 bucket. // Otherwise, no effect. const Key = `${username}/`; try { const data = await s3Client.send( new PutObjectCommand({ Key: Key, Bucket: params.Bucket }) ); console.log("Folder created for user ", data.Username); } catch (err) { console.log("Error", err); } try { // Get a list of the objects in the Amazon S3 bucket. const data = await s3Client.send( new ListObjectsCommand({ Bucket: params.Bucket, Prefix: username }) ); // Create a variable for the list of objects in the Amazon S3 bucket. const output = data.Contents; // Loop through the objects, populating a row on the user interface for each object. for (var i = 0; i < output.length; i++) { var obj = output[i]; const objectParams = { Bucket: params.Bucket, Key: obj.Key, }; // Get the name of the object from the Amazon S3 bucket. const data = await s3Client.send(new GetObjectCommand(objectParams)); // Extract the body contents, a readable stream, from the returned data. const result = data.Body; // Create a variable for the string version of the readable stream. let stringResult = ""; // Use 'yieldUnit8Chunks' to convert the readable streams into JSON. for await (let chunk of yieldUint8Chunks(result)) { stringResult += String.fromCharCode.apply(null, chunk); } // The setTimeout function waits while readable stream is converted into JSON. setTimeout(function () { // Parse JSON into human readable transcript, which will be displayed on user interface (UI). const outputJSON = JSON.parse(stringResult).results.transcripts[0].transcript; // Create name for transcript, which will be displayed. const outputJSONTime = JSON.parse(stringResult) .jobName.split("/")[0] .replace("-job", ""); i++; // // Display the details for the transcription on the UI. // 'displayTranscriptionDetails()' is in 'helper.js'. displayTranscriptionDetails( i, outputJSONTime, objectParams.Key, outputJSON ); }, 1000); } } catch (err) { console.log("Error", err); } } catch (err) { console.log("Error creating presigned URL", err); } } catch (err) { console.log("Error", err); } }; // Convert readable streams. async function* yieldUint8Chunks(data) { const reader = data.getReader(); try { while (true) { const { done, value } = await reader.read(); if (done) return; yield value; } } finally { reader.releaseLock(); } }
When the user records a voice message for transcriptions, the upload
uploads the recordings to the Amazon S3 bucket. This function is called from the
recorder.js
file.
// Upload recordings to Amazon S3 bucket window.upload = async function (blob, userName) { // Set the parameters for the recording recording. const Key = `${userName}/test-object-${Math.ceil(Math.random() * 10 ** 10)}`; let signedUrl; // Create a presigned URL to upload the transcription to the Amazon S3 bucket when it is ready. try { // Create an Amazon S3RequestPresigner object. const signer = new S3RequestPresigner({ ...s3Client.config }); // Create the request. const request = await createRequest( s3Client, new PutObjectCommand({ Key, Bucket: params.Bucket }) ); // Define the duration until expiration of the presigned URL. const expiration = new Date(Date.now() + 60 * 60 * 1000); // Create and format the presigned URL. signedUrl = formatUrl(await signer.presign(request, expiration)); console.log(`\nPutting "${Key}"`); } catch (err) { console.log("Error creating presigned URL", err); } try { // Upload the object to the Amazon S3 bucket using a presigned URL. response = await fetch(signedUrl, { method: "PUT", headers: { "content-type": "application/octet-stream", }, body: blob, }); // Create the transcription job name. In this case, it's the current date and time. const today = new Date(); const date = today.getFullYear() + "-" + (today.getMonth() + 1) + "-" + today.getDate(); const time = today.getHours() + "-" + today.getMinutes() + "-" + today.getSeconds(); const jobName = date + "-time-" + time; // Call the "createTranscriptionJob()" function. createTranscriptionJob( "s3://" + params.Bucket + "/" + Key, jobName, params.Bucket, Key ); } catch (err) { console.log("Error uploading object", err); } }; // Create the AWS Transcribe transcription job. const createTranscriptionJob = async (recording, jobName, bucket, key) => { // Set the parameters for transcriptions job const params = { TranscriptionJobName: jobName + "-job", LanguageCode: "en-US", // For example, 'en-US', OutputBucketName: bucket, OutputKey: key, Media: { MediaFileUri: recording, // For example, "https://transcribe-demo.s3-REGION.amazonaws.com/hello_world.wav" }, }; try { // Start the transcription job. const data = await client.send(new StartTranscriptionJobCommand(params)); console.log("Success - transcription submitted", data); } catch (err) { console.log("Error", err); } };
deleteTranscription
deletes a transcription from the user interface, and
deleteRow
deletes an existing transcription from the Amazon S3 bucket. Both
are triggered by the Delete button on the user interface.
// Delete a transcription from the Amazon S3 bucket. window.deleteJSON = async (jsonFileName) => { try { await s3Client.send( new DeleteObjectCommand({ Bucket: params.Bucket, Key: jsonFileName, }) ); console.log("Success - JSON deleted"); } catch (err) { console.log("Error", err); } }; // Delete a row from the user interface. window.deleteRow = function (rowid) { const row = document.getElementById(rowid); row.parentNode.removeChild(row); };
Finally, run the following at the command prompt to bundle the JavaScript for this
example in a file named main.js
:
webpack index.js --mode development --target web --devtool false -o main.js
Note
For information about installing webpack, see Bundling applications with webpack.