Last active
April 21, 2020 13:39
-
-
Save seanmtracey/f820a0df2400a965dfe72d8b2f833919 to your computer and use it in GitHub Desktop.
The code for the IBM Developer UK word counter tutorial
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[{"id":"b76061c1.f23da","type":"inject","z":"92d160d6.54f31","name":"Blue","topic":"","payload":"#000099","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":530,"y":435,"wires":[["e6cb0afc.efffd8"]]},{"id":"756acaa2.4247b4","type":"inject","z":"92d160d6.54f31","name":"Orange","topic":"","payload":"#ffff00","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":530,"y":495,"wires":[["e6cb0afc.efffd8"]]},{"id":"72dd9b62.3bc494","type":"inject","z":"92d160d6.54f31","name":"Green","topic":"","payload":"#00ff00","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":530,"y":555,"wires":[["e6cb0afc.efffd8"]]},{"id":"7e5328f4.4aa2b8","type":"function","z":"92d160d6.54f31","name":"Word Counter","func":"const MAX_WORDS_ALLOWED = 185;\nconst ALLOWANCE = 40;\nconst WINDOW_TRANSCRIPTS = context.get('audio') || [];\n\nconst data = {\n time : Date.now() | 0,\n words : msg.transcription.split(' ')\n};\n\nWINDOW_TRANSCRIPTS.push(data);\n\nconst MINUTE_TRANSCRIPT_WINDOW = WINDOW_TRANSCRIPTS.filter(datum => {return (Date.now() | 0) - datum.time < 60000 });\n\ncontext.set('audio', MINUTE_TRANSCRIPT_WINDOW);\n\nconst WORDS_COUNTED = MINUTE_TRANSCRIPT_WINDOW.reduce( (acc, data) => {\n \n console.log('COUNT!:', acc, data);\n return acc + data.words.length\n \n}, 0 );\n\n\nconst TIME_ELAPSED = (MINUTE_TRANSCRIPT_WINDOW[MINUTE_TRANSCRIPT_WINDOW.length - 1].time) - MINUTE_TRANSCRIPT_WINDOW[0].time;\nconst MULT_FACTOR = (60000 / TIME_ELAPSED);\nconst WORDS_SPOKEN = WORDS_COUNTED * MULT_FACTOR;\n\nconst NB = `EST: ${WORDS_SPOKEN} COUNTED: ${WORDS_COUNTED} TIME ELAPSED: ${TIME_ELAPSED}`;\nconsole.log(NB);\n\nmsg.NB = NB;\n\n\nif(WORDS_SPOKEN > MAX_WORDS_ALLOWED){\n msg.payload = '#0000ff';\n} else if(WORDS_SPOKEN > MAX_WORDS_ALLOWED - ALLOWANCE){\n msg.payload = '#ffff00';\n} else {\n msg.payload = '#00ff00';\n}\n\nmsg.words_spoken = WORDS_SPOKEN === Infinity ? 0 : WORDS_SPOKEN;\n\nreturn msg;","outputs":1,"noerr":0,"x":590,"y":285,"wires":[["c5494993.caaf68","eac868c.c377c98","ff0f84e9.6e58c8","e6cb0afc.efffd8"]]},{"id":"c5494993.caaf68","type":"debug","z":"92d160d6.54f31","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":785,"y":225,"wires":[]},{"id":"9bb56441.c2fbc8","type":"websocket in","z":"92d160d6.54f31","name":"","server":"acd8ae06.c9bf5","client":"","x":145,"y":225,"wires":[["c5494993.caaf68","e747537e.709ac"]]},{"id":"7a64e849.b77098","type":"http in","z":"92d160d6.54f31","name":"","url":"/word-count","method":"get","upload":false,"swaggerDoc":"","x":155,"y":150,"wires":[["ac02e244.643f5"]]},{"id":"f46e6c2b.8ab33","type":"http response","z":"92d160d6.54f31","name":"","statusCode":"","headers":{},"x":815,"y":150,"wires":[]},{"id":"ac02e244.643f5","type":"template","z":"92d160d6.54f31","name":"CSS","field":"payload.styles","fieldType":"msg","format":"css","syntax":"mustache","template":"/*\n* {\n background: blue;\n}*/\n\nbody{\n display: flex;\n flex-direction: column;\n align-items: center;\n font-family: sans-serif;\n}\n\n\n#toggle{\n width: 200px;\n padding: 1em;\n border: 1px solid black;\n border-radius: 10px;\n cursor: pointer;\n font-weight: 800;\n font-size: 1em;\n outline: 0 solid transparent;\n}\n\n#toggle[data-state=\"started\"]{\n color: white;\n border-color: red;\n background: #ff7878;\n animation: pulse 2.5s infinite;\n\t-moz-animation: pulse 2.5s infinite;\n\t-webkit-animation: pulse 2.5s infinite;\n\t-o-animation: pulse 2.5s infinite;\n}\n\n@keyframes pulse{\n\t0% {opacity:1; }\n\t50% {opacity: 0.5; }\n 100% {opacity: 1; }\n}\n\n@-moz-keyframes pulse{\n\t0% {opacity:1; }\n\t50% {opacity: 0.5; }\n 100% {opacity: 1; }\n}\n\t\n@-webkit-keyframes pulse{\n\t0% {opacity:1; }\n\t50% {opacity: 0.5; }\n 100% {opacity: 1; }\n}\n\t\n@-o-keyframes pulse{\n\t0% {opacity:1; }\n\t50% {opacity: 0.5; }\n 100% {opacity: 1; }\n}","output":"str","x":350,"y":150,"wires":[["67afa70a.c35628"]]},{"id":"e747537e.709ac","type":"watson-speech-to-text","z":"92d160d6.54f31","name":"","alternatives":1,"speakerlabels":false,"smartformatting":false,"lang":"en-US","langhidden":"en-US","langcustom":"NoCustomisationSetting","langcustomhidden":"","custom-weight":"","band":"BroadbandModel","bandhidden":"BroadbandModel","keywords":"","keywords-threshold":"","word-confidence":false,"password":"","apikey":"","payload-response":false,"streaming-mode":false,"streaming-mute":false,"auto-connect":false,"discard-listening":false,"disable-precheck":true,"default-endpoint":false,"service-endpoint":"https://api.eu-gb.speech-to-text.watson.cloud.ibm.com/instances/5a99436a-752e-4a3f-bcbb-7e4a349fdb3f","x":350,"y":285,"wires":[["7e5328f4.4aa2b8"]]},{"id":"eac868c.c377c98","type":"debug","z":"92d160d6.54f31","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"words_spoken","x":825,"y":285,"wires":[]},{"id":"ec16d20c.0ecf4","type":"template","z":"92d160d6.54f31","name":"HTML","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<!DOCTYPE html>\n<html>\n <head>\n <title>Simple Mic Streamer</title>\n <style>\n {{{payload.styles}}}\n </style>\n </head>\n <body>\n \n <h1>Sean's Friendly Word Counting Assistant</h1>\n\n <button id=\"toggle\" data-state=\"stopped\">Start</button>\n \n <script>\n\n {{{payload.script}}}\n \n </script>\n \n </body>\n</html>","output":"str","x":650,"y":150,"wires":[["f46e6c2b.8ab33"]]},{"id":"67afa70a.c35628","type":"template","z":"92d160d6.54f31","name":"Script","field":"payload.script","fieldType":"msg","format":"javascript","syntax":"mustache","template":"(function(){\n \n 'use strict';\n \n let ws = createWebSocket('wss://' + window.location.host + '/ws/audio');\n bindWebSocketEvents(ws);\n\n function createWebSocket(URL){\n console.log('Attempting to establish WS connection to:', URL);\n return new WebSocket(URL);\n }\n\n function bindWebSocketEvents(WS){\n \n ws.addEventListener('open', function(){\n console.log('WS connection established'); \n }, false);\n \n ws.addEventListener('message', function(msg){\n console.log('WS message:', msg);\n }, false);\n \n ws.addEventListener('error', function(err){\n console.log('WS error:', err);\n }, false);\n \n ws.addEventListener('close', function(e){\n console.log('WS connection closed:', e);\n ws = createWebSocket('wss://' + window.location.host + '/ws/audio');\n bindWebSocketEvents(ws);\n });\n\n }\n\n const button = document.querySelector('button');\n \n let mR;\n\n const constraints = {\n video : false,\n audio : true\n };\n\n navigator.mediaDevices.getUserMedia(constraints)\n .then(function(stream){\n\n mR = new MediaRecorder(stream);\n \n mR.start();\n \n setInterval(function(){\n\n mR.ondataavailable = function(e){\n console.log(e.data);\n \n if(button.dataset.state === 'started'){\n console.log('Sending to server:', e.data);\n if(ws.readyState === 1){\n ws.send(e.data);\n }\n }\n }\n\n mR.stop();\n\n mR = new MediaRecorder(stream);\n mR.start();\n\n }, 5000);\n\n\n })\n .catch(function(err){\n console.log('Media stream err:', err);\n })\n ;\n\n button.addEventListener('click', function(){\n\n this.dataset.state = this.dataset.state === 'stopped' ? 'started' : 'stopped';\n this.textContent = this.dataset.state === 'stopped' ? 'Start' : 'Stop';\n \n }, false);\n \n}());\n","output":"str","x":500,"y":150,"wires":[["ec16d20c.0ecf4"]]},{"id":"ff0f84e9.6e58c8","type":"debug","z":"92d160d6.54f31","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"NB","x":795,"y":345,"wires":[]},{"id":"e6cb0afc.efffd8","type":"mqtt out","z":"92d160d6.54f31","name":"","topic":"gloworb-emulator","qos":"","retain":"","broker":"efc46a04.2ab5d8","x":835,"y":465,"wires":[]},{"id":"b6f8c15e.c18e6","type":"inject","z":"92d160d6.54f31","name":"Red","topic":"","payload":"#FF0000","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":530,"y":645,"wires":[["e6cb0afc.efffd8"]]},{"id":"acd8ae06.c9bf5","type":"websocket-listener","z":"","path":"/ws/audio","wholemsg":"false"},{"id":"efc46a04.2ab5d8","type":"mqtt-broker","z":"","name":"","broker":"mqtt.eclipse.org","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""}] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Simple Mic Streamer</title> | |
<style> | |
{{{payload.styles}}} | |
</style> | |
</head> | |
<body> | |
<h1>Sean's Friendly Word Counting Assistant</h1> | |
<button id="toggle" data-state="stopped">Start</button> | |
<script> | |
{{{payload.script}}} | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(){ | |
'use strict'; | |
let ws = createWebSocket('wss://' + window.location.host + '/ws/audio'); | |
bindWebSocketEvents(ws); | |
function createWebSocket(URL){ | |
console.log('Attempting to establish WS connection to:', URL); | |
return new WebSocket(URL); | |
} | |
function bindWebSocketEvents(WS){ | |
ws.addEventListener('open', function(){ | |
console.log('WS connection established'); | |
}, false); | |
ws.addEventListener('message', function(msg){ | |
console.log('WS message:', msg); | |
}, false); | |
ws.addEventListener('error', function(err){ | |
console.log('WS error:', err); | |
}, false); | |
ws.addEventListener('close', function(e){ | |
console.log('WS connection closed:', e); | |
ws = createWebSocket('wss://' + window.location.host + '/ws/audio'); | |
bindWebSocketEvents(ws); | |
}); | |
} | |
const button = document.querySelector('button'); | |
let mR; | |
const constraints = { | |
video : false, | |
audio : true | |
}; | |
navigator.mediaDevices.getUserMedia(constraints) | |
.then(function(stream){ | |
mR = new MediaRecorder(stream); | |
mR.start(); | |
setInterval(function(){ | |
mR.ondataavailable = function(e){ | |
console.log(e.data); | |
if(button.dataset.state === 'started'){ | |
console.log('Sending to server:', e.data); | |
if(ws.readyState === 1){ | |
ws.send(e.data); | |
} | |
} | |
} | |
mR.stop(); | |
mR = new MediaRecorder(stream); | |
mR.start(); | |
}, 5000); | |
}) | |
.catch(function(err){ | |
console.log('Media stream err:', err); | |
}) | |
; | |
button.addEventListener('click', function(){ | |
this.dataset.state = this.dataset.state === 'stopped' ? 'started' : 'stopped'; | |
this.textContent = this.dataset.state === 'stopped' ? 'Start' : 'Stop'; | |
}, false); | |
}()); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* { | |
background: blue; | |
}*/ | |
body{ | |
display: flex; | |
flex-direction: column; | |
align-items: center; | |
font-family: sans-serif; | |
} | |
#toggle{ | |
width: 200px; | |
padding: 1em; | |
border: 1px solid black; | |
border-radius: 10px; | |
cursor: pointer; | |
font-weight: 800; | |
font-size: 1em; | |
outline: 0 solid transparent; | |
} | |
#toggle[data-state="started"]{ | |
color: white; | |
border-color: red; | |
background: #ff7878; | |
animation: pulse 2.5s infinite; | |
-moz-animation: pulse 2.5s infinite; | |
-webkit-animation: pulse 2.5s infinite; | |
-o-animation: pulse 2.5s infinite; | |
} | |
@keyframes pulse{ | |
0% {opacity:1; } | |
50% {opacity: 0.5; } | |
100% {opacity: 1; } | |
} | |
@-moz-keyframes pulse{ | |
0% {opacity:1; } | |
50% {opacity: 0.5; } | |
100% {opacity: 1; } | |
} | |
@-webkit-keyframes pulse{ | |
0% {opacity:1; } | |
50% {opacity: 0.5; } | |
100% {opacity: 1; } | |
} | |
@-o-keyframes pulse{ | |
0% {opacity:1; } | |
50% {opacity: 0.5; } | |
100% {opacity: 1; } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This is all of the code needed to follow the IBM Developer UK word counter tutorial. | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const MAX_WORDS_ALLOWED = 185; | |
const ALLOWANCE = 40; | |
const WINDOW_TRANSCRIPTS = context.get('audio') || []; | |
const data = { | |
time : Date.now() | 0, | |
words : msg.transcription.split(' ') | |
}; | |
WINDOW_TRANSCRIPTS.push(data); | |
const MINUTE_TRANSCRIPT_WINDOW = WINDOW_TRANSCRIPTS.filter(datum => {return (Date.now() | 0) - datum.time < 60000 }); | |
context.set('audio', MINUTE_TRANSCRIPT_WINDOW); | |
const WORDS_COUNTED = MINUTE_TRANSCRIPT_WINDOW.reduce( (acc, data) => { | |
console.log('COUNT!:', acc, data); | |
return acc + data.words.length | |
}, 0 ); | |
const TIME_ELAPSED = (MINUTE_TRANSCRIPT_WINDOW[MINUTE_TRANSCRIPT_WINDOW.length - 1].time) - MINUTE_TRANSCRIPT_WINDOW[0].time; | |
const MULT_FACTOR = (60000 / TIME_ELAPSED); | |
const WORDS_SPOKEN = WORDS_COUNTED * MULT_FACTOR; | |
const NB = `EST: ${WORDS_SPOKEN} COUNTED: ${WORDS_COUNTED} TIME ELAPSED: ${TIME_ELAPSED}`; | |
console.log(NB); | |
msg.NB = NB; | |
if(WORDS_SPOKEN > MAX_WORDS_ALLOWED){ | |
msg.payload = '#0000ff'; | |
} else if(WORDS_SPOKEN > MAX_WORDS_ALLOWED - ALLOWANCE){ | |
msg.payload = '#ffff00'; | |
} else { | |
msg.payload = '#00ff00'; | |
} | |
msg.words_spoken = WORDS_SPOKEN === Infinity ? 0 : WORDS_SPOKEN; | |
return msg; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment