The documentation live call control states that for a specific call ID, we receive a controlURL and a listenURL. However, the listenURL Listen URL: wss://phone-call-websocket.aws-us-west-2-backend-production3.vapi.ai/call_id/listen
is not working correctly and is returning the following error:
HTTP Status: 400 Bad Request 2025/01/02 14:36:09 HTTP Headers: map[Alt-Svc:[h3=":443"; ma=86400] Cf-Cache-Status:[DYNAMIC] Cf-Ray:[8fb99766dbf554a1-DEL] Connection:[keep-alive] Content-Length:[30] Content-Type:[application/json] Date:[Thu, 02 Jan 2025 09:06:10 GMT] Server:[cloudflare] Set-Cookie:[_cfuvid=FOE3xNcNAAQ9nAbYpUexjFBnvXPCcFLTmPQwo8qzv8c-1735808770005-0.0.1.1-604800000; path=/; domain=.vapi.ai; HttpOnly; Secure; SameSite=None]] 2025/01/02 14:36:09 Error connecting to WebSocket server: websocket: bad handshake
which api key i have to provide in header.
Listen URL: wss://phone-call-websocket.aws-us-west-2-backend-production3.vapi.ai/9fcedad9-c0d0-4ed1-a099-f7f17a12d07e/listen
i want to use this listen url for processing live call streaming for further operation.
func LiveCallStreamingWebsocket(serverURL string) {
// Set up headers if needed
header := http.Header{}
// Example: header.Add("Authorization", "Bearer YOUR_TOKEN")
// Connect to the WebSocket server
c, resp, err := websocket.DefaultDialer.Dial(serverURL, header)
if err != nil {
if resp != nil {
log.Printf("HTTP Status: %s", resp.Status)
log.Printf("HTTP Headers: %v", resp.Header)
// Read the response body if needed
// body, _ := io.ReadAll(resp.Body)
// log.Printf("Response Body: %s", body)
}
log.Fatalf("Error connecting to WebSocket server: %v", err)
}
defer c.Close()
// Channel to handle OS interrupts for graceful shutdown
interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt)
// Channel to signal when the connection should be closed
done := make(chan struct{})
// Buffer to store PCM data
var pcmBuffer []byte
// Goroutine to read messages from the WebSocket
go func() {
defer close(done)
for {
messageType, message, err := c.ReadMessage()
if err != nil {
log.Println("Error reading message:", err)
return
}
switch messageType {
case websocket.BinaryMessage:
pcmBuffer = append(pcmBuffer, message...)
log.Printf("Received PCM data, buffer size: %d\n", len(pcmBuffer))
case websocket.TextMessage:
var msg interface{}
if err := json.Unmarshal(message, &msg); err != nil {
log.Println("Error unmarshalling message:", err)
continue
}
log.Println("Received message:", msg)
}
}
}()
// Wait for interrupt signal to gracefully shut down
for {
select {
case <-done:
return
case <-interrupt:
log.Println("Interrupt received, closing connection...")
// Close the WebSocket connection
err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
if err != nil {
log.Println("Error during closing WebSocket:", err)
return
}
// Save PCM data to file
if len(pcmBuffer) > 0 {
err := os.WriteFile("audio.pcm", pcmBuffer, 0644)
if err != nil {
log.Println("Error writing PCM data to file:", err)
} else {
log.Println("Audio data saved to audio.pcm")
}
}
select {
case <-done:
case <-time.After(time.Second):
}
return
}
}
}