From b4d59c23a4bc48a9d74909ddcc9ee45e30e18db1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Martins?= Date: Wed, 12 Jul 2023 20:12:10 +0100 Subject: [PATCH] Add Streaming to Deepgram example --- streaming-to-deepgram/.env.example | 3 + streaming-to-deepgram/Dockerfile | 14 ++++ streaming-to-deepgram/app.js | 109 +++++++++++++++++++++++++++++ streaming-to-deepgram/package.json | 9 +++ 4 files changed, 135 insertions(+) create mode 100644 streaming-to-deepgram/.env.example create mode 100644 streaming-to-deepgram/Dockerfile create mode 100644 streaming-to-deepgram/app.js create mode 100644 streaming-to-deepgram/package.json diff --git a/streaming-to-deepgram/.env.example b/streaming-to-deepgram/.env.example new file mode 100644 index 0000000..1a07136 --- /dev/null +++ b/streaming-to-deepgram/.env.example @@ -0,0 +1,3 @@ +DEEPGRAM_TOKEN=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +NGROK_TOKEN=25FKaLUXXXXXXXXXXXXX_XXXXXXXXXXXXXXXXXX +PORT=3000 \ No newline at end of file diff --git a/streaming-to-deepgram/Dockerfile b/streaming-to-deepgram/Dockerfile new file mode 100644 index 0000000..ccdc3da --- /dev/null +++ b/streaming-to-deepgram/Dockerfile @@ -0,0 +1,14 @@ +FROM node:18 + +# Create app directory +WORKDIR /usr/src/app + +# Install app dependencies +COPY package*.json ./ +RUN npm install + +# Bundle app source +COPY . . + +EXPOSE 3000 +CMD [ "node", "app.js" ] \ No newline at end of file diff --git a/streaming-to-deepgram/app.js b/streaming-to-deepgram/app.js new file mode 100644 index 0000000..4023ab2 --- /dev/null +++ b/streaming-to-deepgram/app.js @@ -0,0 +1,109 @@ +require("dotenv").config() +const ngrok = require('ngrok') +let wss_url + +(async function () { + let ngrok_url = await ngrok.connect({ + authtoken: process.env.NGROK_TOKEN, + addr: process.env.PORT + }) + console.log("Please connect a Phone Number with the following Webhook URL:", ngrok_url + '/startStreaming') + wss_url = ngrok_url.replace("https://", "wss://") +})(); + +const WebSocket = require('ws') +const wss = new WebSocket.Server({ noServer: true }) +var express = require('express') +var app = express() + +app.use(express.json()) +app.use(express.urlencoded({ extended: true })) + +const { RestClient } = require('@signalwire/compatibility-api') +const { Deepgram } = require("@deepgram/sdk") +const deepgram = new Deepgram(process.env.DEEPGRAM_TOKEN) + +app.post("/startStreaming", async (req, res) => { + const response = new RestClient.LaML.VoiceResponse() + + const start = response.start(); + start.stream({ + url: wss_url, + track: 'both_tracks' + }) + response.pause({ length: 1 }) + response.say("Please wait one moment.") + response.pause({ length: 3 }) + response.say("Yes, we are open Monday through Friday.") + response.pause({ length: 60 }) + + res.send(response.toString()) +}); + +const server = app.listen(process.env.PORT, () => { + console.log(`Listening on port ${process.env.PORT}\n`) +}); + +function createDeepgramConnection() { + return deepgram.transcription.live({ + punctuate: true, + model: "phonecall", + encoding: "mulaw", + channels: 1, + sample_rate: 8000 + }) +} + +function listenForTranscriptionResults(deepgramConnection, callSid, callLeg) { + deepgramConnection.addListener("transcriptReceived", (result) => { + let data = JSON.parse(result) + + if (data.type == 'Results' && data.channel.alternatives[0].transcript != '') { + console.log(callSid, callLeg, data.channel.alternatives[0].transcript) + } + + }); +} + +server.on('upgrade', (request, socket, head) => { + wss.handleUpgrade(request, socket, head, async (ws) => { + console.log("New Connection Initiated.") + + const deepgramLiveInbound = createDeepgramConnection() + const deepgramLiveOutbound = createDeepgramConnection() + + ws.on('message', (message) => { + const msg = JSON.parse(message) + + switch (msg.event) { + case "connected": + console.log("A new call was connected.") + break + + case "start": + listenForTranscriptionResults(deepgramLiveInbound, msg.start.callSid, 'inbound') + listenForTranscriptionResults(deepgramLiveOutbound, msg.start.callSid, 'outbound') + break + + case "media": + const payload = Buffer.from(msg.media.payload, "base64") + + try { + if (msg.media.track === 'inbound' && deepgramLiveInbound.getReadyState() === 1) { + deepgramLiveInbound.send(payload) + } else if (msg.media.track === 'outbound' && deepgramLiveOutbound.getReadyState() === 1) { + deepgramLiveOutbound.send(payload) + } + } catch (error) { + console.log("Error:", error) + } + + break + + case "stop": + console.log("Call has ended.") + break + } + }); + }); +}); \ No newline at end of file diff --git a/streaming-to-deepgram/package.json b/streaming-to-deepgram/package.json new file mode 100644 index 0000000..87df87b --- /dev/null +++ b/streaming-to-deepgram/package.json @@ -0,0 +1,9 @@ +{ + "dependencies": { + "@deepgram/sdk": "^2.2.0", + "@signalwire/compatibility-api": "^3.1.2", + "dotenv": "^16.3.1", + "express": "^4.18.2", + "ngrok": "^5.0.0-beta.2" + } +}