How to use websocket data from external source with phoenix app?

In my phoenix app I’m trying to consume a live stream of data from a 3rd party service through websockets. The 3rd party client connects through my app at this url: wss://myapp.ngrok.io/datastream/websocket.

I copied the Phoenix.Socket.Transport docs example to set up the connection.

In endpoint.ex I have:

  socket "/datastream", MyAppWeb.DatastreamSocket,
    websocket: true,
    longpoll: false

and datastream_socket.ex:

defmodule MyAppWeb.DatastreamSocket do
  @behaviour Phoenix.Socket.Transport

  def child_spec(_opts) do
    # We won't spawn any process, so let's return a dummy task
    %{id: Task, start: {Task, :start_link, [fn -> :ok end]}, restart: :transient}
  end

  def connect(map) do
    {:ok, map}
  end

  def init(state) do
    {:ok, state}
  end

  def handle_in({text, _opts}, state) do
    {:reply, :ok, {:text, text}, state}
  end

  def handle_info(_, state) do
    {:ok, state}
  end

  def terminate(_reason, state) do
    :ok
  end
end

I’ve inspected the state and it’s sending in the data, but I’m not sure what to do next.

My use case is to take the data from the external client (which is a stream of raw audio encoded in base64) and stream it to users’ browsers.

I was thinking I could set up a channel for users to connect to, and then broadcast the state from datastream_socket.ex's handle_in/2 function to the channel. Does this make sense?

Just to clarify. The third party connects to that WebSocket above, then you will have clients on an additional socket/channel that follows the standard Phoenix socket approach? If so, that sounds like a good first approach. I’m not sure how often the third party is pushing data, but you wouldn’t have any performance concerns unless it’s quite high volume.

It could be useful to know when the third party is connected to your system so clients can know that as well

1 Like

The third party connects to that WebSocket above, then you will have clients on an additional socket/channel that follows the standard Phoenix socket approach?

Yea that’s what I was thinking.

Not sure what qualifies as high volume, but in 3 seconds the datastream_socket.ex websocket received 137 messages from the external service. Each message coming in is a chunk of raw audio data.

It could be useful to know when the third party is connected to your system so clients can know that as well

The 3rd party first sends a connected message, then a start message, then it begins sending the data. When the socket closes it sends a stop message.

The one thing I would be careful here is latency, since that heavily affects audio. I’m not sure if you’re doing a slight lagged buffer or anything, but that could be useful to avoid real-time audio problems.

If you’re in a distributed system, each packet is going to hit your server and then get broadcast to the local node (close to immediate) plus the other connected nodes (network hop) and then get sent to the client (over the established WebSocket, so it has network hop but generally will be fast. It’s worth making sure that this doesn’t add any latency into the final product.

1 Like