The following code streams a file to a process.
I want to stream audio/mp3
to many users who will hear it via html5 audio tag.
How can it be done via File.stream!
?
defmodule Test do
def start do
p = spawn(Test, :say, [])
send p, {self, "a message"}
end
def say do
receive do
{from, msg} ->
IO.puts "Process #{inspect self} says: #{msg}"
stream_bytes = 128
File.stream!("./song.mp3", [], stream_bytes)
|> Enum.each(fn chunk ->
IO.inspect chunk
end)
say
end
end
end
$: iex test.ex
iex(1)> Test.start
output:
<<171, 46, 254, 26, 163, 32, 178, 27, 0, 75, 17, 35, 4, 236, 51, 57, 5, 144, 154, 198, 166, 47, 62, 4, 61, 85, 67, 135, 16, 34, 82, 49, 57, 176, 131, 96, 116, 152, 232, 24, 32, 140, 220, 67, 73, 128, 165, 178, 230, 202, ...>> <<100, 220, 156, 191, 38, 0, 161, 117, 80, 16, 102, 91, 22, 5, 8, 66, 26, 7, 193, 155, 193, 66, 198, 28, 157, 244, 65, 131, 204, 240, 5, 172, 143, 44, 173, 85, 144, 2, 157, 144, 145, 97, 200, 236, 16, 49, 149, 150, 133, 67, ...>> <<150, 54, 37, 254, 192, 218, 218, 26, 69, 231, 88, 124, 33, 129, 169, 66, 117, 52, 214, 134, 130, 103, 85, 130, 48, 6, 144, 221, 153, 132, 8, 181, 26, 27, 83, 140, 54, 117, 149, 7, 60, 144, 237, 248, 132, 12, 210, 51, 103, 116, ...>> <<57, 2, 143, 220, 198, 182, 22, 177, 231, 126, 187, 147, 33, 9, 1, 5, 164, 2, 36, 105, 47, 255, 255, 255, 255, 255, 245, 54, 51, 225, 104, 98, 1, 184, 148, 206, 50, 135, 230, 28, 50, 47, 144, 134, 53, 16, 64, 130, 192, 198, ...>> ..............
how can I use JavaScript to read this binary data and hear it via audio tag ?
If you're using a plug based web framework it should be reasonably straight forward. This is possible if you're using plug directly or if you're using it from within phoenix (which is based on plug).
Maybe a plug like this would do the trick
defmodule Audio do
@chunk_size 128
def init(opts), do: opts
def song(conn, _opts) do
conn = conn
|> send_chunked(200)
|> put_resp_header("content-type", "audio/mpeg")
File.stream!("/some/song/somewhere.mp3", [], @chunk_size)
|> Enum.into(conn)
end
end
Maybe you want to hook up your plug to a phoenix router like this
defmodule MyApp.Router do
use MyApp.Web, :router
get "/the_song", Audio, :song
end
Then in your page
<audio src="/the_song">
Your browser does not support the <code>audio</code> element.
</audio>