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

VCS live streaming example #13

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
26 changes: 17 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

This demo highlights [Daily's prebuilt UI](https://www.daily.co/blog/prebuilt-ui/), and how it can be used to embed a video chat widget in a website or app. The demo also illustrates how to use [daily-js methods](https://docs.daily.co/reference#instance-methods) and [events](https://docs.daily.co/reference#events) to build custom interfaces outside of the callframe that control the call.

Check out a live version of the demo [here](https://prebuilt-ui.netlify.app/).
Check out a live version of the demo [here](https://prebuilt-ui.netlify.app/).

The demo's custom controls use these Daily methods:

Expand All @@ -17,7 +17,8 @@ The demo's custom controls use these Daily methods:
- [`.getNetworkStats()`](https://docs.daily.co/reference#%EF%B8%8F-getnetworkstats)
- [`.setSubscribeToTracksAutomatically()`](https://docs.daily.co/reference#%EF%B8%8F-setsubscribetotracksautomatically)

![Video call takes up the left side of the screen, call controls on the right](./assets/prebuilt-ui-demo.gif)
![homescreen](./assets/homescreen.png)
![call ui](./assets/callui.png)

## Prerequisites

Expand All @@ -34,24 +35,31 @@ Once a room has been created, the participant can click "Join call." This button
1. Install dependencies `npm i`
2. Start dev server `npm run dev`
3. Then open your browser and go to `http://localhost:8080`
4. Add your own room url in index.js and comment/uncomment the code as noted

### To use live streaming:

1. Create a Daily room through the [dashboard](https://dashboard.daily.co) or [REST API](https://docs.daily.co/reference/rest-api/rooms/create-room).
2. Create a [meeting token](https://docs.daily.co/reference/rest-api/meeting-tokens/create-meeting-token) for your new room with the [`is_owner` property](https://docs.daily.co/reference/rest-api/meeting-tokens/config#is_owner) set to `true`.
3. From the home screen, click "Enter my room URL" and use the room URL you create in step 1.
![home screen with existing room URL](./assets/livestreaming.png)
4. Add your token from step 2 in `index.js` where the `.join()` call happens. There's a `todo` comment included to show you where to add it.
![code where token should be added](./assets/token.png)

OR...

## Running using Netlify CLI
## Running using Netlify CLI

If you want access to the Daily REST API (using the proxy as specified in `netlify.toml`) as well as a more robust local dev environment, please do the following (in this project's directory):
If you want access to the Daily REST API (using the proxy as specified in `netlify.toml`) as well as a more robust local dev environment, please do the following (in this project's directory):

1. Deploy to your Netlify account
[![Deploy with Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/daily-demos/prebuilt-ui)
[![Deploy with Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/daily-demos/prebuilt-ui)

2. Install the Netlify CLI `npm i -g netlify-cli`
3. Login to your account `netlify login`
4. Rename `sample.env` to `.env` and add your API key
4. Start the dev server `netlify dev`

> Note: If the API proxy isn't working locally you may need to run `netlify build` first. This will put API key in the `netlify.toml` file, so make sure you don't commit this change.
5. Start the dev server `netlify dev`

> Note: If the API proxy isn't working locally you may need to run `netlify build` first. This will put API key in the `netlify.toml` file, so make sure you don't commit this change.

## Contributing and feedback

Expand Down
Binary file added assets/callui.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/homescreen.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/livestreaming.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/token.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 25 additions & 14 deletions index.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
--dark-blue: #1f2d3d;
--dark-blue-border: #2b3f56;
--green: #72cc18;
--red-dark: #BB0C0C;
--red-dark: #bb0c0c;
--font-family: GraphikRegular, 'Helvetica Neue', Sans-Serif;
}

Expand Down Expand Up @@ -102,7 +102,7 @@ body {
}

.white-button {
color: var(--dark-blue);
color: var(--dark-blue);
display: flex;
flex-direction: row;
align-items: center;
Expand All @@ -111,8 +111,8 @@ body {
padding: 8px 16px;
border-radius: 8px;
flex: none;
font-size: 12px;
line-height: 16px;
font-size: 12px;
line-height: 16px;
font-weight: bold;
cursor: pointer;
}
Expand Down Expand Up @@ -286,7 +286,8 @@ body {
cursor: pointer;
}

.url-input {
.url-input,
.toast-input {
width: 280px;
height: 32px;
padding: 8px 16px;
Expand All @@ -313,21 +314,21 @@ body {
}

.error-message {
display: flex;
flex-direction: column;
align-items: center;
display: flex;
flex-direction: column;
align-items: center;
}

.error-title {
color: var(--red-dark);
font-size: 16px;
line-height: 24px;
margin: 0px;
color: var(--red-dark);
font-size: 16px;
line-height: 24px;
margin: 0px;
}

.error-description {
font-size: 12px;
line-height: 16px;
font-size: 12px;
line-height: 16px;
padding: 0 16px;
text-align: center;
}
Expand Down Expand Up @@ -366,3 +367,13 @@ body {
width: 100%;
}
}

form {
display: flex;
flex-direction: column;
padding-top: 16px;
}

form div {
padding-top: 8px;
}
37 changes: 37 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,43 @@ <h3>Example custom controls</h3>
</button>
</div>
</div>
<div class="controls-custom-example">
<h3>Live streaming controls</h3>
<p>
You can also create your own meeting controls outside of the
callframe using daily-js.
</p>
<div class="custom-buttons">
<button
class="button controls-button white-button"
id="start-livestreaming"
onclick="startLiveStreaming()"
>
Start live streaming
</button>
<button
class="button controls-button white-button"
id="start-livestreaming"
onclick="updateLiveStreaming()"
>
Apply custom VCS settings
</button>
<button
class="button controls-button white-button"
id="stop-livestreaming"
onclick="stopLiveStreaming()"
>
Stop live streaming
</button>
</div>
<form onsubmit="showToast(event)">
<label for="toast">Toast text</label>
<input class="toast-input" type="text" id="toast" />
<div>
<input class="white-button" type="submit" value="Send toast" />
</div>
</form>
</div>
</div>
</div>
</div>
Expand Down
82 changes: 82 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ async function joinCall() {
await callFrame.join({
url: url,
showLeaveButton: true,
//TODO: add an owner token to use live streaming
// token: <token>,
});
} catch (e) {
if (
Expand Down Expand Up @@ -226,6 +228,86 @@ function toggleFullscreen() {
callFrame.requestFullscreen();
}

// To use live streaming, the room URL should use the format:
// https://your-daily-domain.daily.co/room-name?t=your-owner-meeting-token
function startLiveStreaming() {
// This should be in the format rtmp://RTMP_ENDPOINT/STREAM_KEY
// or rtmps://RTMP_ENDPOINT/STREAM_KEY
console.log('starting!!!');

Choose a reason for hiding this comment

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

Do we keep the console.log()s in the demo?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Could go either way but since I'm not planning on merging to main, I think it's fine. In my experience working with this, I tended to keep the console open to see feedback when it's starting, so I personally liked having these printed.

const rtmpUrl = 'rtmp://RTMP_ENDPOINT/STREAM_KEY';
callFrame.startLiveStreaming({
rtmpUrl,
layout: {
preset: 'custom',
composition_params: {
'videoSettings.showParticipantLabels': true,
},
/* optional: sessions assets must be included in startLiveStreaming() even if they aren't used until an updateLiveStreaming() call
session asset images *must* be a .png
*/
session_assets: {
'images/dailyLogo': 'https://docs.daily.co/assets/generic-meta.png',
},
},
});
}

function updateLiveStreaming() {
console.log('updating!!!');
callFrame.updateLiveStreaming({
layout: {
preset: 'custom',
composition_params: {
mode: 'pip',
showImageOverlay: true,
'image.assetName': 'dailyLogo',
'image.aspectRatio': 1,
'image.position': 'bottom-left',
'image.opacity': 0.7,
'image.height_vh': 0.2,
'image.margin_vh': 0.01,
showTextOverlay: true,
'text.align_horizontal': 'right',
'text.align_vertical': 'bottom',
'text.offset_x': -20,
'text.fontFamily': 'PermanentMarker',
'text.content': 'Hello from Daily!',
},
},
});
}

function stopLiveStreaming() {
console.log('stopping!!!');
callFrame.stopLiveStreaming();
}

let toastKey = 0;

function showToast(e) {
// prevent default form behavior
e.preventDefault();
// get input value from form submit event
const toastText = e.target[0].value;

// send
callFrame.updateLiveStreaming({
layout: {
preset: 'custom',
composition_params: {
'toast.text': toastText,
'toast.color': 'rgba(215, 50, 110, 0.8)',
'toast.text.fontFamily': 'Bitter',
'toast.duration_secs': 3,
'toast.text.fontSize_pct': 150,
'toast.text.fontWeight': '400',
'toast.key': toastKey,
},
},
});
toastKey++;
}

function toggleLocalVideo() {
const localVideoButton = document.getElementById('local-video-button');
const currentlyShown = callFrame.showLocalVideo();
Expand Down