Created
October 4, 2023 01:53
-
-
Save kylemcdonald/c9df6e5a9e09370311246bdfd500d826 to your computer and use it in GitHub Desktop.
Twilio app for repeating everything someone has said once they say the word "repeat".
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 WebSocket = require("ws"); | |
const express = require("express"); | |
const app = express(); | |
const server = require("http").createServer(app); | |
const wss = new WebSocket.Server({ server }); | |
const path = require("path"); | |
const fs = require("fs"); | |
require("dotenv").config(); | |
const speech = require("@google-cloud/speech"); | |
const client = new speech.SpeechClient(); | |
const request = { | |
config: { | |
encoding: "MULAW", | |
sampleRateHertz: 8000, | |
languageCode: "en-US", | |
}, | |
interimResults: true | |
}; | |
wss.on("connection", function connection(ws) { | |
console.log("New Connection Initiated"); | |
let recognizeStream = null; | |
let recording = Buffer.from([]); | |
let repeated = false; | |
ws.on("message", function incoming(message) { | |
const msg = JSON.parse(message); | |
switch (msg.event) { | |
case "connected": | |
console.log(`A new call has connected.`); | |
break; | |
case "start": | |
const streamSid = msg.streamSid; | |
console.log(`Starting Media Stream ${streamSid}`); | |
recognizeStream = client | |
.streamingRecognize(request) | |
.on("error", console.error) | |
.on("data", (data) => { | |
const transcript = data.results[0].alternatives[0].transcript; | |
console.log(transcript); | |
wss.clients.forEach((client) => { | |
if (client.readyState === WebSocket.OPEN) { | |
if (transcript.toLowerCase().includes("repeat") && !repeated) { | |
repeated = true; | |
client.send( | |
JSON.stringify({ | |
event: "media", | |
streamSid, | |
media: { | |
payload: Buffer.from(recording).toString("base64"), | |
}, | |
}) | |
); | |
client.send( | |
JSON.stringify({ | |
event: "mark", | |
streamSid, | |
mark: { | |
name: "repeat", | |
}, | |
}) | |
); | |
} | |
client.send( | |
JSON.stringify({ | |
event: "interim-transcription", | |
text: transcript, | |
}) | |
); | |
} | |
}); | |
}); | |
break; | |
case "media": | |
let payload = msg.media.payload; | |
let decoded = Buffer.from(payload, "base64"); | |
recording = Buffer.concat([recording, decoded]); | |
recognizeStream.write(msg.media.payload); | |
break; | |
case "stop": | |
console.log(`Call Has Ended`); | |
recognizeStream.destroy(); | |
let filename = "audio.pcm"; | |
fs.writeFileSync(filename, recording); | |
break; | |
} | |
}); | |
}); | |
app.use(express.static("public")); | |
app.get("/", (req, res) => res.sendFile(path.join(__dirname, "/index.html"))); | |
app.post("/", (req, res) => { | |
res.set("Content-Type", "text/xml"); | |
res.send(` | |
<Response> | |
<Say>Let's go!</Say> | |
<Connect> | |
<Stream url="wss://${req.headers.host}/"/> | |
</Connect> | |
<Pause length="60" /> | |
</Response> | |
`); | |
}); | |
console.log("Listening on Port 8080"); | |
server.listen(8080); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment