├── img ├── flow.png ├── flow0.png ├── flow1.png ├── flow2.png ├── flow3.png ├── flow4.png ├── button-next.png ├── button-previous.png ├── button-get-started.png └── button-launch-stack.png ├── guide ├── phase0 │ ├── my-car.mp3 │ ├── mi-coche.mp3 │ ├── babel-fish.css │ ├── README.md │ ├── babel-fish.html │ └── babel-fish.js ├── phase3 │ ├── polly_solution.zip │ └── README.md ├── phase2 │ ├── translate_solution.zip │ └── README.md ├── phase1 │ ├── transcribe_solution.zip │ └── README.md └── cleaning │ └── README.md ├── README.md └── acknowledgements.md /img/flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maciejchmielarz/babel-fish/HEAD/img/flow.png -------------------------------------------------------------------------------- /img/flow0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maciejchmielarz/babel-fish/HEAD/img/flow0.png -------------------------------------------------------------------------------- /img/flow1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maciejchmielarz/babel-fish/HEAD/img/flow1.png -------------------------------------------------------------------------------- /img/flow2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maciejchmielarz/babel-fish/HEAD/img/flow2.png -------------------------------------------------------------------------------- /img/flow3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maciejchmielarz/babel-fish/HEAD/img/flow3.png -------------------------------------------------------------------------------- /img/flow4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maciejchmielarz/babel-fish/HEAD/img/flow4.png -------------------------------------------------------------------------------- /img/button-next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maciejchmielarz/babel-fish/HEAD/img/button-next.png -------------------------------------------------------------------------------- /guide/phase0/my-car.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maciejchmielarz/babel-fish/HEAD/guide/phase0/my-car.mp3 -------------------------------------------------------------------------------- /img/button-previous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maciejchmielarz/babel-fish/HEAD/img/button-previous.png -------------------------------------------------------------------------------- /guide/phase0/mi-coche.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maciejchmielarz/babel-fish/HEAD/guide/phase0/mi-coche.mp3 -------------------------------------------------------------------------------- /img/button-get-started.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maciejchmielarz/babel-fish/HEAD/img/button-get-started.png -------------------------------------------------------------------------------- /img/button-launch-stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maciejchmielarz/babel-fish/HEAD/img/button-launch-stack.png -------------------------------------------------------------------------------- /guide/phase3/polly_solution.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maciejchmielarz/babel-fish/HEAD/guide/phase3/polly_solution.zip -------------------------------------------------------------------------------- /guide/phase2/translate_solution.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maciejchmielarz/babel-fish/HEAD/guide/phase2/translate_solution.zip -------------------------------------------------------------------------------- /guide/phase1/transcribe_solution.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maciejchmielarz/babel-fish/HEAD/guide/phase1/transcribe_solution.zip -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Build a Babel Fish with Machine Learning Language Services 2 | 3 | This repository contains necessary resources for AWS workshop. In this readme you will find detailed instructions for each phase of the workshop. 4 | 5 | 6 | 7 | The process of building your own Babel Fish will be split into four phases. In each phase you will add a new functionality to your solution by using one of the AI services from AWS portfolio. 8 | 9 | 10 | -------------------------------------------------------------------------------- /guide/phase0/babel-fish.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Allerta Stencil', sans-serif; 3 | } 4 | 5 | h1.title { 6 | text-align: left; 7 | padding-left: 0.2em; 8 | } 9 | 10 | div.app { 11 | display: inline-block; 12 | } 13 | 14 | ul.app { 15 | list-style: none; 16 | padding: 0; 17 | } 18 | 19 | li.app { 20 | border: 1px dashed grey; 21 | padding: 0.5em; 22 | margin: 0.5em; 23 | } 24 | 25 | ul.audio-input { 26 | list-style: none; 27 | padding: 0; 28 | overflow: hidden; 29 | } 30 | 31 | ul.audio-input li { 32 | float: left; 33 | } 34 | 35 | li.audio-input { 36 | border: 1px dotted grey; 37 | padding: 1em; 38 | margin: 0.5em; 39 | } 40 | 41 | span#processing { 42 | color: red; 43 | display: none; 44 | } 45 | -------------------------------------------------------------------------------- /guide/cleaning/README.md: -------------------------------------------------------------------------------- 1 | # Build a Babel Fish with Machine Learning Language Services 2 | 3 | This repository contains necessary resources for AWS re:Invent 2018 workshop AIM313. In this readme you will find detailed instructions how to cleanup your environment. 4 | 5 | 6 | 7 | ## Cleaning 8 | 9 | When the workshop is finished you may consider taking following housekeeping steps at your AWS account. 10 | 11 | The S3 bucket was created as public and is accessible to anyone on the Internet. You may want to change this setting and restrict access (in current setup the app will stop working though). 12 | 13 | It's also very easy to remove all AWS resources created for this workshop. Firstly, you need to use S3 service in the AWS Console to empty your S3 bucket. Secondly, you need to use CloudFormation service in AWS Console to delete created resources. To do this select checkbox next to created `babel-fish-app` stack and choose `Delete Stack` option in `Actions` menu. 14 | 15 | 16 | -------------------------------------------------------------------------------- /acknowledgements.md: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | 3 | ## JavaScript Polling 4 | 5 | Project URL: https://davidwalsh.name/javascript-polling 6 | 7 | Project License: 8 | 9 | > Copyright 2015 David Walsh 10 | > 11 | > 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, subject to the following conditions: 12 | > 13 | > The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 14 | > 15 | > 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. 16 | 17 | ## Recorder.js 18 | 19 | Project URL: https://github.com/mattdiamond/Recorderjs 20 | 21 | Project License: 22 | 23 | > Copyright © 2013 Matt Diamond 24 | > 25 | > 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, subject to the following conditions: 26 | > 27 | > The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 28 | > 29 | > 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. 30 | -------------------------------------------------------------------------------- /guide/phase3/README.md: -------------------------------------------------------------------------------- 1 | # Build a Babel Fish with Machine Learning Language Services 2 | 3 | This repository contains necessary resources for AWS workshop. In this readme you will find detailed instructions for `Phase 3`. 4 | 5 | 6 | 7 | ## Phase 3: Convert text to audio 8 | 9 | Use Lambda service in the AWS Console to open `PollyLambda` function. In the `Add triggers` section on the left configure trigger for this function: 10 | 11 | 1. Choose S3 as the trigger and go to the `Configure triggers` section. 12 | 1. Pick correct S3 bucket name. 13 | 1. Pick `PUT` as event type. 14 | 1. Put `.txt` as suffix. 15 | 1. Click `Add` at the bottom of the page to add trigger. 16 | 1. Click `Save` at the top of the page to confirm changes to the function. 17 | 18 | Implement the function to use translation result and synthesize it with Amazon Polly. 19 | 20 | > Hint: Your function should put synthesis result to an `.mp3` file in project's S3 bucket in `output` folder and use the same file naming convention as Babel Fish JavaScript component. 21 | 22 | > Hint: You may want to look up [Amazon Polly Boto 3 Docs](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/polly.html) or inspire yourself with [Amazon Polly Synthesize Speech Example](https://docs.aws.amazon.com/polly/latest/dg/SynthesizeSpeechSamplePython.html). 23 | 24 | > Hint: Getting behind? No worries, we've got you covered! When the time is up speakers will provide the password to the `solution.zip` file with a ready solution and will show how to apply it to unblock next steps. 25 | 26 | ## Testing 27 | 28 | That's it! :) It's time to let your Babel Fish out :) To test the full solution, open your Babel Fish web app, record yourself or upload an audio file (you can use example files from the setup phase), verify in the S3 bucket if an `mp3` file with synthesized speech is created and listen to the spoken output played automatically by the app. 29 | 30 | > Hint: If it didn't work you may start troubleshooting by: 31 | > 1. checking if translation result `txt` file is non-empty and contains text that makes sense, 32 | > 1. checking Lambda function logs in CloudWatch for errors (to do that navigate to `Monitoring` tab in the AWS Console, see relevant documentation [here](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-functions-logs.html)). 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /guide/phase2/README.md: -------------------------------------------------------------------------------- 1 | # Build a Babel Fish with Machine Learning Language Services 2 | 3 | This repository contains necessary resources for AWS workshop. In this readme you will find detailed instructions for `Phase 2`. 4 | 5 | 6 | 7 | ## Phase 2: Translate text 8 | 9 | Use Lambda service in the AWS Console to open `TranslateLambda` function. In the `Add triggers` section on the left configure trigger for this function: 10 | 11 | 1. Choose S3 as the trigger and go to the `Configure triggers` section. 12 | 1. Pick correct S3 bucket name. 13 | 1. Pick `PUT` as event type. 14 | 1. Put `.json` as suffix. 15 | 1. Click `Add` at the bottom of the page to add trigger. 16 | 1. Click `Save` at the top of the page to confirm changes to the function. 17 | 18 | Implement the function to use transcription result and translate it with Amazon Translate. 19 | 20 | > Hint: Your function should put translation result to a `.txt` file in project's S3 bucket and use the same file naming convention as Babel Fish JavaScript component. 21 | 22 | > Hint: You may want to look up [Amazon Translate Boto 3 Docs](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/translate.html) or inspire yourself with [Amazon Translate Getting Started](https://docs.aws.amazon.com/translate/latest/dg/examples-python.html). 23 | 24 | > Hint: Getting behind? No worries, we've got you covered! When the time is up speakers will provide the password to the `solution.zip` file with a ready solution and will show how to apply it to unblock next steps. 25 | 26 | ## Testing 27 | 28 | To test this part of implementation, open your Babel Fish web app, record yourself or upload an audio file (you can use example files from the setup phase) and verify in the S3 bucket if a `txt` file with translation result is created. 29 | 30 | > Hint: If it didn't work you may start troubleshooting by: 31 | > 1. checking if transcription result in `json` file contains `transcript` that is non-empty and makes sense, 32 | > 1. checking Lambda function logs in CloudWatch for errors (to do that navigate to `Monitoring` tab in the AWS Console, see relevant documentation [here](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-functions-logs.html)). 33 | 34 | **Once you're finished with this phase please wait for speakers to present the next one before moving forward.** 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /guide/phase1/README.md: -------------------------------------------------------------------------------- 1 | # Build a Babel Fish with Machine Learning Language Services 2 | 3 | This repository contains necessary resources for AWS workshop. In this readme you will find detailed instructions for `Phase 1`. 4 | 5 | 6 | 7 | ## Phase 1: Convert audio to text 8 | 9 | Use Lambda service in the AWS Console to open `TranscribeLambda` function. In the `Add triggers` section on the left configure trigger for this function: 10 | 11 | 1. Choose S3 as the trigger and go to the `Configure triggers` section. 12 | 1. Pick correct S3 bucket name. 13 | 1. Pick `PUT` as event type. 14 | 1. Put `input/` as prefix. 15 | 1. Put `.mp3` as suffix. 16 | 1. Click `Add` at the bottom of the page to add trigger. 17 | 1. Click `Save` at the top of the page to confirm changes to the function. 18 | 1. Add a second trigger. Exactly the same as the previous one, but this time, the suffix should be `.wav`. 19 | 20 | Implement the function to use audio file link and transcribe it with Amazon Transcribe. 21 | 22 | > Hint: JavaScript app uses a following format to name the files: `xx-XX_yy-YY_guid.ext`, where `xx-XX` is the input language (locale), `yy-YY` is the output language (locale), `guid` is a unique identifier and `ext` is the uploaded audio file extension or `wav` for recordings. 23 | 24 | > Hint: Your function should request Amazon Transcribe to put results in project's S3 bucket and use the same file naming convention as Babel Fish JavaScript component. 25 | 26 | > Hint: You may want to look up [Amazon Transcribe Boto 3 Docs](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/transcribe.html) or inspire yourself with [Amazon Transcribe Getting Started](https://docs.aws.amazon.com/transcribe/latest/dg/getting-started-python.html). 27 | 28 | > Hint: Getting behind? No worries, we've got you covered! When the time is up speakers will provide the password to the `solution.zip` file with a ready solution and will show how to apply it to unblock next steps. 29 | 30 | ## Testing 31 | 32 | To test this part of implementation, open your Babel Fish web app, record yourself or upload an audio file (you can use example files from the setup phase) and verify in the S3 bucket if a `json` file with transcription result is created. 33 | 34 | > Hint: If it didn't work you may start troubleshooting by: 35 | > 1. checking Transcribe jobs in the AWS Console for any `IN PROGRESS` or `FAILED` items, 36 | > 1. checking Lambda function logs in CloudWatch for errors (navigate to `Monitoring` tab in the AWS Console, see relevant documentation [here](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-functions-logs.html)). 37 | 38 | **Once you're finished with this phase please wait for speakers to present the next one before moving forward.** 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /guide/phase0/README.md: -------------------------------------------------------------------------------- 1 | # Build a Babel Fish with Machine Learning Language Services 2 | 3 | This repository contains necessary resources for AWS workshop. In this readme you will find detailed instructions for `Phase 0`. 4 | 5 | 6 | 7 | ## Phase 0: Environment setup 8 | 9 | 1. Sign into the AWS Console and choose `eu-west-1` (Ireland) region. Open the link below in a new tab to launch CloudFormation stack in your AWS account. It will configure your environment with resources necessary to run this workshop. 10 | 11 | 12 | 13 | 2. Move through the wizard (`Next`, `Next`, `Next`), on `Review` page acknowledge that CloudFormation might create IAM resources and click `Create`. Wait a few moments until status changes from `CREATE_IN_PROGRESS` to `CREATE_COMPLETE`. 14 | 15 | 3. On `Stacks` page click stack name to view `Stack Detail` page and expand `Outputs` section. In `Key` column find the following items and copy their `Value` values for later use: 16 | 17 | * `IdentityPoolId` - Amazon Cognito Identity Pool ID. 18 | * `S3BucketName` - S3 bucket for Babel Fish app data. 19 | * `BabelFishAppLink` - Link to your Babel Fish app. 20 | 21 | 4. Download zip file with the content of this repo using this [link](https://github.com/maciejchmielarz/babel-fish/archive/master.zip), extract it and find Babel Fish app files listed under `guide/phase0`: 22 | 23 | * `babel-fish.css` 24 | * `babel-fish.html` 25 | * `babel-fish.js` 26 | 27 | 5. Update your local JavaScript app `babel-fish.js` and replace placeholders with correct configuration data: 28 | 29 | 1. Provide your S3 bucket name in line 3. 30 | 1. Provide your Identity Pool ID in line 4. 31 | 32 | 7. Upload Babel Fish app files (`babel-fish.css`, `babel-fish.html` and `babel-fish.js`) to the S3 bucket which was created in the previous steps. 33 | 34 | During this workshop you will be implementing app logic in Lambda functions created by CloudFormation. Please note that those functions use `Python 3.6` by default and while it's absolutely not a problem to use other programming languages to develop this solution, only `Python` is actively supported during this workshop. 35 | 36 | ## Testing 37 | 38 | To test this part of implementation, open the `BabelFishAppLink` that you copied in step 3, record yourself or upload an audio file (you can use example files from this directory: `my-car.mp3` or `mi-coche.mp3`) and verify in the S3 bucket if an audio file is put into `input` folder. At this point your app will show `Processing...` and will eventually timeout because all the backend parts are not implemented... yet :) 39 | 40 | > Hint: If it didn't work you may start troubleshooting by checking browser's JavaScript console for app errors (see relevant documentation for [Firefox](https://developer.mozilla.org/en-US/docs/Tools/Browser_Console) and [Chrome](https://developers.google.com/web/tools/chrome-devtools/console/)). 41 | 42 | **Once you're finished with this phase please wait for speakers to present the next one before moving forward.** 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /guide/phase0/babel-fish.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 |

