-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
181 lines (154 loc) · 7.17 KB
/
index.html
File metadata and controls
181 lines (154 loc) · 7.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
video {
width: 640px;
height: 360px;
}
</style>
<script src="https://cdn.dashjs.org/v4.7.2/dash.all.min.js"></script>
<script>
// Reference to DashJS player
var player = null;
// Get this UUID from your camera detail page, or camera list API
const CAMERA_UUID = "NEED_CAMERA_UUID"
// FILL THESE OUT --> Your server paths
const BASE_URL = "NEED_YOUR_SERVER_URL"; // ex: https://www.example.com/api
const GET_FEDERATED_TOKEN_PATH = "NEED_YOUR_FEDERATED_TOKEN_PATH"; // proxy requests to Rhombus API: /org/generateFederatedSessionToken
const GET_MEDIA_URIS_PATH = "NEED_YOUR_MEDIA_URI_PATH"; // proxy requests to Rhombus API: /camera/getMediaUris
[CAMERA_UUID, BASE_URL, GET_FEDERATED_TOKEN_PATH, GET_MEDIA_URIS_PATH].forEach(x => {
if(x.startsWith("NEED")) {
throw new Error(`${x}`);
}
})
// Headers for your server
const headers = {
"Content-Type": "application/json",
"x-auth-scheme": "api-token",
accept: "application/json",
}
// Get a federated token from your server (should just be a proxy call)
async function getFederatedSessionToken(durationSec) {
const url = `${BASE_URL}${GET_FEDERATED_TOKEN_PATH}`;
const response = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ durationSec })
});
const data = await response.json();
return data.federatedSessionToken;
}
// Get a list of media uris (similarly, just a proxy call)
async function getMediaUri(cameraUuid, federatedSessionToken) {
const url = `${BASE_URL}${GET_MEDIA_URIS_PATH}`
const response = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ cameraUuid })
});
const data = await response.json();
return data.wanLiveMpdUri
}
// Main function to stream the video
async function streamVideo(cameraUuid) {
// Step 1: Get the federated session token (duration 24 hours for example)
const federatedSessionToken = await getFederatedSessionToken(86400);
// Step 2: Get the media URI for the camera
const mediaUri = await getMediaUri(cameraUuid, federatedSessionToken);
// Step 3: Set up the video player in the DOM
const videoElement = document.querySelector("#videoPlayer");
// Step 4: Create a DashJS Media player
player = dashjs.MediaPlayer().create();
// Step 4: override request modifiers to add two query params: x-auth-scheme, and x-auth-ft
player.extend("RequestModifier", function() {
return {
modifyRequestHeader: function (xhr, {url}) {
return xhr;
},
modifyRequestURL: function (url) {
/* Modify url adding a custom query string parameter */
return url + `?x-auth-scheme=federated-token&x-auth-ft=${federatedSessionToken || "MISSING_FEDERATED_TOKEN"}`;
},
modifyRequest(request) {
return request;
},
}
}, true);
// [OPTIONAL] Step 5 - Settings for DashJS
const settings = {
debug: {
logLevel: 5,
dispatchEvent: true,
},
streaming: {
scheduling: {
// Set to false when live so that paused live feeds will not consume network bandwidth.
// This is especially important for shareMode, but always desired.
scheduleWhilePaused: false,
defaultTimeout: 5000,
},
delay: {
liveDelayFragmentCount: 4,
},
liveCatchup: {
// Maximum drift allowed in seconds before the player tries to catch up
maxDrift: 10, // Example value: Allow up to 10 seconds of drift
// Playback rate control for catch-up mode
playbackRate: {
min: -0.5, // Valid values for min catch up rate are in the range -0.5 to 0 (-50% to 0% playback rate decrease)
max: 1.0, // Valid values for max catch up rate are in the range 0 to 1 (0% to 100% playback rate increase).
},
// Minimum buffer size required to enter catch-up mode
playbackBufferMin: 15, // Example value: Require at least 60 seconds of buffer
// Enable or disable live catch-up mode
enabled: true, // Example value: Enable live catch-up mode
// Mode of catch-up (available modes: "accurate", "fast", "none")
mode: "fast", // Example value: Use accurate catch-up mode
},
gaps: {
jumpGaps: true,
jumpLargeGaps: true,
smallGapLimit: 1.5,
threshold: 0.3,
enableSeekFix: true,
enableStallFix: true,
stallSeek: 0.1,
},
buffer: {
flushBufferAtTrackSwitch: true,
fastSwitchEnabled: true,
initialBufferLevel: NaN,
bufferTimeAtTopQuality: 30,
bufferTimeAtTopQualityLongForm: 60,
longFormContentDurationThreshold: 600,
},
// We don't support multiple qualities yet and this helps
// the player recover properly from running low on buffer
abr: {
autoSwitchBitrate: {
video: false,
audio: false,
},
},
},
};
player.updateSettings(settings);
// Step 6 - Start the video
player.initialize(videoElement, mediaUri, true);
}
// Example functions to hook in externally and play / pause video.
function play() { if (player) player.play(); }
function pause() { if(player) player.pause(); }
// Main Entry: Kick off the video
streamVideo(CAMERA_UUID);
</script>
<title>Camera Stream</title>
</head>
<body>
<h1>Rhombus Camera Stream</h1>
<video id="videoPlayer" muted></video>
</body>
</html>