// We import the settings.js file to know which address we should contact
// to talk to Janus, and optionally which STUN/TURN servers should be
// used as well. Specifically, that file defines the "server" and
// "iceServers" properties we'll pass when creating the Janus session.
/* global iceServers:readonly, Janus:readonly, server:readonly */
var janus = null;
var recordplay = null;
var opaqueId = "recordplaytest-" + Janus.randomString(12);
var localTracks = {},
localVideos = 0,
remoteTracks = {},
remoteVideos = 0;
var bandwidth = 1024 * 1024;
var myname = null;
var recording = false;
var playing = false;
var recordingId = null;
var selectedRecording = null;
var selectedRecordingInfo = null;
var acodec =
getQueryStringValue("acodec") !== "" ? getQueryStringValue("acodec") : null;
var vcodec =
getQueryStringValue("vcodec") !== "" ? getQueryStringValue("vcodec") : null;
var vprofile =
getQueryStringValue("vprofile") !== ""
? getQueryStringValue("vprofile")
: null;
var doSimulcast =
getQueryStringValue("simulcast") === "yes" ||
getQueryStringValue("simulcast") === "true";
var doOpusred =
getQueryStringValue("opusred") === "yes" ||
getQueryStringValue("opusred") === "true";
var recordData =
getQueryStringValue("data") !== "" ? getQueryStringValue("data") : null;
if (recordData !== "text" && recordData !== "binary") recordData = null;
$(document).ready(function () {
// Initialize the library (all console debuggers enabled)
Janus.init({
debug: "all",
callback: function () {
// Use a button to start the demo
$("#start").one("click", function () {
$(this).attr("disabled", true).unbind("click");
// Make sure the browser supports WebRTC
if (!Janus.isWebrtcSupported()) {
bootbox.alert("No WebRTC support... ");
return;
}
// Create session
janus = new Janus({
server: server,
iceServers: iceServers,
// Should the Janus API require authentication, you can specify either the API secret or user token here too
// token: "mytoken",
// or
// apisecret: "serversecret",
success: function () {
// Attach to Record&Play plugin
janus.attach({
plugin: "janus.plugin.recordplay",
opaqueId: opaqueId,
success: function (pluginHandle) {
$("#details").remove();
recordplay = pluginHandle;
Janus.log(
"Plugin attached! (" +
recordplay.getPlugin() +
", id=" +
recordplay.getId() +
")"
);
// Prepare the name prompt
$("#recordplay").removeClass("hide");
$("#start")
.removeAttr("disabled")
.html("Stop")
.click(function () {
$(this).attr("disabled", true);
janus.destroy();
});
updateRecsList();
},
error: function (error) {
Janus.error(" -- Error attaching plugin...", error);
bootbox.alert(" -- Error attaching plugin... " + error);
},
consentDialog: function (on) {
Janus.debug(
"Consent dialog should be " + (on ? "on" : "off") + " now"
);
if (on) {
// Darken screen and show hint
$.blockUI({
message: '
',
baseZ: 3001,
css: {
border: "none",
padding: "15px",
backgroundColor: "transparent",
color: "#aaa",
top: "10px",
left: "100px",
},
});
} else {
// Restore screen
$.unblockUI();
}
},
iceState: function (state) {
Janus.log("ICE state changed to " + state);
},
mediaState: function (medium, on, mid) {
Janus.log(
"Janus " +
(on ? "started" : "stopped") +
" receiving our " +
medium +
" (mid=" +
mid +
")"
);
},
webrtcState: function (on) {
Janus.log(
"Janus says our WebRTC PeerConnection is " +
(on ? "up" : "down") +
" now"
);
$("#videobox").parent().unblock();
},
slowLink: function (uplink, lost, mid) {
Janus.warn(
"Janus reports problems " +
(uplink ? "sending" : "receiving") +
" packets on mid " +
mid +
" (" +
lost +
" lost packets)"
);
},
onmessage: function (msg, jsep) {
Janus.debug(" ::: Got a message :::", msg);
let result = msg["result"];
if (result) {
if (result["status"]) {
let event = result["status"];
if (event === "preparing" || event === "refreshing") {
Janus.log("Preparing the recording playout");
recordplay.createAnswer({
jsep: jsep,
// We only specify data channels here, as this way in
// case they were offered we'll enable them. Since we
// don't mention audio or video tracks, we autoaccept them
// as recvonly (since we won't capture anything ourselves)
tracks: [{ type: "data" }],
success: function (jsep) {
Janus.debug("Got SDP!", jsep);
let body = { request: "start" };
recordplay.send({ message: body, jsep: jsep });
},
error: function (error) {
Janus.error("WebRTC error:", error);
bootbox.alert("WebRTC error... " + error.message);
},
});
if (result["warning"]) bootbox.alert(result["warning"]);
} else if (event === "recording") {
// Got an ANSWER to our recording OFFER
if (jsep) recordplay.handleRemoteJsep({ jsep: jsep });
let id = result["id"];
if (id) {
Janus.log("The ID of the current recording is " + id);
recordingId = id;
}
} else if (event === "playing") {
Janus.log("Playout has started!");
} else if (event === "stopped") {
Janus.log("Session has stopped!");
let id = result["id"];
if (recordingId) {
if (recordingId !== id) {
Janus.warn("Not a stop to our recording?");
return;
}
bootbox.alert(
"Recording completed! Check the list of recordings to replay it."
);
}
if (selectedRecording) {
if (selectedRecording !== id) {
Janus.warn("Not a stop to our playout?");
return;
}
}
// FIXME Reset status
$("#videobox").empty();
$("#video").addClass("invisible");
recordingId = null;
recording = false;
playing = false;
recordplay.hangup();
$("#record").removeAttr("disabled").click(startRecording);
$("#play").removeAttr("disabled").click(startPlayout);
$("#list").removeAttr("disabled").click(updateRecsList);
$("#recset").removeAttr("disabled");
$("#recslist").removeAttr("disabled");
updateRecsList();
}
}
} else {
// FIXME Error?
let error = msg["error"];
bootbox.alert(error);
// FIXME Reset status
$("#videobox").empty();
$("#video").addClass("invisible");
recording = false;
playing = false;
recordplay.hangup();
$("#record").removeAttr("disabled").click(startRecording);
$("#play").removeAttr("disabled").click(startPlayout);
$("#list").removeAttr("disabled").click(updateRecsList);
$("#recset").removeAttr("disabled");
$("#recslist").removeAttr("disabled");
updateRecsList();
}
},
onlocaltrack: function (track, on) {
if (playing === true) return;
Janus.debug(
"Local track " + (on ? "added" : "removed") + ":",
track
);
// We use the track ID as name of the element, but it may contain invalid characters
let trackId = track.id.replace(/[{}]/g, "");
if (!on) {
// Track removed, get rid of the stream and the rendering
let stream = localTracks[trackId];
if (stream) {
try {
let tracks = stream.getTracks();
for (let i in tracks) {
let mst = tracks[i];
if (mst) mst.stop();
}
// eslint-disable-next-line no-unused-vars
} catch (e) {}
}
if (track.kind === "video") {
$("#thevideo" + trackId).remove();
localVideos--;
if (localVideos === 0) {
// No video, at least for now: show a placeholder
if ($("#videobox .no-video-container").length === 0) {
$("#videobox").append(
'
' +
'' +
'No webcam available' +
"
"
);
}
}
}
delete localTracks[trackId];
return;
}
// If we're here, a new track was added
let stream = localTracks[trackId];
if (stream) {
// We've been here already
return;
}
$("#videotitle").html("Recording...");
$("#stop").unbind("click").click(stopRecPlay);
$("#video").removeClass("invisible");
if (track.kind === "audio") {
// We ignore local audio tracks, they'd generate echo anyway
if (localVideos === 0) {
// No video, at least for now: show a placeholder
if ($("#videobox .no-video-container").length === 0) {
$("#videobox").append(
'
' +
'' +
'No webcam available' +
"
"
);
}
}
} else {
// New video track: create a stream out of it
localVideos++;
$("#videobox .no-video-container").remove();
let stream = new MediaStream([track]);
localTracks[trackId] = stream;
Janus.log("Created local stream:", stream);
$("#videobox").append(
''
);
Janus.attachMediaStream(
$("#thevideo" + trackId).get(0),
stream
);
}
if (
recordplay.webrtcStuff.pc.iceConnectionState !==
"completed" &&
recordplay.webrtcStuff.pc.iceConnectionState !== "connected"
) {
$("#videobox")
.parent()
.block({
message: "Publishing...",
css: {
border: "none",
backgroundColor: "transparent",
color: "white",
},
});
}
},
onremotetrack: function (track, mid, on, metadata) {
if (playing === false) return;
Janus.debug(
"Remote track (mid=" +
mid +
") " +
(on ? "added" : "removed") +
(metadata ? " (" + metadata.reason + ") " : "") +
":",
track
);
if (!on) {
// Track removed, get rid of the stream and the rendering
$("#thevideo" + mid).remove();
if (track.kind === "video") {
remoteVideos--;
if (remoteVideos === 0) {
// No video, at least for now: show a placeholder
if ($("#videobox .no-video-container").length === 0) {
$("#videobox").append(
'
' +
'' +
'No remote video available' +
"
"
);
}
}
}
delete remoteTracks[mid];
return;
}
if ($("#thevideo" + mid).length > 0) return;
// If we're here, a new track was added
if (
$("#videobox audio").length === 0 &&
$("#videobox video").length === 0
) {
$("#videotitle").html(selectedRecordingInfo);
$("#stop").unbind("click").click(stopRecPlay);
$("#video").removeClass("invisible");
}
if (track.kind === "audio") {
// New audio track: create a stream out of it, and use a hidden