2016-05-31 21 views
5

Der folgende Code streamt eine Datei an einen Prozess. Ich möchte Audio/mp3 an viele Benutzer streamen, die es über html5 Audio-Tag hören. Wie kann es über File.stream! getan werden?Elixir stream audio an Benutzer

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 , 19 1, 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, ... >> ..............

Wie kann ich JavaScript verwenden, um diese Binärdaten zu lesen und sie über Audio-Tags zu hören?

Antwort

2

Wenn Sie ein Plug-basiertes Web-Framework verwenden, sollte es einigermaßen unkompliziert sein. Dies ist möglich, wenn Sie den Plug direkt verwenden oder wenn Sie ihn aus Phoenix verwenden (der auf einem Plug basiert).

Vielleicht mögen dieses

Sie wollen den Anschluss Ihres Stecker an einen Router in Phoenix ein Stecker wie dies würde den 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 

Vielleicht

auf Ihrer Seite
defmodule MyApp.Router do 
    use MyApp.Web, :router 

    get "/the_song", Audio, :song 
end 

Dann

<audio src="/the_song"> 
    Your browser does not support the <code>audio</code> element. 
</audio> 
+0

danke! es funktioniert, aber wirft eine Expectation "[Fehler] Ranch Listener Plugtest.HTTP hatte Verbindungsprozess gestartet mit: cowboy_protocol: start_link/4 bei #PID <0.261.0> beenden mit Grund: {{% File.Error {action:" stream ", Pfad: "./song.mp3", Grund:: enoent} .. "&& Wie kann ich es wie Radio streamen, so dass alle verbundenen Benutzer von derselben Sekunde hören? Für diesen Test kann ich den Song loopen, aber ich möchte mit dem nächsten Song in der Playlist fortfahren – IddoE

+0

Dieser Fehler besagt, dass die Datei nicht existiert. Sie müssen den Pfad auflösen - ich würde vorschlagen, keine relativen Pfade zu verwenden. Soweit Ihr tatsächliches Ziel, ist dies ein Schritt in Richtung es, aber Sie brauchen mehr. Jetzt sprichst du von einer Pubsub-Architektur. In Elixir sollte das überraschend einfach sein. Sie möchten einen einzelnen Prozess, der den Dateistrom ausführt und festhält und offene Verbindungen protokolliert. Ein GenServer wird gut funktionieren. Wenn es Blöcke aus dem Stream liest, sollte es in jede Verbindung schreiben, die es kennt. – rozap

+0

Nochmals vielen Dank @rozap, überprüfen Sie bitte verwandte Frage unter http://stackoverflow.com/questions/38551798 – IddoE