@@ -20,16 +20,129 @@ def deps do
2020end
2121```
2222
23- ## Usage
23+ ## Demos
2424
2525The ` examples ` directory shows how to send and receive streams from a web browser.
26- There are following two demos there:
26+ There are the following three demos:
27+ * ` live_view ` - a simple Phoenix LiveView project using ` Membrane.WebRTC.Live.Player ` and ` Membrane.WebRTC.Live.Capture ` to echo video stream
28+ captured from the user's browser.
2729* ` phoenix_signaling ` - showcasing simple Phoenix application that uses ` Membrane.WebRTC.PhoenixSignaling ` to echo stream captured
2830from the user's browser and sent via WebRTC. See ` assets/phoenix_signaling/README.md ` for details on how to run the demo.
29- * ` webrtc_signaling ` - it consists of two scripts: ` file_to_browser.exs ` and ` browser_to_file.exs ` . The first one display stream from
30- the fixture file in the user's browser. The later one captures user's camera input from the browser and saves it in the file.
31+ * ` webrtc_signaling ` - it consists of two scripts: ` file_to_browser.exs ` and ` browser_to_file.exs ` . The first one displays the stream from
32+ the fixture file in the user's browser. The latter captures the user's camera input from the browser and saves it in the file.
3133To run one of these demos, type: ` elixir <script_name> ` and visit ` http://localhost:4000 ` .
3234
35+ ## Exchanging Signaling Messages
36+
37+ To establish a WebRTC connection you have to exchange WebRTC signaling messages between peers.
38+ In ` membrane_webrtc_plugin ` it can be done by the user, with ` Membrane.WebRTC.Signaling ` or by passing WebSocket address to
39+ ` Membrane.WebRTC.Source ` or ` Membrane.WebRTC.Sink ` , but there are two additional ways of doing it, dedicated to be used within
40+ ` Phoenix ` projects:
41+ - The first one is to use ` Membrane.WebRTC.PhoenixSignaling ` along with ` Membrane.WebRTC.PhoenixSignaling.Socket `
42+ - The second one is to use ` Phoenix.LiveView ` ` Membrane.WebRTC.Live.Player ` or ` Membrane.WebRTC.Live.Capture ` . These modules expect
43+ ` t:Membrane.WebRTC.Signaling.t/0 ` as an argument and take advantage of WebSocket used by ` Phoenix.LiveView ` to exchange WebRTC
44+ signaling messages, so there is no need to add any code to handle signaling messages.
45+
46+ ### How to use Membrane.WebRTC.PhoenixSignaling in your own Phoenix project?
47+
48+ The see the full example, visit ` example/phoenix_signaling ` .
49+
50+ 1 . Create a new socket in your application endpoint, using the ` Membrane.WebRTC.PhoenixSignaling.Socket ` , for instance at ` /signaling ` path:
51+ ```
52+ socket "/signaling", Membrane.WebRTC.PhoenixSignaling.Socket,
53+ websocket: true,
54+ longpoll: false
55+ ```
56+ 2 . Create a Phoenix signaling channel with the desired signaling ID and use it as ` Membrane.WebRTC.Signaling.t() `
57+ for ` Membrane.WebRTC.Source ` , ` Membrane.WebRTC.Sink ` or [ ` Boombox ` ] ( https://github.com/membraneframework/boombox ) :
58+ ```
59+ signaling = Membrane.WebRTC.PhoenixSignaling.new("<signaling_id>")
60+
61+ # use it with Membrane.WebRTC.Source:
62+ child(:webrtc_source, %Membrane.WebRTC.Source{signaling: signaling})
63+ |> ...
64+
65+ # or with Membrane.WebRTC.Sink:
66+ ...
67+ |> child(:webrtc_sink, %Membrane.WebRTC.Sink{signaling: signaling})
68+
69+ # or with Boombox:
70+ Boombox.run(
71+ input: {:webrtc, signaling},
72+ output: ...
73+ )
74+ ```
75+
76+ > Please note that ` signaling_id ` is expected to be globally unique for each WebRTC connection about to be
77+ > estabilished. You can, for instance:
78+ > 1 . Generate a unique id with ` :uuid ` package and assign it to the connection in the page controller:
79+ > ```
80+ >unique_id = UUID.uuid4()
81+ >render(conn, :home, layout: false, signaling_id: unique_id)
82+ >```
83+ >
84+ >2. Generate HTML based on HEEx template, using the previously set assign:
85+ >```
86+ ><video id="videoPlayer" controls muted autoplay signaling_id={@signaling_id}></video>
87+ >```
88+ >
89+ >3. Access it in your client code:
90+ >```
91+ >const videoPlayer = document.getElementById('videoPlayer');
92+ >const signalingId = videoPlayer.getAttribute('signaling_id');
93+ >```
94+
95+
96+ 3. Use the Phoenix Socket to exchange WebRTC signaling data.
97+ ```
98+ let socket = new Socket("/signaling", {params: {token: window.userToken}})
99+ socket.connect()
100+ let channel = socket.channel('<signaling_id>')
101+ channel.join()
102+ .receive("ok", resp => { console.log("Signaling socket joined successfully", resp)
103+ // here you can exchange WebRTC data
104+ })
105+ .receive("error", resp => { console.log("Unable to join signaling socket", resp) })
106+ ```
107+
108+ Visit `examples/phoenix_signaling/assets/js/signaling.js` to see how WebRTC signaling messages exchange might look like.
109+
110+ ## Integrating Phoenix.LiveView with Membrane WebRTC Plugin
111+
112+ `membrane_webrtc_plugin` comes with two `Phoenix.LiveView`s:
113+ - `Membrane.WebRTC.Live.Capture` - exchanges WebRTC signaling messages between `Membrane.WebRTC.Source` and the browser. It
114+ expects the same `Membrane.WebRTC.Signaling` that has been passed to the related `Membrane.WebRTC.Source`. As a result,
115+ `Membrane.Webrtc.Source` will return the media stream captured from the browser, where `Membrane.WebRTC.Live.Capture` has been
116+ rendered.
117+ - `Membrane.WebRTC.Live.Player` - exchanges WebRTC signaling messages between `Membrane.WebRTC.Sink` and the browser. It
118+ expects the same `Membrane.WebRTC.Signaling` that has been passed to the related `Membrane.WebRTC.Sink`. As a result,
119+ `Membrane.WebRTC.Live.Player` will play media streams passed to the related `Membrane.WebRTC.Sink`. Currently supports up
120+ to one video stream and up to one audio stream.
121+
122+ ### Usage
123+
124+ To use `Phoenix.LiveView`s from this repository, you have to use related JS hooks. To do so, add the following code snippet to `assets/js/app.js`
125+
126+ ```js
127+ import { createCaptureHook, createPlayerHook } from "membrane_webrtc_plugin";
128+
129+ let Hooks = {};
130+ const iceServers = [{ urls: "stun:stun.l.google.com:19302" }];
131+ Hooks.Capture = createCaptureHook(iceServers);
132+ Hooks.Player = createPlayerHook(iceServers);
133+ ```
134+
135+ and add ` Hooks ` to the WebSocket constructor. It can be done in the following way:
136+
137+ ``` js
138+ new LiveSocket (" /live" , Socket, {
139+ params: SomeParams,
140+ hooks: Hooks,
141+ });
142+ ```
143+
144+ To see the full usage example, you can go to ` examples/live_view/ ` directory in this repository (take a look especially at ` examples/live_view/assets/js/app.js ` and ` examples/live_view/lib/example_project_web/live_views/echo.ex ` ).
145+
33146## Copyright and License
34147
35148Copyright 2020, [ Software Mansion] ( https://swmansion.com/?utm_source=git&utm_medium=readme&utm_campaign=membrane_webrtc_plugin )
0 commit comments