package com.amazonaws.kvsmlinference; import com.amazonaws.SdkClientException; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.regions.Regions; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3ClientBuilder; import com.amazonaws.services.s3.model.CannedAccessControlList; import com.amazonaws.services.s3.model.GetObjectRequest; import com.amazonaws.services.s3.model.ObjectMetadata; import com.amazonaws.services.s3.model.PutObjectRequest; import com.amazonaws.services.s3.model.PutObjectResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.sound.sampled.AudioFileFormat; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.UnsupportedAudioFileException; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; /** * Utility class to download/upload audio files from/to S3 * *

Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.

* * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so. *

* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ public final class AudioUtils { private static final Logger logger = LoggerFactory.getLogger(AudioUtils.class); /** * Fetches the audio file from S3 and saves it locally * @param region * @param bucketName * @param objectKey * @param audioFilePath * @param awsCredentials * @throws SdkClientException */ public static void fetchAudio(Regions region, String bucketName, String objectKey, String audioFilePath, AWSCredentialsProvider awsCredentials) { AmazonS3 s3Client = AmazonS3ClientBuilder.standard() .withRegion(region) .withCredentials(awsCredentials) .build(); // save the object locally logger.info(String.format("Fetching %s/%s to %s", bucketName, objectKey, audioFilePath)); File localFile = new File(audioFilePath); GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, objectKey); ObjectMetadata metaData = s3Client.getObject(getObjectRequest, localFile); logger.info(String.format("fetchAudio: getObject completed successfully %d byte(s) %s", metaData.getContentLength(), metaData.getETag())); } /** * Converts the given raw audio data into a wav file. Returns the wav file back. */ private static File convertToWav(String audioFilePath) throws IOException, UnsupportedAudioFileException { File outputFile = new File(audioFilePath.replace(".raw", ".wav")); AudioInputStream source = new AudioInputStream(Files.newInputStream(Paths.get(audioFilePath)), new AudioFormat(8000, 16, 1, true, false), -1); // 8KHz, 16 bit, 1 channel, signed, little-endian AudioSystem.write(source, AudioFileFormat.Type.WAVE, outputFile); return outputFile; } /** * Saves the raw audio file as an S3 object * * @param region * @param bucketName * @param keyPrefix * @param audioFilePath * @param awsCredentials */ public static String uploadRawAudio(Regions region, String bucketName, String keyPrefix, String audioFilePath, String contactId, boolean publicReadAcl, AWSCredentialsProvider awsCredentials) { File wavFile = null; try { AmazonS3 s3Client = AmazonS3ClientBuilder .standard() .withRegion(region) .withCredentials(awsCredentials) .build(); wavFile = convertToWav(audioFilePath); // upload the raw audio file to the designated S3 location String objectKey = keyPrefix + wavFile.getName(); logger.info(String.format("Uploading Audio: to %s/%s from %s", bucketName, objectKey, wavFile)); PutObjectRequest request = new PutObjectRequest(bucketName, objectKey, wavFile); ObjectMetadata metadata = new ObjectMetadata(); metadata.setContentType("audio/wav"); metadata.addUserMetadata("contact-id", contactId); request.setMetadata(metadata); if (publicReadAcl) { request.setCannedAcl(CannedAccessControlList.PublicRead); } PutObjectResult s3result = s3Client.putObject(request); logger.info("putObject completed successfully " + s3result.getETag()); if (wavFile != null) { wavFile.delete(); } return String.format("s3://%s/%s", bucketName, objectKey); } catch (SdkClientException e) { logger.error("Audio upload to S3 failed: ", e); return ""; } catch (UnsupportedAudioFileException|IOException e) { logger.error("Failed to convert to wav: ", e); return ""; } } }