2016-05-31 44 views
5

Il seguente codice esegue lo streaming di un file in un processo. Voglio lo streaming audio/mp3 per molti utenti che lo ascolteranno tramite tag audio html5. Come può essere effettuato tramite File.stream!?Elixir stream audio per gli utenti

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

uscita:

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

Come posso utilizzare JavaScript per leggere questi dati binari e ascoltarli tramite tag audio?

risposta

2

Se si utilizza un framework Web basato su plug dovrebbe essere ragionevolmente semplice. Questo è possibile se stai usando la spina direttamente o se la stai usando da phoenix (che si basa sulla spina).

Forse un tappo come questo sarebbe fare il trucco

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 

Forse si vuole collegare il connettore ad un router phoenix come questo

defmodule MyApp.Router do 
    use MyApp.Web, :router 

    get "/the_song", Audio, :song 
end 

Poi nella tua pagina

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

grazie! funziona, ma genera un'espettazione "[error] Listener Ranch Plugtest.HTTP ha avuto il processo di connessione avviato con: cowboy_protocol: start_link/4 al #PID <0.261.0> exit with reason: {{% File.Error {action:" stream ", percorso: "./song.mp3", motivo:: enoent} .. "&& come posso eseguire lo streaming come radio in modo che tutti gli utenti connessi possano ascoltare dallo stesso secondo? per questo test posso eseguire il loop della canzone ma voglio continuare con la canzone successiva nella playlist – IddoE

+0

Questo errore dice che il file non esiste. Dovrai risolvere il percorso: ti suggerirei di non utilizzare percorsi relativi. Per quanto riguarda il tuo obiettivo attuale, questo è un passo avanti ma è necessario di più. Ora stai parlando di un'architettura pubsub. In Elisir questo dovrebbe essere sorprendentemente facile. Avrai bisogno di un singolo processo in esecuzione e che tenga il flusso di file e tenga traccia delle connessioni aperte. Un GenServer funzionerà bene. Mentre legge i pezzi dallo stream, dovrebbe scrivere su ogni connessione di cui è a conoscenza. – rozap

+0

grazie ancora @rozap, si prega di verificare la relativa domanda su http://stackoverflow.com/questions/38551798 – IddoE