Skip to content

Commit 28deafe

Browse files
committed
[Broadcaster] Add headless client
1 parent 66bf085 commit 28deafe

File tree

2 files changed

+86
-3
lines changed

2 files changed

+86
-3
lines changed

.github/workflows/__CD__broadcaster.yml

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,18 @@ jobs:
2727
username: ${{ secrets.BROADCASTER_SSH_USERNAME }}
2828
key: ${{ secrets.BROADCASTER_SSH_PRIV_KEY }}
2929
script: |
30+
# Exit if any command fails.
31+
set -e
32+
3033
export APP_NAME=broadcaster
3134
export TAG=${{ github.ref_name }}
3235
export TAG=${TAG#*-v}
36+
37+
echo "Cleaning previous broadcaster docker image"
3338
docker stop $APP_NAME
3439
docker rm $APP_NAME
40+
41+
echo "Running a new broadcaster image - $TAG"
3542
docker run -d --restart unless-stopped \
3643
--name $APP_NAME \
3744
-e SECRET_KEY_BASE=${{ secrets.BROADCASTER_SECRET_KEY_BASE }} \
@@ -42,10 +49,40 @@ jobs:
4249
-e WHIP_TOKEN=${{ secrets.BROADCASTER_WHIP_TOKEN }} \
4350
--network host \
4451
ghcr.io/elixir-webrtc/apps/$APP_NAME:$TAG
45-
docker image prune --all --force
46-
47-
4852
53+
docker image prune --all --force
4954
55+
echo "Waiting for broadcaster to be ready."
56+
attempts=10
57+
until curl localhost:4000 > /dev/null 2>&1
58+
do
59+
((attempts--))
60+
if [ $attempts -eq 0 ]; then
61+
exit 1
62+
fi
63+
sleep 1
64+
done
65+
66+
echo "Cloning client script"
67+
rm -rf /tmp/apps
68+
git clone -b ${{ github.ref_name }} https://github.com/${{ github.repository }} /tmp/apps
69+
cd /tmp/apps/broadcaster
5070
71+
echo "Terminating previously running client"
72+
# ignore non-zero exit status
73+
killall node || true
74+
75+
# This is needed to find `node` and `npm` commands.
76+
# See difference between interactive and non-interactive shells.
77+
source ~/.nvm/nvm.sh
78+
79+
echo "Installing puppeteer in current directory"
80+
npm install puppeteer
5181
82+
# Run node in bg, disconnect it from terminal and redirect all output.
83+
# In other case action won't end.
84+
echo "Running client script"
85+
USERNAME=${{ secrets.BROADCASTER_ADMIN_USERNAME }} \
86+
PASSWORD=${{ secrets.BROADCASTER_ADMIN_PASSWORD }} \
87+
TOKEN=${{ secrets.BROADCASTER_WHIP_TOKEN }} \
88+
nohup node headless_client.js > nohup.out 2> nohup.err < /dev/null &

broadcaster/headless_client.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
'use strict';
2+
3+
const puppeteer = require('puppeteer');
4+
5+
(async () => {
6+
const browser = await puppeteer.launch({
7+
// headless: false,
8+
args: [
9+
'--no-sandbox',
10+
'--use-fake-ui-for-media-stream',
11+
'--use-fake-device-for-media-stream'
12+
]
13+
});
14+
15+
try {
16+
const username = (process.env.USERNAME === undefined) ? 'admin' : process.env.USERNAME;
17+
const password = (process.env.PASSWORD === undefined) ? 'admin' : process.env.PASSWORD;
18+
const url = (process.env.URL === undefined) ? 'http://localhost:4000' : process.env.URL;
19+
const token = (process.env.TOKEN === undefined) ? 'example' : process.env.TOKEN;
20+
21+
const page = await browser.newPage();
22+
await page.setViewport({width: 1280, height: 720});
23+
await page.authenticate({username: username, password: password});
24+
await page.goto(`${url}/admin/player`);
25+
26+
// When button is available and is initialized,
27+
// we can safely start streaming.
28+
await page.waitForSelector('button');
29+
await page.waitForFunction(() => {
30+
const button = document.getElementById('button');
31+
console.log(button);
32+
return button.onclick !== null;
33+
});
34+
35+
await page.evaluate((url, token) => {
36+
document.getElementById('serverUrl').value = `${url}/api/whip`;
37+
document.getElementById('serverToken').value = token;
38+
}, url, token);
39+
40+
page.evaluate(() => {
41+
document.getElementById('button').click();
42+
});
43+
} catch {
44+
await browser.close();
45+
}
46+
})();

0 commit comments

Comments
 (0)