Twilio를 사용하여 검색 가능한 전화 호출 계기판을 구축하다
32161 단어 twiliotranscriptsearchtutorial
사용자는 Twilio 전화번호로 전화를 걸 수 있으며, 이 번호는 녹음할 때 당신의 대리에게 전달될 것입니다.통화가 끝나면 Deepgram의 음성인식 API를 사용해 성적표를 받고 검색 가능한 대시보드를 통해 Vue와 통합할 것입니다.js.앞부분은 매우 가볍기 때문에 어떤 프레임 (또는 프레임이 아예 없거나) 으로도 그것을 구축할 수 있다.
최종 항목 코드를 보고 싶으면 https://github.com/deepgram-devs/twilio-voice-searchable-log 에서 찾을 수 있습니다.
저희가 시작하기 전에.
다음이 필요합니다.
npm init -y
생성 package.json
파일을 실행하고 다음 패키지를 설치합니다.npm install @deepgram/sdk twilio dotenv express body-parser nedb-promises
코드 편집기에서 파일을 열고 자격 증명 및 설정으로 채우는 .env
파일을 만듭니다.DG_KEY=replace_with_deepgram_key
TWILIO_ACCOUNT_SID=replace_with_sid
TWILIO_AUTH_TOKEN=replace_with_auth_token
TWILIO_NUMBER=replace_with_twilio_phone_number
FORWARDING_NUMBER=replace_with_your_phone_number
너는 이것을 나눠서는 안 된다.env 파일은 민감한 증거를 포함하기 때문입니다.git 버전 제어를 사용한다면 이 파일을 무시하십시오.index.js
파일을 만들고 코드 편집기에서 엽니다.종속성 준비
파일 상단에는 다음 패키지가 필요합니다.
require('dotenv').config()
const express = require('express')
const bodyParser = require('body-parser')
const nedb = require('nedb-promises')
const Twilio = require('twilio')
const { Deepgram } = require('@deepgram/sdk')
새로운nedb 데이터베이스를 만듭니다.이렇게 하면 기존 파일이 로드되고 존재하지 않으면 다음과 같이 생성됩니다.const db = nedb.create('calls.db')
Twilio Helper 라이브러리를 초기화하고 다음을 수행합니다Deepgram Node SDK.const twilio = new Twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN)
const deepgram = new Deepgram(process.env.DG_KEY)
Express 서버 만들기
초기화
express
인스턴스, 구성body-parser
및 public
디렉토리, 포트 3000에서 시작:const app = express()
app.use(bodyParser.urlencoded({ extended: false }))
app.use(express.static('public'))
// Further code goes here
app.listen(3000, console.log(`Listening at ${new Date().toISOString()}`))
프로젝트 개요
사용자가 Twilio 번호로 전화를 걸 때, Google 프로그램은 대량의 정보를 포함하는POST 요청을 받을 것입니다. Google은 그들의 전화번호와 통화 식별자를 가져와 데이터베이스에 추가할 것입니다.우리는 응용 프로그램에 호출을 실제 번호로 전달하고 녹음을 시작하도록 지시할 것입니다.통화가 끝나면 녹음은 저장되고, 준비가 되면 Twilio는 녹음 정보를 프로그램으로 보냅니다.
우리는 녹음 URL을 Deepgram에 보내고 사본을 받아서 보답할 것이다.녹음 상세한 정보는 통화 식별자도 포함하기 때문에 우리는 녹음 URL과 기록을 기존의 데이터베이스 항목에 추가할 수 있다.
일단 데이터베이스에 데이터가 생기면 마지막 단계는 클라이언트 검색으로 웹 템플릿을 구축하는 것이다. 우리는 이 블로그의 끝부분에서 이렇게 할 것이다.
Twilio 번호 설정
Twilio가 응용 프로그램에 데이터를 보낼 때, 공개적으로 접근할 수 있는 URL이 필요하지만, 우리 응용 프로그램은 로컬 기기에만 있습니다.다행히도, 우리는 ngrok 로컬에서 실행되는 프로그램에 요청을 전송할 임시 공공 URL을 제공할 수 있습니다.새 터미널을 열고 다음을 실행합니다.
npx ngrok http 3000
실행하면 터미널 대시보드에 Twilio에 제공할 수 있는 Ngrok URL이 표시됩니다.터미널ngrok을 다시 시작하거나 24시간 후에 다시 시작하면 URL이 변경됩니다. 다음 단계를 다시 완성해야 합니다.Twilio 콘솔에서 귀하의 전화번호 설정을 탐색하고 ngrok URL에 HTTP POST 요청을 보내기 위한 후면
/inbound
으로 설정합니다.전보를 받다.
index.js
파일에 Twilio 호출을 받을 수 있는 새 라우팅 프로세서를 추가합니다.app.post('/inbound', async (req, res) => {
const { Caller, CallSid } = req.body
// Add caller number, call indetifier, and date to the database
await db.insert({ Caller, CallSid, date: new Date() })
// Create Twilio instructions
const twiml = new Twilio.twiml.VoiceResponse()
const dial = twiml.dial({
record: 'record-from-answer-dual',
recordingStatusCallback: '/recordings',
})
dial.number(process.env.FORWARDING_NUMBER)
// Send response to Twilio
res.type('text/xml')
res.end(twiml.toString())
})
// Further code here
dial
변수는 여기서 가장 관건적인 것이다. 우리는 트와이리오에게 전화를 받은 후에 통화를 기록하고 각 채널에 스피커를 기록하라고 말했다.이것은 필수적인 것은 아니지만, 이후에 더욱 높은 품질의 성적표가 나올 것이다.녹음이 준비된 후, 우리는 Twilio에게 /recordings
데이터를 포함하는 POST 요청을 보내라고 알렸다.마지막으로, 우리는 Twilio에게 이 전화를 우리 .env
파일에 전송하는 번호를 알려 주었다. 아마도 프론트 데스크나 판매 대표일 것이다.테스트를 수행하기 전에 기록에 대한 빈 라우팅 프로그램을 만듭니다.
app.post('/recordings', async (req, res) => {
console.log('Recording received')
// Further code here
res.send('ok')
})
당신의 코드를 테스트하세요!node index.js
달리기를 사용하고ngrok가 여전히 운행하고 있음을 확보한다.과 다른 전화 번호로 Twilio 번호로 전화하십시오.env와 너의 전송 번호가 울릴 것이다.전화를 받고, 통화하고, 전화를 끊으면, 몇 초 후에 터미널에서 '이미 녹음을 받았다' 는 것을 볼 수 있을 것이다.성적표 생성 및 저장
교체
/recordings
경로 처리기:app.post('/recordings', async (req, res) => {
console.log('Recording received')
// Get values from data
const { CallSid, RecordingUrl } = req.body
// Get transcript
const transcriptionFeatures = {
punctuate: true,
utterances: true,
model: 'phonecall',
multichannel: true,
}
const transcript = await deepgram.transcription.preRecorded(
{ url: RecordingUrl },
transcriptionFeatures
)
// Format response
const utterances = transcript.results.utterances.map((utterance) => ({
channel: utterance.channel,
transcript: utterance.transcript,
}))
// Update database entry
await db.update({ CallSid }, { $set: { RecordingUrl, utterances } })
res.send('ok')
})
Twilio는 이 요청에 일련의 데이터를 보냅니다. 우리는 통화 표지부와 녹음된 URL에만 관심을 가지기 때문에 대상에 대한 압축을 취소함으로써 이 데이터를 추출합니다.그리고 우리는 Deepgram에 기록을 요구했다.이제 우리가 사용한 기능을 살펴보겠습니다.
punctuate
기능은 문장부호를 추가하여 읽기 편리하게 한다.utterances
기능은 단어뿐만 아니라 이 단어를 말하는 사용자를 지정합니다.model
기능을 통해 사용할 모델을 지정할 수 있습니다.우리는 일부 기본적인 모델이 잘 표현될 수 있지만, 특히 전화 교육을 받은 모델이 있기 때문에 여기서 그것을 지정한다.multichannel
기능은 Deepgram에 여러 개의 오디오 채널을 포함하는 오디오 파일을 보내고 있음을 알려줍니다.그것은 우리가 언제든지 누가 말하고 있는지 정확하게 식별할 수 있기 때문에 녹화의 질을 향상시켰다.[
{ "channel": 1, "transcript": "Hi, Kev." },
{ "channel": 0, "transcript": "Hello. How are you mum?" },
{ "channel": 1, "transcript": "I'm fine. Thank you. How are you?" },
{ "channel": 0, "transcript": "Yes. Not too bad at all. Thank you" }
]
마지막으로, 우리는 이 호출된 기존 데이터베이스 항목을 업데이트해서 녹음된 URL과 말한 것을 포함합니다.당신의 코드를 테스트하세요!앞의 테스트 절차를 반복하면 현재 새로운 데이터를 포함하는 데이터베이스 파일 (
calls.db
을 볼 수 있습니다.모든 녹음 가져오기
프로젝트 서버의 마지막 단계는 사본이 포함된 모든 호출을 반환하는 라우팅 프로세스를 구축하는 것입니다.
app.get('/recordings', async (req, res) => {
const recordings = await db
.find({ utterances: { $exists: true } })
.sort({ date: -1 })
res.json(recordings)
})
이 루트 프로세서도 결과를 정렬하기 때문에 가장 최근의 첫 번째이다.브라우저에서 데이터 수신
검색에는
public
와 파일 index.html
을 만듭니다.파일을 열고 페이지를 만들려면 다음과 같이 하십시오.<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Twilio x Deepgram Call Transcripts</title>
<style></style>
</head>
<body>
<div id="app"></div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script>
const app = new Vue({
el: '#app',
data: {
fuse: false,
calls: {
all: [],
selected: false,
},
filter: {
term: '',
results: [],
},
},
async created() {
// Further code goes here
},
methods: {
search() {},
},
})
</script>
</body>
</html>
우리의 첫 번째 목표는 GETdata.calls.all
루트 프로세서가 되돌아오는 데이터베이스에 있는 항목을 채우고 이 항목들로Fuse 검색 인덱스를 만드는 것이다./recordings
방법:this.calls.all = await fetch('/recordings').then((r) => r.json())
this.fuse = new Fuse(this.calls.all, {
keys: ['Caller', 'utterances.transcript'],
includeMatches: true,
threshold: 0.5,
})
서버를 재부팅하고 브라우저에서 Fuse.js로 이동합니다.DevTools 콘솔을 열고 created()
를 입력하여 이 값이 제대로 채워졌는지 확인합니다.http://localhost:3000
레코드 검색
app.calls.all
에 텍스트 입력을 추가하려면 다음과 같이 하십시오.<input
type="text"
placeholder="Search term"
v-model="filter.term"
@keyup="search"
/>
그리고 빈 <div id="app">
방법의 내부에서 Fuse를 사용하여 검색하고 결과를 search()
에게 분배합니다.this.filter.results = this.fuse.search(this.filter.term)
이제 결과를 계산한 다음 data.filter.results
아래에 결과를 표시합니다.<ol id="results">
<li v-for="result in filter.results">
<p><b>{{ result.item.Caller }} on {{ result.item.date }}</b></p>
<p v-for="match in result.matches">{{ match.value }}</p>
</li>
</ol>
완전한 기록을 제시하다
검색 결과를 클릭하면 전체 성적표를 보여 줍니다.요소의 끝에 이 속성을 추가합니다
<input>
. - 클릭한 항목으로 설정됩니다.<li v-for="result in filter.results" @click="calls.selected = result">
그리고 <li>
아래에 다른 data.calls.selected
를 추가하여 복사본의 말을 표시합니다.<ol id="full-call" v-if="calls.selected">
<li v-for="utterance in calls.selected.item.utterances">
<small>{{ utterance.channel == 0 ? 'Receiver' : 'Caller' }}</small>
<p>{{ utterance.transcript }}</p>
</li>
</ol>
Twilio의 다중 채널 오디오는 예측성이 있기 때문에 호출을 전달하는 수신기는 항상 0 채널에 있기 때문에 우리는 누가 말을 하고 있는지 더욱 잘 나타낼 수 있다.마지막으로 다음 CSS를
<ol>
의 <ol>
태그에 추가합니다.* { margin: 0; padding: 0; font-family: sans-serif; }
#app { display: grid; grid-template-columns: 1fr 1fr; paddi g: 1em; gap: 2em }
input { grid-column: 1 / span 2; font-size: 1em; padding: 0.5em; }
li { list-style: none; margin-bottom: 1em; }
#results li { cursor: pointer; }
새로 고침하면 완료된 항목이 표시됩니다.마무리
우리는 Twilio를 사용하여 통화를 전송하고 기록하는 방법, 기록의 유효 부하를 처리하여 성적표를 얻는 방법, 그리고 기본적인 클라이언트 모호한 검색을 실현하는 등 많은 일을 했다.우리는 또한 이 프로젝트를 확장하기 위해 많은 일을 할 수 있다.
Reference
이 문제에 관하여(Twilio를 사용하여 검색 가능한 전화 호출 계기판을 구축하다), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/deepgram/build-a-searchable-phone-call-dashboard-with-twilio-4091텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)