Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 13 Next »

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:

media_device_manager.html

manager.js

Microphone settings

1. Selecting the microphone from the list


code:

    Flashphoner.getMediaDevices(null, true).then(function (list) {
        list.audio.forEach(function (device) {
            ...
        });
     ...
    }).catch(function (error) {
        $("#notifyFlash").text("Failed to get media devices");
    });

2. Microphone switching while stream is publishing

code:

    $("#switchMicBtn").click(function (){
        publishStream.switchMic();
    }).prop('disabled', !($('#sendAudio').is(':checked')));

3. Adjusting microphone gain (works in Chrome only)

code:

    $("#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);
            }
        }
    });

4. Enabling error correction (for the Opus codec only)

code:

    if (constraints.audio) {
        constraints.audio = {
            deviceId: $('#audioInput').val()
        };
        if ($("#fec").is(':checked'))
            constraints.audio.fec = $("#fec").is(':checked');
        ...
    }

5. Setting stereo/mono mode.

code:

    if (constraints.audio) {
        constraints.audio = {
            deviceId: $('#audioInput').val()
        };
        ...
        if ($("#sendStereoAudio").is(':checked'))
            constraints.audio.stereo = $("#sendStereoAudio").is(':checked');
        ...
    }

6. Setting audio bitrate in kbps

code:

    if (constraints.audio) {
        constraints.audio = {
            deviceId: $('#audioInput').val()
        };
        ...
        if (parseInt($('#sendAudioBitrate').val()) > 0)
            constraints.audio.bitrate = parseInt($('#sendAudioBitrate').val());
    }

7. Turning off the microphone (mute).

code:

        if ($("#muteAudioToggle").is(":checked")) {
            muteAudio();
        }


Camera settings

1. Camera selection

code:

    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 while stream is publishing

code:

    $("#switchBtn").text("Switch").off('click').click(function () {
        publishStream.switchCam();
    }).prop('disabled', $('#sendCanvasStream').is(':checked'));

Switching of the camera can be done "on the fly" during stream broadcasting. Here is how switching works:

  • On PC cameras switch in the order they are defined in the device manager of the operating system.
  • On Android, if Chrome is used, the default is the frontal camera. If Firefox is used, the default is the rear camera.
  • On iOS in the Safari browser, by default the frontal camera is selected, but in the drop-down the rear camera is the first.

3. Specifying the resolution of the video

code:

            constraints.video = {
                deviceId: $('#videoInput').val(),
                width: parseInt($('#sendWidth').val()),
                height: parseInt($('#sendHeight').val())
            };
            if (Browser.isSafariWebRTC() && Browser.isiOS() && Flashphoner.getMediaProviders()[0] === "WebRTC") {
                constraints.video.deviceId = {exact: $('#videoInput').val()};
                constraints.video.width = {min: parseInt($('#sendWidth').val()), max: 640};
                constraints.video.height = {min: parseInt($('#sendHeight').val()), max: 480};
            }

4. Setting FPS

code:

   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:

   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:

    if (!$("#cpuOveruseDetection").is(':checked')) {
        mediaConnectionConstraints = {
            "mandatory": {
                googCpuOveruseDetection: false
            }
        }
    }

7. Turning off the camera (mute)

code:

        if ($("#muteVideoToggle").is(":checked")) {
            muteVideo();
        }

Testing camera and microhpone capturing locally

Local camera and microphone test is intended to check capturing in browser without publishing stream to server.


code:

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

        previewStream = session.createStream({
            name: streamName,
            display: remoteVideo,
            constraints: constraints,
            sdpHook: rewriteSdp
            ...
        })

rewriteSdp function code

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:

a=fmtp:(.*) (.*)

to

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:

    publishStream = session.createStream({
        ...
        stripCodecs: ["h264", "flv", "mpv"]
    }).on(STREAM_STATUS.PUBLISHING, function (publishStream) {
        ...
    });
    publishStream.publish();


Such a capability is handy when you need to find some workaround for bugs of a browser or if it conflicts with the given codec. For example, if H.264 does not work in a browser, you can turn it off and switch to VP8 when working via WebRTC.

Sound device selection in Chrome browser

Sound output device can be selected (and switched "on the fly") while stream is playing in Chrome browser.

code:

    Flashphoner.getMediaDevices(null, true, MEDIA_DEVICE_KIND.OUTPUT).then(function (list) {
        list.audio.forEach(function (device) {
            ...
        });
    }).catch(function (error) {
        $('#audioOutputForm').remove();
    });

WebRTC statistics displaying

A client application can get WebRTC statistics according to the standard while publishing or playing stream. The statistics can be displayed in browser, for example:

Note that in Safari browser audio only statistics can be displayed.

1. Statistics displaying while stream is published

stream.getStats() code:

    publishStream.getStats(function (stats) {
        if (stats && stats.outboundStream) {
            if(stats.outboundStream.videoStats) {
                $('#outVideoStatBytesSent').text(stats.outboundStream.videoStats.bytesSent);
                $('#outVideoStatPacketsSent').text(stats.outboundStream.videoStats.packetsSent);
                $('#outVideoStatFramesEncoded').text(stats.outboundStream.videoStats.framesEncoded);
            } else {
                ...
            }

            if(stats.outboundStream.audioStats) {
                $('#outAudioStatBytesSent').text(stats.outboundStream.audioStats.bytesSent);
                $('#outAudioStatPacketsSent').text(stats.outboundStream.audioStats.packetsSent);
            } else {
                ...
            }
        }
    });

2. Statistics displaying while stream is played

stream.getStats() code:

    previewStream.getStats(function (stats) {
        if (stats && stats.inboundStream) {
            if(stats.inboundStream.videoStats) {
                $('#inVideoStatBytesReceived').text(stats.inboundStream.videoStats.bytesReceived);
                $('#inVideoStatPacketsReceived').text(stats.inboundStream.videoStats.packetsReceived);
                $('#inVideoStatFramesDecoded').text(stats.inboundStream.videoStats.framesDecoded);
            } else {
                ...
            }

            if(stats.inboundStream.audioStats) {
                $('#inAudioStatBytesReceived').text(stats.inboundStream.audioStats.bytesReceived);
                $('#inAudioStatPacketsReceived').text(stats.inboundStream.audioStats.packetsReceived);
            } else {
                ...
            }
        }
    });

Known issues

1. Microphone swithing does not work in Safari browser.

Symptoms: microphone does not switch using switchMic() WCS WebSDK method.

Solution: use another browser, because Safari always uses sound input microphone, that is chosen in system sound menu (hold down the option (alt) button and click on the sound icon in the menu bar). When microphone is chosen in sound menu, Mac reboot is required.

If Logitech USB camers microphone does not work (when it is chosen in sound menu), format / sample rate changing in Audio MIDI Setup and rebooting can help.

  • No labels