...
WCS allows configuring the camera and the microphone from a browser. Let's see how this can be done and what parameters you can adjust when an audio and video stream is captured. We use the Media Devices web application as an example:
Microphone settings
1. Selecting the microphone from the list
code:
Code Block | ||||
---|---|---|---|---|
| ||||
Flashphoner.getMediaDevices(null, true).then(function (list) { list.audio.forEach(function (device) { var audio = document.getElementById("audioInput"); var i; var deviceInList = false; for (i = 0; i < audio.options.length; i++) { if (audio.options[i].value == device.id) { deviceInList = true; break; } } if (!deviceInList) { var option = document.createElement("option"); option.text = device.label || device.id; option.value = device.id; audio.appendChild(option); } }); ... }).catch(function (error) { $("#notifyFlash").text("Failed to get media devices"); }); |
...
2. Adjusting microphone gain (works in Chrome only)
code:
Code Block | ||||
---|---|---|---|---|
| ||||
$("#micGainControl").slider({ range: "min", min: 0, max: 100, value: currentGainValue, step: 10, animate: true, slide: function (event, ui) { currentGainValue = ui.value; if(previewStream) { publishStream.setMicrophoneGain(currentGainValue); } } }); |
3. Enabling error correction (for the Opus codec only)
code:
Code Block | ||||
---|---|---|---|---|
| ||||
if (constraints.audio) { constraints.audio = { deviceId: $('#audioInput').val() }; if ($("#fec").is(':checked')) constraints.audio.fec = $("#fec").is(':checked'); ... } |
4. Setting stereo/mono mode.
code:
Code Block | ||||
---|---|---|---|---|
| ||||
if (constraints.audio) { constraints.audio = { deviceId: $('#audioInput').val() }; ... if ($("#sendStereoAudio").is(':checked')) constraints.audio.stereo = $("#sendStereoAudio").is(':checked'); ... } |
5. Setting audio bitrate in kbps
code:
Code Block | ||||
---|---|---|---|---|
| ||||
if (constraints.audio) { constraints.audio = { deviceId: $('#audioInput').val() }; ... if (parseInt($('#sendAudioBitrate').val()) > 0) constraints.audio.bitrate = parseInt($('#sendAudioBitrate').val()); } |
6. Turning off the microphone (mute).
code:
Code Block | ||||
---|---|---|---|---|
| ||||
if ($("#muteAudioToggle").is(":checked")) { muteAudio(); } |
Camera settings
1. Camera selection
code:
Code Block | ||||
---|---|---|---|---|
| ||||
Flashphoner.getMediaDevices(null, true).then(function (list) { ... list.video.forEach(function (device) { ... }); }).catch(function (error) { $("#notifyFlash").text("Failed to get media devices"); }); |
2. Switching cameras.
code:
Code Block | ||||
---|---|---|---|---|
| ||||
$("#switchBtn").text("Switch").off('click').click(function () { publishStream.switchCam(); }).prop('disabled', $('#sendCanvasStream').is(':checked')); |
...
3. Specifying the resolution of the video
code:
Code Block | ||||
---|---|---|---|---|
| ||||
function resizeLocalVideo(event) { var requested = constraints.video; if (requested.width != event.target.videoWidth || requested.height != event.target.videoHeight) { console.warn("Camera does not support requested resolution, actual resolution is " + event.target.videoWidth + "x" + event.target.videoHeight); } $("#publishResolution").text(event.target.videoWidth + "x" + event.target.videoHeight); resizeVideo(event.target); } |
4. Setting FPS
code:
Code Block | ||||
---|---|---|---|---|
| ||||
if (constraints.video) { if (constraints.customStream) { ... } else { ... if (parseInt($('#fps').val()) > 0) constraints.video.frameRate = parseInt($('#fps').val()); } } |
5.Setting video bitrate in kbps
code:
Code Block | ||||
---|---|---|---|---|
| ||||
if (constraints.video) { if (constraints.customStream) { ... } else { ... if (parseInt($('#sendVideoMinBitrate').val()) > 0) constraints.video.minBitrate = parseInt($('#sendVideoMinBitrate').val()); if (parseInt($('#sendVideoMaxBitrate').val()) > 0) constraints.video.maxBitrate = parseInt($('#sendVideoMaxBitrate').val()); ... } } |
6. Setting CPU Overuse Detection
code:
Code Block | ||||
---|---|---|---|---|
| ||||
if (!$("#cpuOveruseDetection").is(':checked')) { mediaConnectionConstraints = { "mandatory": { googCpuOveruseDetection: false } } } |
7. Turning off the camera (mute)
code:
Code Block | ||||
---|---|---|---|---|
| ||||
if ($("#muteVideoToggle").is(":checked")) { muteVideo(); } |
...
Local camera and microphone test is intended to check capturing in browser without publishing stream to server.
Code Block | ||||
---|---|---|---|---|
| ||||
function startTest() { if (Browser.isSafariWebRTC()) { Flashphoner.playFirstVideo(localVideo, true); Flashphoner.playFirstVideo(remoteVideo, false); } Flashphoner.getMediaAccess(getConstraints(), localVideo).then(function (disp) { $("#testBtn").text("Release").off('click').click(function () { $(this).prop('disabled', true); stopTest(); }).prop('disabled', false); window.AudioContext = window.AudioContext || window.webkitAudioContext; if (Flashphoner.getMediaProviders()[0] == "WebRTC" && window.AudioContext) { for (i = 0; i < localVideo.children.length; i++) { if (localVideo.children[i] && localVideo.children[i].id.indexOf("-LOCAL_CACHED_VIDEO") != -1) { var stream = localVideo.children[i].srcObject; audioContextForTest = new AudioContext(); var microphone = audioContextForTest.createMediaStreamSource(stream); var javascriptNode = audioContextForTest.createScriptProcessor(1024, 1, 1); microphone.connect(javascriptNode); javascriptNode.connect(audioContextForTest.destination); javascriptNode.onaudioprocess = function (event) { ... } } } } else if (Flashphoner.getMediaProviders()[0] == "Flash") { micLevelInterval = setInterval(function () { $("#micLevel").text(disp.children[0].getMicrophoneLevel()); }, 500); } testStarted = true; }).catch(function (error) { $("#testBtn").prop('disabled', false); testStarted = false; }); drawSquare(); } |
SDP parameters replacing
When publishing stream, there is a possibility to replace SDP parameters. In 'SDP replace' field string template is set for search for the parameter to replace, and in 'with' field new parameter value is set.
To replace SDP parameters, a callback function is used that should be set on stream creation in sdpHook option of createStream() method:
stream creation code
Code Block | ||||
---|---|---|---|---|
| ||||
previewStream = session.createStream({
name: streamName,
display: remoteVideo,
constraints: constraints,
sdpHook: rewriteSdp
...
}) |
rewriteSdp function code
Code Block | ||||
---|---|---|---|---|
| ||||
function rewriteSdp(sdp) {
var sdpStringFind = $("#sdpStringFind").val();
var sdpStringReplace = $("#sdpStringReplace").val();
if (sdpStringFind != 0 && sdpStringReplace != 0) {
var newSDP = sdp.sdpString.toString();
newSDP = newSDP.replace(sdpStringFind, sdpStringReplace);
return newSDP;
}
return sdp.sdpString;
} |
Rising up the bitrate of video stream published in Chrome browser
SDP parameters replacement allows to rise video streeam published bitrate. To do this, SDP parameter 'a' must be replaced by this template:
Code Block | ||||
---|---|---|---|---|
| ||||
a=fmtp:(.*) (.*) |
to
Code Block | ||||
---|---|---|---|---|
| ||||
a=fmtp:$1 $2;x-google-min-bitrate=2500 |
where 2500 is the bitrate in kilobytes per second.
Similarly, video bitrate on start can be set (x-google-start-bitrate attribute) and maximum bitrate can be limited (x-google-max-bitrate attribute)
Note that this feature is available in Chrome browser only.
Setting up codecs
When publishing the stream, there is a possibility to eliminate from WebRTC SDP codecs that should not be used to publish the given stream, for example:
...