Info center for developers wanting to use Skyway and other Temasys Open Source web projects. Thanks to Luke Maciak for getting us started with his Jekyll Sample App.
Development time dependencies:
AdapterJS Javascript Polyfill and Tools for WebRTC - Skylink WebRTC
Home Page: http://skylink.io/web
License: Other
Info center for developers wanting to use Skyway and other Temasys Open Source web projects. Thanks to Luke Maciak for getting us started with his Jekyll Sample App.
Development time dependencies:
iceServers[i].hasCredentials = AdapterJS.
isDefined(iceServers[i].username) &&
AdapterJS.isDefined(iceServers[i].credential);
Why is that hasCredentials
for? is that needed for the plugin to properly connect to TURN servers?
var downloadLink = AdapterJS.WebRTCPlugin.pluginInfo.downloadLink;
if(downloadLink) {
var popupString;
if (AdapterJS.WebRTCPlugin.pluginInfo.downloadLink) {
// IE will only start the plugin if it's ACTUALLY visible
if (isIE) {
AdapterJS.WebRTCPlugin.plugin.width = '1px';
AdapterJS.WebRTCPlugin.plugin.height = '1px';
}
AdapterJS.WebRTCPlugin.plugin.width = '1px';
AdapterJS.WebRTCPlugin.plugin.height = '1px';
width and height are set anyhow.
What do you think about it? It would be great to allow localization of installation/GUM popups via separate javascript language files/plugin initialization settings. I could help with making a Russian language pack. Natively implemented GUM popups in Chrome/Firefox are, of course, localized :)
If I want to implement theAdapterJS.WebRTCPlugin.pluginNeededButNotInstalledCb
callback the source code says that it needs to be overridden but what I don't want to do is to end up using a custom AdapterJS version. Also it would be nice to be able to pass options. For example like this:
window.AdapterJS = {
options: {
hidePluginInstallPrompt: true
},
WebRTCPlugin: {
pluginNeededButNotInstalledCb: function() {
//Do something when the plugin is not installed
}
}
};
Hi,
I have a question related to modifying objects which plugin return. For now I'm trying to delete some properties in peer connection object (which is instance of plugin) in IE and received following error:
Object doesn't support this action
Seems to be a problem because plugin return [IFBComJavascript object]. Also JSON.stringify(), if I pass to it this object, throw stack overflow error.
Do I have any possibility to manage this object like native javascript object?
Thanks in advance.
Hello.
Currently plugin supports renegotiation in general, but I cannot make use of it because of these problems:
Bowser from Ericsson supports webrtc, but it doesn't seem to work with adapter.js. Please update adapter.js to support Bowser.
We had to patch AdapterJS slightly to make it work with EasyRTC, see comment here:
https://github.com/priologic/easyrtc/issues/121#issuecomment-78211330
Basically, AdapterJS' attachMediaSource replaces the video tag with an object tag. Later on, attachMediaSource fails if one passes a newly created object due to missing properties and functions.
Hi there,
we use the Temasys plugin within an iFrame, and have found that in IE11 and Safari 5 PC / 7 OSX the following lines throw an exception:
var rectObject = element.getBoundingClientRect();
element.parentNode.insertBefore(frag, element); //exception thrown
frag = document.getElementById(elementId);
frag.width = rectObject.width + 'px';
frag.height = rectObject.height + 'px';
element.parentNode.removeChild(element); //exception thrown
Commenting them out allows the connection to take place, but the Temasys object gets inserted into the top level page, not into the iframe, and the caller has no local or remote video.
Please let me know if you need more info.
Thanks, and keep up the great work!
Jamie
It is noted that in this fix:
// IE 9 is not offering an implementation of console.log until you open a console
if (typeof console !== 'object' || typeof console.log !== 'function') {
/* jshint -W020 */
console = {} || console;
// Implemented based on console specs from MDN
// You may override these functions
console.log = function (arg) {};
console.info = function (arg) {};
console.error = function (arg) {};
console.dir = function (arg) {};
console.exception = function (arg) {};
console.trace = function (arg) {};
console.warn = function (arg) {};
console.count = function (arg) {};
console.debug = function (arg) {};
console.count = function (arg) {};
console.time = function (arg) {};
console.timeEnd = function (arg) {};
console.group = function (arg) {};
console.groupCollapsed = function (arg) {};
console.groupEnd = function (arg) {};
/* jshint +W020 */
}
This was to prevent the adapterjs from running into errors when console is not opened, but however when the console is opened in IE9 before the page loads, it should appear the logs, which it doesn't.
Even though I register callback for onwebrtcready
and once it's called I try to create peer connection I get such kind of error Exception: TypeError: undefined is not a function (evaluating 'o.WebRTCPlugin.plugin.PeerConnection(o.WebRTCPlugin.pageId,a,i,r)')
.
Browser is Safari 8.
I'd like to pipe the microphone audio data into a Web Audio API chain. In Chrome or Firefox, I would just create a MediaStreamSource with AudioContext.createMediaStreamSource(mediaStream) (see https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/createMediaStreamSource) and pass the mediaStream I get from the onSuccess event from getUserMedia.
Anyhow the AudioContext of Safari does not provide the createMediaStreamSource() method, since it makes no sense without (native) getUserMedia. The method is also not polyfilled by AdapterJS. I wonder if I could instead access the raw audio data from the temasys mediaStream JSAPI-object and write into a BufferSourceNode. Is anyone aware if this is possible?
Or are there even any plans to polyfill the AudioContext.createMediaStreamSource() in Safari. That would be awesome!
IE 9 enters a "quirks mode" whenever a HTML document does not start with
When doing so, attachEvent is defined, and not addEventListener on which the adapter relies to inject the plugin.
How the reproduce:
Expected:
Observed:
following up on this specific part of the code
There is a method named Temasys.WebRTCPlugin.WaitForPluginReady
whose job is to turn JS into IO Blocking by entering in an infinite loop.
Forcibly turning an event driven language into IO Blocking is a failure to realize that this is an async operation.
You are bringing thousands of machines to their knees, wasting million of CPU cycles because you fail to grasp how this is an async operation and how to handle it. The very nature of JS, being a single threaded language, should not even allow Temasys.WebRTCPlugin.isPluginReady
to ever become true, you got away with pure luck here.
Considering you are wildy distributing this code, I strongly suggest you refactor this and all the methods (they are plenty) that invoke it.
Hi.
Haven't found any info about getStats usage. Could you help me, how to correctly call getStats method in peer connection?
Thanks.
The adapter.js file says:
If you need to do something once the page/plugin is ready, override window.onwebrtcready instead.
But the fact is that setting something like window.onwebrtcready = function() { console.warn('onwebrtcready'); }
does nothing.
My colleague has a logitech c920 camera installed on their system, and it is plugged in when starting IE.
He later unplugs the camera, and reloads the page that uses the Temasys plugin, calling gUM.
The Temasys plugin shows the camera that has been unplugged, and trying to access it causes a gUMFailed event.
If the camera is not plugged in it should not be visible in the in the device list.
Using latest plugin version 0.8.826, Safari 7.1, Mac OSX 10.9 Maverics
1.It would be great to have a public documentation like MDN or MSDN, which would describe functionality implemented in your plugin.
2. These methods seem to be not implemented: MediaStream.getTracks(), RTCPeerConnection.removeStream(), at least in Safari 7.1 their type is undefined. Both of them exist in latest W3C Draft and are implemented in Chrome and Firefox.
3. Plugin causes Safari to freeze when closing connection in this order:
May be it is some how related to #23 ?
Calling MediaStream.stop() doesn't free camera lock since usage indicator (LED) is still on.
Expected result:
the plugin runs
Actual result:
The plugin works as long as there is no callback in it.
It can return a value, but not make a JS callback
document.body.appendChild is triggered before body is available.
__TemWebRTCReady0 = function () {
arguments.callee.StaticWasInit = arguments.callee.StaticWasInit || 1;
if (arguments.callee.StaticWasInit === 1) {
AdapterJS.WebRTCPlugin.documentReadyInterval = setInterval(function () {
if (document.readyState === 'complete') {
// TODO: update comments, we wait for the document to be ready
clearInterval(AdapterJS.WebRTCPlugin.documentReadyInterval);
AdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY;
}
}, 100);
}
arguments.callee.StaticWasInit++;
};
Questions:
var
?window
global namespace)? Could it be a local function not exposed in window
?arguments.callee.StaticWasInit === 1
. Otherwise it increments StaticWasInit
and does NOT set READY state. In which case could StaticWasInit
has a value != 1?arguments.callee
in strict mode: link. Could not the same effect be implemented by using a local counter variable or a counter within the AdapterJS.WebRTCPlugin
object?Guys, do you have any events for plugin as onReadyForUpdate or any other update configs? I can't find any info about it.
Thanks!
In order to check how to properly close/stop a MediaStream I check whether the MediaStreamTrack.prototype.stop
exists or not. However the MediaStreamTrack
implementation of the plugin has no prototype
(it is undefined
).
Would it be easy to add it? Otherwise I'll use another approach to check the existence of the stop
method.
Hi guys,
Are you planing to add some functionality to take a snapshots from camera?
Can't draw image in canvas from object that is returned from plugin.
Thanks in advance.
IE 11.0.9600.xxx Windows 7 SP1 x64.
Intalled plugin, restarted IE, tried to make a call, but got "navigator.getUserMedia is undefined". window.getUserMedia is also undefined. "AdapterJS.onwebrtcready" does not fire, no errors in developer console except when trying to access WebRTC methods as described above. Extension details:
Name: Plugin allowing browser without native handling of WebRTC to actually use it Vendor: (Not verified) Temasys Type: ActiveX element Arch: 32-bit Version: 0.8.826 File date: 3 february 2015 , 12:04 Last access date: 1 april 2015, 14:11 Class ID: {38CD4193-5EEE-5B7E-BA60-9AF497EE2C59} Usage count: 7 Blocks count: 0 File: npTemWebRTCPlugin.dll Directory: C:\Users\Дмитрий\AppData\Roaming\Tem\TemWebRTCPlugin\0.8.826
try to find a way that reuse adapter.js as much as possible to ease updates on peerjs side.
I have just uninstalled and re-installed Temasys in my Windows 7 VM using the following link:
http://bit.ly/1w0jWB1
I understand this is the link to your latest version of the plugin, but once installed, it shows v0.8.801.0
Once this version is installed, restarting IE and calling GUM crashes IE.
I do not understand why the old version of your plugin is getting installed from this link? Any ideas?
Here is the log from the crash:
Podpis problému:
Název události problému: APPCRASH
Název aplikace: IEXPLORE.EXE
Verze aplikace: 11.0.9600.17207
Časové razítko aplikace: 53a20c50
Název chybného modulu: npTemWebRTCPlugin.dll
Verze chybného modulu: 0.8.801.0
Časové razítko chybného modulu: 54365535
Kód výjimky: c0000005
Posun výjimky: 0059d786
Verze operačního systému: 6.1.7601.2.1.0.768.3
ID národního prostředí: 1029
Další informace 1: 0a9e
Další informace 2: 0a9e372d3b4ad19135b953a78882e789
Další informace 3: 0a9e
Další informace 4: 0a9e372d3b4ad19135b953a78882e789
Přečtěte si prohlášení o zásadách ochrany osobních údajů online:
http://go.microsoft.com/fwlink/?linkid=104288&clcid=0x0405
Pokud není k dispozici Prohlášení o zásadách ochrany osobních údajů online, přečtěte si toto prohlášení offline:
C:\Windows\system32\cs-CZ\erofflps.txt
Hi there,
another one I'm afraid - it seems consistent after ending a call in Safari OSX Mavricks using your plugin, if I try to reload the page to make another call the page fails to reload. I have to kill safari and open it again to be able to reload the page and make another call.
Please let me know if you need any more details in how to reproduce this issue.
Thanks
Jamie
I have noticed that for IE you are assigning the onplaying event for "newElement" in a way that only supports IE9 and lower.
Can I suggest the following that covers IE10 / 11 too?
newElement.onplaying = (element.onplaying) ? element.onplaying : function (arg) {};
if (isIE) { // on IE the event needs to be plugged manually
if(newElement.addEventListener){
newElement.addEventListener('onplaying', newElement.onplaying);
}else if(newElement.attachEvent){
newElement.attachEvent('onplaying', newElement.onplaying);
}
Cheers!
Jamie
AdapterJS.WebRTCPlugin.callWhenPluginReady = function (callback) {
var checkPluginReadyState = setInterval(function () {
if (AdapterJS.WebRTCPlugin.pluginState === AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY) {
clearInterval(checkPluginReadyState);
callback();
}
}, 100);
};
This means that, even if the plugin state is READY (this is, the DOM is "complete") it will take 100ms for the callback to be called.
If plugin state is READY this function should immediately execute the callback.
You have a polyfill for this method in Firefox and it returns two devices - audio and video. I think it would be better to return an empy list here because:
There are three possible alternatives:
The adapter is currently showing MediaStreamTrack.getSource instead of MediaStreamTrack.getSourceInfos
Keep both for compatibility purposes.
Hi,
I have a use-case when I need to remove streams from peer connection and by calling _pc.removeStream(stream)
where _pc
is RTCPeerConnection leading to undefined is not a function (evaluating '_pc.removeStream(stream)')
.
I checked RTCPeerConnection object and it's prototype and removeStream is defined in prototype but somehow not exposed properly.
Yes, I forgot to mention: I'm running Safari 8.
Is there a workaround for this?
Randomly, but quite frequently, and I think only in the latest version of the Temasys plugin, I have been noticing that in Safari Version 7.1.2 (9537.85.11.5) OSX Mavericks when calling gUM, the camera / mic selection box shows blank, with only the OK option showing (see attached screenshot - I saved the console log also but can not attach it here.
Clicking OK then does not access my camera and mic, and no video or audio.
the AdapterJS object is created but never exported via module.exports
Since version 38 (GA will be released in May) FF supports RTCIceServer.urls property and throws deprecation warning when using RTCIceServer.url. So FF RTCPeerConnection polyfill should be changed to:
RTCPeerConnection = function (pcConfig, pcConstraints) {
if (webrtcDetectedVersion < 38) {
AdapterJS.maybeFixConfiguration(pcConfig);
}
return new mozRTCPeerConnection(pcConfig, pcConstraints);
};
Hey guys,
When I path to the getUserMedia { audio: true, video: false } I still can select video in the popup window. After it I'll be able to get video stream from the stream object in the getUserMedia success callback.
Thanks!
Hi guys,
I try to get a real name of device and have incorrect behaviour.
When I use getUserMedia()
method and call getAudioTracks() / getVideoTracks()
with "stream" here, Temasys plugin returns non-readable string. Something like this: "J+fpdCSBad"
.
I would like to get name like as "Microphone (Logitech USB Headset)"
.
Also this correct information we have after calling GetSources()
method.
I know about this case (some code from adapter.js):
// Fake get{Video,Audio}Tracks
if (!MediaStream.prototype.getVideoTracks) {
MediaStream.prototype.getVideoTracks = function () {
return [];
};
}
if (!MediaStream.prototype.getAudioTracks) {
MediaStream.prototype.getAudioTracks = function () {
return [];
};
}
But could you clarify can I get a real name of device from "stream"?
Or I can not access to there.
Thanks.
Hey one more again.
There were IE crashes when plugin found updates.
There was no issue before new plugin version became available and after plugin update.
Problem signature:
Problem Event Name: APPCRASH
Application Name: IEXPLORE.EXE
Application Version: 11.0.9600.17416
Application Timestamp: 5452eed9
Fault Module Name: npTemWebRTCPlugin.dll
Fault Module Version: 0.8.826.0
Fault Module Timestamp: 54d048cc
Exception Code: c0000005
Exception Offset: 005aa380
OS Version: 6.3.9600.2.0.0.256.4
Locale ID: 1033
Additional Information 1: 5861
Additional Information 2: 5861822e1919d7c014bbb064c64908b2
Additional Information 3: a10f
Additional Information 4: a10ff7d2bb2516fdc753f9c34fc3b069
Read our privacy statement online:
http://go.microsoft.com/fwlink/?linkid=280262
If the online privacy statement is not available, please read our privacy statement offline:
C:\WINDOWS\system32\en-US\erofflps.txt
It is general practice to hide the orignal element with style="display:none", not remove completely. Then you could restore it easily, and all of it's properties (even changed while working with plugin) would be preserved.
Currently, yes, we have such a use case: by default video tag is opaque and user sees a picture behind it. When a call starts - peer's stream it attached to this video element. When a call ends video tag should becomes opaque again (that's why we need to detach media stream from it). And between calls some video files may be played in this video tag. Of course we could just replace video tag with a new one every time, but i think it is a bad approach.
Also, this approach might be helpful in listening to video element events. For example, you hide video element and listen to it's "volumechange" event to enable/disable stream audio tracks. That would solve #34. So generally, user interracts with original video element, and you just proxy it's events to your plugin in some way. Of couse this approach needs investigation and testing, but i find it possible and perspective.
Conserning ID management:
Usually it is done this way: you leave original ID on it's place, and set ID of your inserted content to something like 'ID_plugin'. Then, when user want to manipulate original element some way - he can get it by original ID and does not get any mess. But when he uses attachMediaStream(), for example (calls one of your API methods), this method transparetly converts ID to ID_plugin and takes actions in favor of your inserted content.
General idea here is that you transparently insert some new content and user (developer) even doesn't notice that, when working with original element's or your plugin's public API.
For example, in method "attachMediaStream" it could look like this:
function attachMediaStream(element, stream) {
var object_element = document.getElementById(element.id + '_plugin');
element = object_element;
...
Hey guys! I want to remind you topic about the video resize - https://groups.google.com/forum/#!topic/temasys-discuss-webrtcplugin/_laLEsuaYSo
Is it possible to have some video resize event?
Thanks!
It is often needed to not only attach, but also detach media stream from video/audio element. Detaching code looks almost like attaching one, and logically it might be a good decision to use attachMediaStream() for it like this:
attachMediaStream(element, null)
The only thing that needs to be changed in attachMediaStream() is line "element.src = URL.createObjectURL(stream);" to "element.src = (stream === null ? "" : URL.createObjectURL(stream));", and also disable video.play() in Firefox-specific attachMediaStream() version.
It may also be done via a separate function, but it will be just code duplicate.
When camera is already in use (by another getUserMedia call) and next getUserMedia call prompts device selection dialog and same camera is selected (which works fine for native implementation) both success and failure callbacks are called.
Error callback gets error object containing message that constraints are not fulfilled.
Success callback gets stream object which is valid but contains no audio/video stream tracks (depends on initial constraints).
This behaviour is wrong since only one callback should be called and in this case - error callback.
Thanks.
According to the current spec .urls
should accept an URL string or a sequence of them:
dictionary RTCIceServer {
(DOMString or sequence<DOMString>) urls;
However the plugin completely ignores the urls
entries if it contains an Array. This is:
iceServers: [{
urls: 'turn:turn.example.com:1234?transport=udp',
username: 'foo',
credential: '1234f'
}]
iceServers: [{
urls: ['turn:turn.example.com:1234?transport=udp'],
username: 'foo',
credential: '1234f'
}]
Is this a limitation? or should it already work?
Thanks a lot.
I have the feeling that renderNotificationBar should be namespaced Temasys.AdapterJS instead of Temasys.WebRTCPlugin.
@serrynaimo @letchoo please validate and make the associated changes if needed.
<video autoplay muted='true'></video>
This seems not to work as there is audio (it should be muted). IMHO the following could be the reason:
attachMediaStream = function (element, stream) {
stream.enableSoundTracks(true);
The point is, how to mute or change the volume of the "video" / "object" element? which API is implemented?
It would be great to add a new polyfill to handle differences in createOffer options dict. Firefox already supports (from version 33-34) a new syntax http://www.w3.org/TR/webrtc/#idl-def-RTCOfferOptions (and throws deprecation warning when using "mandatory: {}"). Googgle Chrome still doesn't accept new syntax, I did not yet check the plugin. To fix this I use this helper function. I think it's place is in AdapterJS library :)
/**
* Create options dict for RTCPeerConnection.createOffer()
* @see http://www.w3.org/TR/webrtc/#idl-def-RTCOfferOptions for param description
*
* @param recieveAudio
* @param recieveVideo
* @param iceRestart
* @param voiceDetection
*
* @returns {Object}
*/
function createOfferOptions(recieveAudio, recieveVideo, iceRestart, voiceDetection) {
var options;
iceRestart = iceRestart || false;
voiceDetection = voiceDetection === false ? false : true;
// current spec: http://www.w3.org/TR/webrtc/#idl-def-RTCOfferOptions
if (webrtcDetectedBrowser === 'firefox' && webrtcDetectedVersion >= 36) {
options = {
offerToReceiveAudio: recieveAudio,
offerToReceiveVideo: recieveVideo,
iceRestart: iceRestart,
voiceActivityDetection: voiceDetection
};
}
// old spec: http://www.w3.org/TR/2013/WD-webrtc-20130910/#constraints
else {
options = {mandatory: {
OfferToReceiveAudio: (recieveAudio ? true : false),
OfferToReceiveVideo: (recieveVideo ? true : false),
IceRestart: iceRestart,
VoiceActivityDetection: voiceDetection
}};
}
return options;
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.