Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
88 changes: 88 additions & 0 deletions .github/workflows/__CD__broadcaster.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
name: Broadcaster CD

on:
push:
tags:
- "broadcaster-v*.*.*"

permissions:
contents: read
packages: write

jobs:
build-publish-broadcaster-image:
name: "Build and publish Broadcaster image"
uses: ./.github/workflows/__CD__build-publish-image.yml
with:
app-name: broadcaster
deploy-broadcaster:
name: "Deploy Broadcaster image"
needs: build-publish-broadcaster-image
runs-on: ubuntu-latest
steps:
- name: Run docker via remote SSH
uses: appleboy/[email protected]
with:
host: ${{ secrets.BROADCASTER_SSH_HOST }}
username: ${{ secrets.BROADCASTER_SSH_USERNAME }}
key: ${{ secrets.BROADCASTER_SSH_PRIV_KEY }}
script: |
# Exit if any command fails.
set -e

export APP_NAME=broadcaster
export TAG=${{ github.ref_name }}
export TAG=${TAG#*-v}

echo "Cleaning previous broadcaster docker image"
docker stop $APP_NAME
docker rm $APP_NAME

echo "Running a new broadcaster image - $TAG"
docker run -d --restart unless-stopped \
--name $APP_NAME \
-e SECRET_KEY_BASE=${{ secrets.BROADCASTER_SECRET_KEY_BASE }} \
-e PHX_HOST=${{ secrets.BROADCASTER_PHX_HOST }} \
-e ICE_PORT_RANGE=${{ secrets.BROADCASTER_ICE_PORT_RANGE }} \
-e ADMIN_USERNAME=${{ secrets.BROADCASTER_ADMIN_USERNAME }} \
-e ADMIN_PASSWORD=${{ secrets.BROADCASTER_ADMIN_PASSWORD }} \
-e WHIP_TOKEN=${{ secrets.BROADCASTER_WHIP_TOKEN }} \
--network host \
ghcr.io/elixir-webrtc/apps/$APP_NAME:$TAG

docker image prune --all --force

echo "Waiting for broadcaster to be ready."
attempts=10
until curl localhost:4000 > /dev/null 2>&1
do
((attempts--))
if [ $attempts -eq 0 ]; then
exit 1
fi
sleep 1
done

echo "Cloning client script"
rm -rf /tmp/apps
git clone -b ${{ github.ref_name }} https://github.com/${{ github.repository }} /tmp/apps
cd /tmp/apps/broadcaster

echo "Terminating previously running client"
# ignore non-zero exit status
killall node || true

# This is needed to find `node` and `npm` commands.
# See difference between interactive and non-interactive shells.
source ~/.nvm/nvm.sh

echo "Installing puppeteer in current directory"
npm install puppeteer

# Run node in bg, disconnect it from terminal and redirect all output.
# In other case action won't end.
echo "Running client script"
USERNAME=${{ secrets.BROADCASTER_ADMIN_USERNAME }} \
PASSWORD=${{ secrets.BROADCASTER_ADMIN_PASSWORD }} \
TOKEN=${{ secrets.BROADCASTER_WHIP_TOKEN }} \
nohup node headless_client.js > nohup.out 2> nohup.err < /dev/null &
2 changes: 1 addition & 1 deletion broadcaster/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Now you can visit [`localhost:4000`](http://localhost:4000) from your browser. Y

You can also run Broadcaster using Docker.

Build an image:
Build an image (or use `ghcr.io/elixir-webrtc/apps/broadcaster:latest`):

```
docker build -t broadcaster .
Expand Down
15 changes: 15 additions & 0 deletions broadcaster/config/runtime.exs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,25 @@ import Config
#
# Alternatively, you can use `mix phx.gen.release` to generate a `bin/server`
# script that automatically sets the env var above.
read_ice_port_range! = fn ->
case System.get_env("ICE_PORT_RANGE") do
nil ->
[0]

raw_port_range ->
case String.split(raw_port_range, "-", parts: 2) do
[from, to] -> String.to_integer(from)..String.to_integer(to)
_other -> raise "ICE_PORT_RANGE has to be in form of FROM-TO, passed: #{raw_port_range}"
end
end
end

if System.get_env("PHX_SERVER") do
config :broadcaster, BroadcasterWeb.Endpoint, server: true
end

config :broadcaster, ice_port_range: read_ice_port_range!.()

if config_env() == :prod do
# The secret key base is used to sign/encrypt cookies and other secrets.
# A default value is used in config/dev.exs and config/test.exs but you
Expand Down
46 changes: 46 additions & 0 deletions broadcaster/headless_client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
'use strict';

const puppeteer = require('puppeteer');

(async () => {
const browser = await puppeteer.launch({
// headless: false,
args: [
'--no-sandbox',
'--use-fake-ui-for-media-stream',
'--use-fake-device-for-media-stream'
]
});

try {
const username = (process.env.USERNAME === undefined) ? 'admin' : process.env.USERNAME;
const password = (process.env.PASSWORD === undefined) ? 'admin' : process.env.PASSWORD;
const url = (process.env.URL === undefined) ? 'http://localhost:4000' : process.env.URL;
const token = (process.env.TOKEN === undefined) ? 'example' : process.env.TOKEN;

const page = await browser.newPage();
await page.setViewport({width: 1280, height: 720});
await page.authenticate({username: username, password: password});
await page.goto(`${url}/admin/player`);

// When button is available and initialized,
// we can safely start streaming.
await page.waitForSelector('button');
await page.waitForFunction(() => {
const button = document.getElementById('button');
console.log(button);
return button.onclick !== null;
});

await page.evaluate((url, token) => {
document.getElementById('serverUrl').value = `${url}/api/whip`;
document.getElementById('serverToken').value = token;
}, url, token);

await page.evaluate(() => {
document.getElementById('button').click();
});
} catch {
await browser.close();
}
})();
3 changes: 2 additions & 1 deletion broadcaster/lib/broadcaster/peer_supervisor.ex
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,9 @@ defmodule Broadcaster.PeerSupervisor do
end

defp spawn_peer_connection(id) do
ice_port_range = Application.fetch_env!(:broadcaster, :ice_port_range)
gen_server_opts = [name: {:via, Registry, {Broadcaster.PeerRegistry, id}}]
pc_opts = Keyword.put(@opts, :controlling_process, self())
pc_opts = @opts ++ [controlling_process: self(), ice_port_range: ice_port_range]

child_spec = %{
id: PeerConnection,
Expand Down
8 changes: 4 additions & 4 deletions broadcaster/mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"bandit": {:hex, :bandit, "1.5.5", "df28f1c41f745401fe9e85a6882033f5f3442ab6d30c8a2948554062a4ab56e0", [:mix], [{:hpax, "~> 0.2.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "f21579a29ea4bc08440343b2b5f16f7cddf2fea5725d31b72cf973ec729079e1"},
"bunch": {:hex, :bunch, "1.6.1", "5393d827a64d5f846092703441ea50e65bc09f37fd8e320878f13e63d410aec7", [:mix], [], "hexpm", "286cc3add551628b30605efbe2fca4e38cc1bea89bcd0a1a7226920b3364fe4a"},
"bunch_native": {:hex, :bunch_native, "0.5.0", "8ac1536789a597599c10b652e0b526d8833348c19e4739a0759a2bedfd924e63", [:mix], [{:bundlex, "~> 1.0", [hex: :bundlex, repo: "hexpm", optional: false]}], "hexpm", "24190c760e32b23b36edeb2dc4852515c7c5b3b8675b1a864e0715bdd1c8f80d"},
"bundlex": {:hex, :bundlex, "1.5.1", "a85890a9d0a70366afa538c8589a4ba75e1319d32a771e1f5f3b7566beea9c26", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:elixir_uuid, "~> 1.2", [hex: :elixir_uuid, repo: "hexpm", optional: false]}, {:qex, "~> 0.5", [hex: :qex, repo: "hexpm", optional: false]}, {:req, "~> 0.4.0", [hex: :req, repo: "hexpm", optional: false]}, {:zarex, "~> 1.0", [hex: :zarex, repo: "hexpm", optional: false]}], "hexpm", "aae447d63230fe1f3b788c429ac02bc696f30163d0f23f52fcfe6ed38372c7ea"},
"bundlex": {:hex, :bundlex, "1.5.3", "35d01e5bc0679510dd9a327936ffb518f63f47175c26a35e708cc29eaec0890b", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:elixir_uuid, "~> 1.2", [hex: :elixir_uuid, repo: "hexpm", optional: false]}, {:qex, "~> 0.5", [hex: :qex, repo: "hexpm", optional: false]}, {:req, ">= 0.4.0", [hex: :req, repo: "hexpm", optional: false]}, {:zarex, "~> 1.0", [hex: :zarex, repo: "hexpm", optional: false]}], "hexpm", "debd0eac151b404f6216fc60222761dff049bf26f7d24d066c365317650cd118"},
"bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"},
"castore": {:hex, :castore, "1.0.8", "dedcf20ea746694647f883590b82d9e96014057aff1d44d03ec90f36a5c0dc6e", [:mix], [], "hexpm", "0b2b66d2ee742cb1d9cb8c8be3b43c3a70ee8651f37b75a8b982e036752983f1"},
"crc": {:hex, :crc, "0.10.5", "ee12a7c056ac498ef2ea985ecdc9fa53c1bfb4e53a484d9f17ff94803707dfd8", [:mix, :rebar3], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "3e673b6495a9525c5c641585af1accba59a1eb33de697bedf341e247012c2c7f"},
Expand All @@ -21,8 +21,8 @@
"ex_sdp": {:hex, :ex_sdp, "0.17.0", "4c50e7814f01f149c0ccf258fba8428f8567dffecf1c416ec3f6aaaac607a161", [:mix], [{:bunch, "~> 1.3", [hex: :bunch, repo: "hexpm", optional: false]}, {:elixir_uuid, "~> 1.2", [hex: :elixir_uuid, repo: "hexpm", optional: false]}], "hexpm", "c7fe0625902be2a835b5fe6834a189f7db7639d2625c8e9d8b3564e6d704145f"},
"ex_stun": {:hex, :ex_stun, "0.2.0", "feb1fc7db0356406655b2a617805e6c712b93308c8ea2bf0ba1197b1f0866deb", [:mix], [], "hexpm", "1e01ba8290082ccbf37acaa5190d1f69b51edd6de2026a8d6d51368b29d115d0"},
"ex_turn": {:hex, :ex_turn, "0.1.0", "177405aadf3d754567d0d37cf881a83f9cacf8f45314d188633b04c4a9e7c1ec", [:mix], [{:ex_stun, "~> 0.2.0", [hex: :ex_stun, repo: "hexpm", optional: false]}], "hexpm", "d677737fb7d45274d5dac19fe3c26b9038b6effbc0a6b3e7417bccc76b6d1cd3"},
"ex_webrtc": {:git, "https://github.com/elixir-webrtc/ex_webrtc.git", "0eb774cd8be919ea3e361f376c8a0cc8104ff79f", []},
"ex_webrtc_dashboard": {:git, "https://github.com/elixir-webrtc/ex_webrtc_dashboard.git", "9498f12014dc68416a5bd5083b2f2eba277478c8", []},
"ex_webrtc": {:git, "https://github.com/elixir-webrtc/ex_webrtc.git", "ef355c055574f498afd448783d7fd510da7b4d20", []},
"ex_webrtc_dashboard": {:git, "https://github.com/elixir-webrtc/ex_webrtc_dashboard.git", "40b67a6399dab5eebaa0434edad74fbc747187bd", []},
"file_system": {:hex, :file_system, "1.0.0", "b689cc7dcee665f774de94b5a832e578bd7963c8e637ef940cd44327db7de2cd", [:mix], [], "hexpm", "6752092d66aec5a10e662aefeed8ddb9531d79db0bc145bb8c40325ca1d8536d"},
"finch": {:hex, :finch, "0.18.0", "944ac7d34d0bd2ac8998f79f7a811b21d87d911e77a786bc5810adb75632ada4", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "69f5045b042e531e53edc2574f15e25e735b522c37e2ddb766e15b979e03aa65"},
"floki": {:hex, :floki, "0.36.2", "a7da0193538c93f937714a6704369711998a51a6164a222d710ebd54020aa7a3", [:mix], [], "hexpm", "a8766c0bc92f074e5cb36c4f9961982eda84c5d2b8e979ca67f5c268ec8ed580"},
Expand All @@ -45,7 +45,7 @@
"plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"},
"plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"},
"qex": {:hex, :qex, "0.5.1", "0d82c0f008551d24fffb99d97f8299afcb8ea9cf99582b770bd004ed5af63fd6", [:mix], [], "hexpm", "935a39fdaf2445834b95951456559e9dc2063d0a055742c558a99987b38d6bab"},
"req": {:hex, :req, "0.4.14", "103de133a076a31044e5458e0f850d5681eef23dfabf3ea34af63212e3b902e2", [:mix], [{:aws_signature, "~> 0.3.2", [hex: :aws_signature, repo: "hexpm", optional: true]}, {:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:nimble_ownership, "~> 0.2.0 or ~> 0.3.0", [hex: :nimble_ownership, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "2ddd3d33f9ab714ced8d3c15fd03db40c14dbf129003c4a3eb80fac2cc0b1b08"},
"req": {:hex, :req, "0.5.4", "e375e4812adf83ffcf787871d7a124d873e983e3b77466e6608b973582f7f837", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "a17998ffe2ef54f79bfdd782ef9f4cbf987d93851e89444cbc466a6a25eee494"},
"shmex": {:hex, :shmex, "0.5.1", "81dd209093416bf6608e66882cb7e676089307448a1afd4fc906c1f7e5b94cf4", [:mix], [{:bunch_native, "~> 0.5.0", [hex: :bunch_native, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.0", [hex: :bundlex, repo: "hexpm", optional: false]}], "hexpm", "c29f8286891252f64c4e1dac40b217d960f7d58def597c4e606ff8fbe71ceb80"},
"tailwind": {:hex, :tailwind, "0.2.3", "277f08145d407de49650d0a4685dc062174bdd1ae7731c5f1da86163a24dfcdb", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "8e45e7a34a676a7747d04f7913a96c770c85e6be810a1d7f91e713d3a3655b5d"},
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
Expand Down