Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebRTC Components #1

Open
wants to merge 46 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
be9250d
wip
FelonEkonom Feb 6, 2025
b8b612e
wip
FelonEkonom Feb 7, 2025
4996e6d
Try fix demo wip
FelonEkonom Feb 11, 2025
9ad6fa4
Maybe it works now
FelonEkonom Feb 11, 2025
626a508
Now player works more or less
FelonEkonom Feb 12, 2025
cef29f0
Rename demo
FelonEkonom Feb 12, 2025
8922025
Refactor js
FelonEkonom Feb 12, 2025
7d2f4cc
Suffix event names with player id
FelonEkonom Feb 12, 2025
874c175
Write Capture, write capture demo
FelonEkonom Feb 13, 2025
8beb69e
Logs refactor
FelonEkonom Feb 13, 2025
f6f434d
Refactor logs
FelonEkonom Feb 13, 2025
16f4533
Celanup demo
FelonEkonom Feb 13, 2025
83eaf49
Refactor live views, add example project
FelonEkonom Feb 17, 2025
43aaeef
Fix bugs in components and demo
FelonEkonom Feb 18, 2025
a512cc5
Add path to .. to esbuild in example project
FelonEkonom Feb 18, 2025
c5b853b
Add JS hooks
FelonEkonom Feb 18, 2025
82340a5
Add live view module content
FelonEkonom Feb 18, 2025
aa449df
Make example project work wip
FelonEkonom Feb 18, 2025
9040ff0
Create new example project
FelonEkonom Feb 18, 2025
791000b
Finally fix example project
FelonEkonom Feb 18, 2025
edf3322
Comment out phoenix header
FelonEkonom Feb 18, 2025
8ffc2f0
Remove old example project
FelonEkonom Feb 18, 2025
123d123
Delete single-file demos
FelonEkonom Feb 19, 2025
6c6972c
Rename boombox_live to membrane_webrtc_live
FelonEkonom Feb 19, 2025
d075767
Merge remote-tracking branch 'origin/master' into implement-webrtc-co…
FelonEkonom Feb 19, 2025
e5e823b
Refactor README.md
FelonEkonom Feb 19, 2025
7ef6aee
Refactor README.md
FelonEkonom Feb 19, 2025
745bdf8
Refactor liveview modules attrs
FelonEkonom Feb 19, 2025
63a8f3b
Refactor moduledocs of player and capture
FelonEkonom Feb 19, 2025
cbdc0a7
Remove leftovers
FelonEkonom Feb 19, 2025
d672533
Remove unnecesary modules
FelonEkonom Feb 19, 2025
c164850
Bump webrtc plugin 0.24.0
FelonEkonom Feb 21, 2025
30d3ca5
simplify liveviews APIs
mat-hek Feb 24, 2025
10e4194
Partially implement CR
FelonEkonom Feb 25, 2025
14f9209
Add captured video preview
FelonEkonom Feb 25, 2025
88dd337
Refactor player and capture
FelonEkonom Feb 26, 2025
aad34f2
Fix README.md
FelonEkonom Feb 26, 2025
5cf38ed
Fix dialyzer
FelonEkonom Feb 26, 2025
e6d833c
Fix lint
FelonEkonom Feb 27, 2025
2abbd7c
Fix lint
FelonEkonom Feb 27, 2025
e6ce995
Refactor example project filenames
FelonEkonom Feb 27, 2025
0d257ee
Send Objects via websocket instead of strings
FelonEkonom Mar 3, 2025
d71adac
Refactor element style
FelonEkonom Mar 3, 2025
4b3be44
Remove old debug code
FelonEkonom Mar 3, 2025
bc136cd
Refactor live render attrs
FelonEkonom Mar 3, 2025
af61686
Update attributes docs
FelonEkonom Mar 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions assets/capture.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,15 @@ export function createCaptureHook(iceServers = [{ urls: "stun:stun.l.google.com:
);
};

this.el.srcObject = new MediaStream();

for (const track of localStream.getTracks()) {
this.pc.addTrack(track, localStream);
this.el.srcObject.addTrack(track);
}

this.el.play();

this.handleEvent("webrtc_signaling-" + this.el.id, async (event) => {
const { type, data } = event;

Expand Down
29 changes: 17 additions & 12 deletions example_project/README.md
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's create a proper readme

  • write what this example does
  • mention which files are important
  • remove the Phoenix links
  • mention that this uses boombox

Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
# ExampleProject
# Example Project

To start your Phoenix server:
Example project showing how `Membrane.WebRTC.Live.Capture` and `Membrane.WebRTC.Live.Player` can be used.

* Run `mix setup` to install and setup dependencies
* Start Phoenix endpoint with `mix phx.server` or inside IEx with `iex -S mix phx.server`
It contains a simple demo, where:
- the video stream is get from the browser and sent via WebRTC to Elixir server using `Membrane.WebRTC.Live.Capture`
- then, this same video stream is re-sent again to the browser and displayed using `Membrane.WebRTC.Live.Player`.

Now you can visit [`localhost:4000`](http://localhost:4000) from your browser.
This demo uses also [Boombox](https://hex.pm/packages/boombox).

The most important file in the project is `example_project/lib/example_project_web/live_views/echo.ex`, that
contains the usage of `Boombox` and LiveViews defined in `membrane_webrtc_live`.

You can also take a look at `example_project/assets/js/app.js` to see how you can use `membrane_webrtc_live` JS hooks.

Ready to run in production? Please [check our deployment guides](https://hexdocs.pm/phoenix/deployment.html).
## Run server

## Learn more
To start Phoenix server:

* Official website: https://www.phoenixframework.org/
* Guides: https://hexdocs.pm/phoenix/overview.html
* Docs: https://hexdocs.pm/phoenix
* Forum: https://elixirforum.com/c/phoenix-forum
* Source: https://github.com/phoenixframework/phoenix
* Run `mix setup` to install and setup dependencies
* Start Phoenix endpoint with `mix phx.server` or inside IEx with `iex -S mix phx.server`

Now you can visit [`localhost:4000`](http://localhost:4000) from your browser.
26 changes: 8 additions & 18 deletions example_project/assets/vendor/topbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
var lastTime = 0;
var vendors = ["ms", "moz", "webkit", "o"];
for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame =
window[vendors[x] + "RequestAnimationFrame"];
window.requestAnimationFrame = window[vendors[x] + "RequestAnimationFrame"];
window.cancelAnimationFrame =
window[vendors[x] + "CancelAnimationFrame"] ||
window[vendors[x] + "CancelRequestAnimationFrame"];
Expand Down Expand Up @@ -68,15 +67,11 @@
ctx.shadowColor = options.shadowColor;

var lineGradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
for (var stop in options.barColors)
lineGradient.addColorStop(stop, options.barColors[stop]);
for (var stop in options.barColors) lineGradient.addColorStop(stop, options.barColors[stop]);
ctx.lineWidth = options.barThickness;
ctx.beginPath();
ctx.moveTo(0, options.barThickness / 2);
ctx.lineTo(
Math.ceil(currentProgress * canvas.width),
options.barThickness / 2
);
ctx.lineTo(Math.ceil(currentProgress * canvas.width), options.barThickness / 2);
ctx.strokeStyle = lineGradient;
ctx.stroke();
},
Expand All @@ -93,15 +88,14 @@
},
topbar = {
config: function (opts) {
for (var key in opts)
if (options.hasOwnProperty(key)) options[key] = opts[key];
for (var key in opts) if (options.hasOwnProperty(key)) options[key] = opts[key];
},
show: function (delay) {
if (showing) return;
if (delay) {
if (delayTimerId) return;
delayTimerId = setTimeout(() => topbar.show(), delay);
} else {
} else {
showing = true;
if (fadeTimerId !== null) window.cancelAnimationFrame(fadeTimerId);
if (!canvas) createCanvas();
Expand All @@ -111,9 +105,7 @@
if (options.autoRun) {
(function loop() {
progressTimerId = window.requestAnimationFrame(loop);
topbar.progress(
"+" + 0.05 * Math.pow(1 - Math.sqrt(currentProgress), 2)
);
topbar.progress("+" + 0.05 * Math.pow(1 - Math.sqrt(currentProgress), 2));
})();
}
}
Expand All @@ -122,9 +114,7 @@
if (typeof to === "undefined") return currentProgress;
if (typeof to === "string") {
to =
(to.indexOf("+") >= 0 || to.indexOf("-") >= 0
? currentProgress
: 0) + parseFloat(to);
(to.indexOf("+") >= 0 || to.indexOf("-") >= 0 ? currentProgress : 0) + parseFloat(to);
}
currentProgress = to > 1 ? 1 : to;
repaint();
Expand Down Expand Up @@ -162,4 +152,4 @@
} else {
this.topbar = topbar;
}
}.call(this, window, document));
}).call(this, window, document);
3 changes: 2 additions & 1 deletion example_project/config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ config :esbuild,
# Configures Elixir's Logger
config :logger, :console,
format: "$time $metadata[$level] $message\n",
metadata: [:request_id]
metadata: [:request_id],
level: :info

# Use Jason for JSON parsing in Phoenix
config :phoenix, :json_library, Jason
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule ExampleProjectWeb.LiveViews.Echo do
defmodule ExampleProjectWeb.Live.EchoLive do
use ExampleProjectWeb, :live_view
alias Membrane.WebRTC.Live.{Capture, Player}

Expand All @@ -8,7 +8,7 @@ defmodule ExampleProjectWeb.LiveViews.Echo do
ingress_signaling = Membrane.WebRTC.Signaling.new()
egress_signaling = Membrane.WebRTC.Signaling.new()

{:ok, _boombox_pid} =
{:ok, _task_pid} =
Task.start_link(fn ->
Boombox.run(
input: {:webrtc, ingress_signaling},
Expand Down Expand Up @@ -36,8 +36,11 @@ defmodule ExampleProjectWeb.LiveViews.Echo do

def render(assigns) do
~H"""
<Capture.live_render socket={@socket} capture={"mediaCapture"} />
<Player.live_render socket={@socket} player={"videoPlayer"} />
<h3>Captured stream preview</h3>
<Capture.live_render socket={@socket} capture="mediaCapture" />

<h3>Stream sent by the server</h3>
<Player.live_render socket={@socket} player="videoPlayer" />
"""
end
end
2 changes: 1 addition & 1 deletion example_project/lib/example_project_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ defmodule ExampleProjectWeb.Router do
scope "/", ExampleProjectWeb do
pipe_through(:browser)

live("/", LiveViews.Echo, :index)
live("/", Live.EchoLive, :index)
end

# Other scopes may use custom stacks.
Expand Down
Loading