Babel Fish App

11 | 93 |
94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /guide/phase0/babel-fish.js: -------------------------------------------------------------------------------- 1 | // AWS configuration 2 | var awsRegion = 'eu-west-1'; 3 | var bucketName = '!!!!! REPLACE !!!!!'; 4 | var IdentityPoolId = '!!!!! REPLACE !!!!!'; 5 | 6 | AWS.config.update({ 7 | region: awsRegion, 8 | credentials: new AWS.CognitoIdentityCredentials({ 9 | IdentityPoolId: IdentityPoolId 10 | }) 11 | }); 12 | 13 | // S3 object for storing input and output audio 14 | var s3 = new AWS.S3({ 15 | apiVersion: '2006-03-01', 16 | params: {Bucket: bucketName}, 17 | region: 'eu-west-1' 18 | }); 19 | 20 | // Define variables for audio recorder 21 | var recorder; 22 | var recorderInput; 23 | var getUserMediaStream; 24 | var AudioContext = window.AudioContext || window.webkitAudioContext; 25 | var audioContext; 26 | 27 | // Get buttons from DOM 28 | var recordStartButton = document.getElementById('record-start'); 29 | var recordStopButton = document.getElementById('record-stop'); 30 | var audioUploadButton = document.getElementById('audio-upload'); 31 | 32 | // Add click event callbacks to buttons 33 | recordStartButton.addEventListener('click', startRecording); 34 | recordStopButton.addEventListener('click', stopRecording); 35 | audioUploadButton.addEventListener('click', uploadAudioFile); 36 | 37 | // Generate unique identifiers 38 | function guid() { 39 | function s4() { 40 | return Math.floor((1 + Math.random()) * 0x10000) 41 | .toString(16) 42 | .substring(1); 43 | } 44 | return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4(); 45 | } 46 | 47 | // Check if URL returns HTTP 200 OK 48 | function urlExists(url) { 49 | var http = new XMLHttpRequest(); 50 | http.open('HEAD', url, false); 51 | http.send(); 52 | return http.status==200; 53 | } 54 | 55 | // Polling for result 56 | function poll(fn, timeout, interval) { 57 | var endTime = Number(new Date()) + (timeout || 2000); 58 | interval = interval || 100; 59 | 60 | var checkCondition = function(resolve, reject) { 61 | // If the condition is met, we're done! 62 | var result = fn(); 63 | if(result) { 64 | resolve(result); 65 | } 66 | // If the condition isn't met but the timeout hasn't elapsed, go again 67 | else if (Number(new Date()) < endTime) { 68 | setTimeout(checkCondition, interval, resolve, reject); 69 | } 70 | // Didn't match and too much time, reject! 71 | else { 72 | reject(new Error('timed out for ' + fn + ': ' + arguments)); 73 | } 74 | }; 75 | 76 | return new Promise(checkCondition); 77 | } 78 | 79 | // Adjust buttons and message for processing 80 | function processingView() { 81 | // Show processing message 82 | document.getElementById('processing').style.display = 'inline'; 83 | // Disable all buttons 84 | recordStartButton.disabled = true; 85 | recordStopButton.disabled = true; 86 | audioUploadButton.disabled = true; 87 | } 88 | 89 | // Adjust buttons and message for recording 90 | function recordingView() { 91 | // Hide processing message 92 | document.getElementById('processing').style.display = 'none'; 93 | // Disable all buttons 94 | recordStartButton.disabled = true; 95 | recordStopButton.disabled = false; 96 | audioUploadButton.disabled = true; 97 | } 98 | 99 | // Reset buttons and hide messages 100 | function resetView() { 101 | // Hide processing message 102 | document.getElementById('processing').style.display = 'none'; 103 | // Disable all buttons 104 | recordStartButton.disabled = false; 105 | recordStopButton.disabled = true; 106 | audioUploadButton.disabled = false; 107 | } 108 | 109 | // Generate request ID 110 | function generateRequestId() { 111 | // Get data from website 112 | var inputLang = document.getElementById('input-lang').value; 113 | var outputLang = document.getElementById('output-lang').value; 114 | // Generate request id in following format: xx-yy-guid 115 | // xx - input language, yy - output language, guid - unique identifier 116 | return requestId = inputLang + '_' + outputLang + '_' + guid(); 117 | } 118 | 119 | // Record audio with device microphone 120 | function startRecording() { 121 | // Adjust buttons and message for recording 122 | recordingView(); 123 | 124 | // Create AudioContext only after a user gesture https://goo.gl/7K7WLu 125 | audioContext = new AudioContext; 126 | 127 | // Define constraints object for MediaStream 128 | var constraints = { audio: true, video: false } 129 | 130 | // Access MediaDevices to get audio stream 131 | navigator.mediaDevices.getUserMedia(constraints).then(function(stream) { 132 | getUserMediaStream = stream; 133 | recorderInput = audioContext.createMediaStreamSource(stream); 134 | // Create Recorder.js object and start recording 135 | recorder = new Recorder(recorderInput, { numChannels: 1 }) 136 | recorder.record() 137 | }).catch(function(err) { 138 | // Reset buttons and message in case of failure 139 | resetView(); 140 | // Inform user that recording failed (most likely was blocked by browser due 141 | // to insecure origin) 142 | alert("Recording failed, try using Firefox or local copy of the app from your machine."); 143 | }); 144 | } 145 | 146 | function stopRecording() { 147 | // Reset buttons and message 148 | resetView(); 149 | 150 | // Stop recording with Recorder.js object 151 | recorder.stop(); 152 | 153 | // Stop microphone and get recorded audio 154 | getUserMediaStream.getAudioTracks()[0].stop(); 155 | 156 | // Pass blob with audio data to callback 157 | recorder.exportWAV(uploadAudioRecording) 158 | } 159 | 160 | function uploadAudioRecording(blob) { 161 | // Show processing phase in the UI 162 | processingView(); 163 | 164 | // Generate unique ID for upload audio file request 165 | requestId = generateRequestId(); 166 | 167 | // Create key for S3 object and upload input audio file 168 | var inputKey = 'input/' + requestId + '.wav' 169 | s3.upload({ 170 | Key: inputKey, 171 | Body: blob 172 | }, function(err, data) { 173 | if (err) { 174 | return alert('There was an error uploading your recording: ', err.message); 175 | } 176 | }); 177 | 178 | // Start polling for record audio result 179 | startPolling(requestId); 180 | } 181 | 182 | function uploadAudioFile() { 183 | // Show processing phase in the UI 184 | processingView(); 185 | 186 | // Generate unique ID for upload audio file request 187 | requestId = generateRequestId(); 188 | 189 | // Get input audio file data 190 | var files = document.getElementById('audio-file').files; 191 | if (!files.length) { 192 | return alert('Please choose a file to upload first.'); 193 | } 194 | var file = files[0]; 195 | var fileName = file.name; 196 | var fileExtension = fileName.split('.').pop(); 197 | 198 | // Create key for S3 object and upload input audio file 199 | var inputKey = 'input/' + requestId + '.' + fileExtension; 200 | s3.upload({ 201 | Key: inputKey, 202 | Body: file 203 | }, function(err, data) { 204 | if (err) { 205 | return alert('There was an error uploading your file: ', err.message); 206 | } 207 | }); 208 | 209 | // Start polling for upload audio file result 210 | startPolling(requestId); 211 | } 212 | 213 | // Poll for result of particular request 214 | function startPolling(requestId) { 215 | // Create expected key and URL for output audio file 216 | var outputKey = 'output/' + requestId + '.mp3'; 217 | var resultUrl = 'https://s3-eu-west-1.amazonaws.com/' + bucketName + '/' + outputKey; 218 | 219 | // Wait for 5 minutes until output audio file is created and display player or timeout request 220 | poll(function() { 221 | return urlExists(resultUrl); 222 | }, 300000, 150).then(function() { 223 | // Reset buttons and processing message 224 | resetView(); 225 | // Add audio player with result 226 | document.getElementById('audio-output').innerHTML = 'Audio output

'; 227 | }).catch(function() { 228 | // Reset buttons and processing message 229 | resetView(); 230 | return alert('Request failed or timed out :(') 231 | }); 232 | } 233 | --------------------------------------------------------------------------------