How to find the current Microphone MediaStream and apply constraints - WEBRTC - webrtc

I want to edit the Microphone signal used by BigBlueButton conference and disable the Automatic Gain Control and Echo Cancelling.
However, I don't have information about the MediaStream instance used in the conference page. So, first issue is whether it is possible to find such active stream on the page? to later apply constraints to it. There is this question that says it is not possible to find active streams. But time has past and maybe options have changed. Plus, there might some other ways to get to this stream object.
Other than that, maybe there is a possibility to change the browsers' own flags for these AGC or AEC from a JS script or extension? (and not from the browser itself)
In a more specific detail of this issue: inside the BBB distribution I have looked for the js files ( sip.js and bbb_webrtc_bridge_sip.js) that use the getUserMedia method and I have edited them to give it the desired constraints, but to no avail. If someone knows about this specific platform I would like to ask for your help.
Note: In the mentioned page, there is an audio object that proves a srcObject which resolves to a MediaStream, I can access this and apply limited actions to it, but only in the echo test. Once past this test and inside the actual conference, access to this audio object has no effect.

Solution turned out to not access the MediaStream from a new JS script or extension but, in as in the specifics of the issue: from inside BigBlueButton JS files:
sip.js and bbb_wertc_bridge_sip.js files mentioned above belonged to the flash client, now out of use favouring the html5 client, so the right file to edit was:
/usr/share/meteor/bundle/programs/web.browser/app/compatibility/sip.js
and so what I did was to look for the instances of constraints or where the media stream is created, and inserted custom constraints and forced them in:
line 11941->. mediaHint = Object.keys(mediaHint || {}).length ? mediaHint : this.mediaHint;
replaced with-> mediaHint = this.mediaHint to force the entry into the following condition that creates a new stream with my own constraints in:
line 11956->
var constraints = mediaHint.constraints ||
(this.mediaHint && this.mediaHint.constraints) ||
{audio: true, video: true};
inserted my own constraints:
var constraints = {
audio: {
autoGainControl: false,
echoCancellation: false,
noiseSuppression: false,
},
video:false
};
This works and now these constraints disable AGC, AEC and NS.

Related

Cannot set URL after the fact on Ti.Media.createSound()

I can successfully play a remote mp3 via the Titanium.Media.Sound object, but there is a problem. The 1st clip always plays fine. But each time I try to play a different clip, the first clip plays again. This is 100% repeatable.
So at the top of my js file I'm doing this:
var soundPlayer = Ti.Media.createSound({allowBackground: false});
Then inside the event listener for a button click, I'm setting the URL thusly:
soundPlayer.setUrl(mp3URL);
And I have even tried this approach:
soundPlayer.url = mp3URL;
But they both have the same flaw: the audio is always still the first clip, never any clip I set afterward. I have verified via console logging that in fact a new url was handed to the sound player, and in fact the new url points at a valid mp3. It seems that once I set a url for the sound player, it is set in stone and cannot be changed--just replayed.
So then I tried a completely different approach. Inside my button click listener, I re-create the Sound object each time and hand in the new URL:
soundPlayer = Ti.Media.createSound({allowBackground: false, url: mp3URL});
This actually DOES work and plays the new url each time, BUT it has a terrible side effect: any attached event listeners no longer fire. I need to track state changes in the player, for example when it completes, etc. But these event listeners no longer fire when I take this approach.
Strangely, the AudioPlayer object behaves correctly in all respects, allows me to set new URLs, etc. BUT the problem with that is that AudioPlayer absolutely refuses to play any mp3 file smaller than 40Kb. I have posted questions around that issue on this and other forums, and based on responses and experimentation, I have lots of evidence for the 40Kb limitation, and no evidence to the contrary.
So why can't I change the url after object creation on the Sound object? Thanks in advance for any ideas.
I'd put this in the "Known bug" category, see here: https://jira.appcelerator.org/browse/TIMOB-3348 marked as "won't fix".
Bug report:
var sound = Titanium.Media.createSound();
sound.url='../cricket.wav'; sound.play();
But if I try to change the url after that, sound plays still the cricket.wav
sound.
Response from Appcelerator(?):
"Duplicate of customer issue TIMOB-1488. This can be easily achieved
by creating a new sound object. Furthermore, this would create a
platform parity issue and would complicate any future API that, for
example, would support sound channels, etc. A sound object should be
considered an immutable object once it's constructed."
So create a new sound object and re-add the event listeners is the solution I think:
var sampleListener = function(){
alert('something happened');
}
var sound = Ti.Media.createSound({url:myURL});
sound.addEventListener('complete', sampleListener);
sound.play();
//later on, make a new sound object:
sound = Ti.Media.createSound({url:anotherURL});
sound.addEventListener('complete', sampleListener);
sound.addEventListener('someevent', anotherSampleListener);
sound.play();
Just so know, this is happening to the Ti.Media.AudioPlayer also. The proposed solution will work just fine in that case as well.

Custom Grid App

So I am trying to make modifications to the custom grid app that rally has already created. I found the source code at https://github.com/RallyApps/app-catalog/tree/master/src/apps/grid. However, I cannot get that code to work. I have added it to a js and then ran build (I also changed the json). However, when I then add the app to rally it doesn't give me the settings options (object, query, pagesize, etc) and just generates a table. This table generates 4 rows (the number of user stories I have), but the rows are completely blank except for gears at the beginning of each row. I was wondering if I was building this app incorrectly or if I had grabbed the wrong code. If not, is there a place where can I get the complete code or a way to modify the already existing code?
Thanks
You may add a fetch to the config as below:
config: {
defaultSettings: {
types: 'hierarchicalrequirement',
fetch: 'FormattedID,Name'
}
}
and it will display a grid.
It will not display settings dialog however. The source code in this github repo is not exactly the CustomGrid app available from the AppCatalog in the UI. It does not have the full functionality and not ready yet. I submitted a defect.

Suppress messages from embedded Windows Media PLayer

I'm working on a Windows Form Application in which I have embedded a Windows Media Player that lets you play video files. The unique thing is that I have changed the extension of the media files (for reasons which I can't get into here). For instance, "xyz.wmv" might be called "xyz.ext". They play just fine, but before they play, I get the message:
"The file you are attempting to play has an extension that does not match the file format. Playing the file may result in unexpected behaviour. Do you want the Player to try to play the file?"
You can click yes and you can even check the box to not show that message again, but I don't want that for all the obvious reasons including the fact that it confuses users. I have looked into the .settings properties but I cannot find a way to suppress this message and more importantly other messages that might come up.
The .ext (for example) extension is not known to media player, hence the warning.
What you can do to change this is modify the registry and register this extension. This is described officially here: File Name Extension Registry Settings
The most simple way to do it is to create a registry key like this:
HKEY_CURRENT_USER\Software\Microsoft\MediaPlayer\Player\Extensions\.ext
And add two key values:
Runtime (DWORD): 6
Permissions (DWORD): 15 (or 0xF in hexa)
This is shown here:
NOTE: this answer was originally in response to a bounty question and edit which was removed on how to do this via code. Parts of this are still relevant to the original question.
You can do this pretty straight forward IF you have admin rights as you need to edit the registry. Not sure how far you will get without admin rights and can test later, but here is how to do this via code (in a real implementation I would do this as part of a setup - or check if the keys exist each time which seems wasteful):
You need to add one key (showing two here for registering the extensions, you may need additional keys for auto-play or a setting on the player):
private void Form1_Load(object sender, EventArgs e) {
/*This first key is not necessary - and if you will be using common
* extensions like mp4, skip this step altogether!!
*/
RegistryKey key = Registry.CurrentUser.OpenSubKey("Software", true)
.OpenSubKey("Classes", true);
key.CreateSubKey(".myExt");
key = key.OpenSubKey(".myExt", true);
key.SetValue("", "WMP11.AssocFile.myExt");
key.SetValue("Content Type", "video/x-ms-wmv");
key.SetValue("PerceivedType", "video");
/*Here is the magic key which will make the dialog go away*/
key = Registry.CurrentUser.OpenSubKey("Software", true)
.OpenSubKey("Microsoft", true)
.OpenSubKey("MediaPlayer", true)
.OpenSubKey("Player", true)
.OpenSubKey("Extensions", true);
key.CreateSubKey(".myExt");
key = key.OpenSubKey(".myExt", true);
key.SetValue("", "");
key.SetValue("Permissions", 0x20);
axWindowsMediaPlayer1.URL = #"C:\Users\Public\Documents\Wildlife.myExt";
}
Media Player creates other keys when you add through its dialog, but the only one definitely needed is: HKEY_Current_User.Software.Microsoft.MediaPlayer.Player.Extensions
If you want to see all the keys Media Player adds,
choose a crazy extension,
click always allow when prompted and then
search the registry for all the keys that get created.
The above code is tested and working for me - confirming the dialog before adding the keys and the lack of any dialog after.
This is a good generic process for programmatically adding file associations and default programs to the Windows Registry from .NET. You have to be careful about registering the extension (the first key I set above) IF the extension already exists (TEST FOR THIS). Otherwise the above code will happily overwrite your current values. All you really should need is the one added to: HKEY_Current_User.Software.Microsoft.MediaPlayer.Player.Extensions anyway. Think it through, check in advance, and test before you go crazy in the registry!!
It is also always a great idea to backup your registry before playing with it.
Final note: missed your question on how to reproduce once you have clicked always allow: just remove the entry in HKEY_Current_User.Software.Microsoft.MediaPlayer.Player.Extensions and voila!
This answer assumes you have a working knowledge of regedit.
Final note #2: Response geared to the questions in the Bounty. Other errors can be suppressed by setting telling Media Player to allow you to handle error events and then writing your custom handler. I have not done this before so cannot comment on the ease and what can/cannot be controlled through this method.
The Windows Media Player control does not raise an exception when it encounters an error such as an invalid URL. Instead, it signals an event. Your application should handle error events sent by the Player.
These can then be handled by creating / registering a MediaError event:
private void axWindowsMediaPlayer1_MediaError(object sender, AxWMPLib._WMPOCXEvents_MediaErrorEvent e) {
// Handle errors and profit!
}
Then set this as the handler in the Events property window for your control - same for other events such as ErrorEvent.

Kaltura - Force player to stop with API only?

Is there any way to force a Kaltura videoplayer to stop ONLY using code and the Kaltura API?
Currently I have solved it by adding a Access Control Profile named "Free preview" under Settings > Access Control in KMC and then added this profile to the Entries I've choosen.
I then add the session to the players flashvars to restrict non-members to only watch the preview, not the whole clip.
But I would like to restrict ALL, or even better selected Categories of clips by using only code, so I don't need to involve KMC.
Is that possible?
Alt) Can you create a new player in KMC and restrict it to viewing only X seconds, no matter what length of Entry? Then I can do the check if user is valid or not and get the category via API and show it in the "preview-player" och the "default player".
If I use the mediaProxy.mediaPlayTo attribute the clip stops, but is easily started again by presing play.
Would greatly appreciate an answer
I got this answer from a guy named oferc in a different forum:
You can listen to the head move event and pause the clip it goes beyond a certain time (then if someone pressed play, you can stop it again)
function jsCallbackReady(player_id) {
my_kdp = $("#"+player_id).get(0); // document.getElementById(player_id) if you do not use jquery/ prefer pure js
my_kdp.addJsListener("kdpReady", "kdpReady"); // when you load the player with an entry (and the player is ready to begin playing it using doPlay for instance)
}
function kdpReady() {
my_kdp.addJsListener("playerUpdatePlayhead","headMove");
}
function headMove(position) {
if (position > "30") { // Your Time, example 30 seconds
my_kdp.sendNotification('doStop')
}
}
Works like a charm!
fredrik_w - neither of the ways you chosen here are a good option to restrict access.
in both cases, your videos are made public, and can be easily accessible by anyone.
The best way to limit access to a video is by defining an Access Control, and like everything in Kaltura, you can define an ACL using API as well.
Check this out as a reference sample-
http://blog.kaltura.org/turning-profit-online-video-made-easy-using-paypal-html5-digital-goods

Reliably getting favicons in Chrome extensions, chrome://favicon?

I'm using the chrome://favicon/ in my Google Chrome extension to get the favicon for RSS feeds. What I do is get the base path of linked page, and append it to chrome://favicon/http://<domainpath>.
It's working really unreliably. A lot of the time it's reporting the standard "no-favicon"-icon, even when the page really has a favicon. There is almost 0 documentation regarding the chrome://favicon mechanism, so it's difficult to understand how it actually works. Is it just a cache of links that have been visited? Is it possible to detect if there was an icon or not?
From some simple testing it's just a cache of favicons for pages you have visited. So if I subscribe to dribbble.com's RSS feed, it won't show a favicon in my extension. Then if I visit chrome://favicon/http://dribbble.com/ it won't return right icon. Then I open dribbble.com in another tab, it shows its icon in the tab, then when I reload the chrome://favicon/http://dribbble.com/-tab, it will return the correct favicon. Then I open my extensions popup and it still shows the standard icon. But if I then restart Chrome it will get the correct icon everywhere.
Now that's just from some basic research, and doesn't get me any closer to a solution. So my question is: Is the chrome://favicon/ a correct use-case for what I'm doing. Is there any documentation for it? And what is this its intended behavior?
I've seen this problem as well and it's really obnoxious.
From what I can tell, Chrome populates the chrome://favicon/ cache after you visit a URL (omitting the #hash part of the URL if any). It appears to usually populate this cache sometime after a page is completely loaded. If you try to access chrome://favicon/http://yoururl.com before the associated page is completely loaded you will often get back the default 'globe icon'. Subsequently refreshing the page you're displaying the icon(s) on will then fix them.
So, if you can, possibly just refreshing the page you're displaying the icons on just prior to displaying it to the user may serve as a fix.
In my use case, I am actually opening tabs which I want to obtain the favicons from. So far the most reliable approach I have found to obtain them looks roughly like this:
chrome.webNavigation.onCompleted.addListener(onCompleted);
function onCompleted(details)
{
if (details.frameId > 0)
{
// we don't care about activity occurring within a subframe of a tab
return;
}
chrome.tabs.get(details.tabId, function(tab) {
var url = tab.url ? tab.url.replace(/#.*$/, '') : ''; // drop #hash
var favicon;
var delay;
if (tab.favIconUrl && tab.favIconUrl != ''
&& tab.favIconUrl.indexOf('chrome://favicon/') == -1) {
// favicon appears to be a normal url
favicon = tab.favIconUrl;
delay = 0;
}
else {
// couldn't obtain favicon as a normal url, try chrome://favicon/url
favicon = 'chrome://favicon/' + url;
delay = 100; // larger values will probably be more reliable
}
setTimeout(function() {
/// set favicon wherever it needs to be set here
console.log('delay', delay, 'tabId', tab.id, 'favicon', favicon);
}, delay);
});
}
This approach returns the correct favicon about 95% of the time for new URLs, using delay=100. Increasing the delay if you can accept it will increase the reliability (I'm using 1500ms for my use case and it misses <1% of the time on new URLs; this reliability worsens when many tabs are being opened simultaneously). Obviously this is a pretty imprecise way of making it work but it is the best method I've figured out so far.
Another possible approach is to instead pull favicons from http://www.google.com/s2/favicons?domain=somedomain.com. I don't like this approach very much as it requires accessing the external network, relies on a service that has no guarantee of being up, and is itself somewhat unreliable; I have seen it inconsistently return the "globe" icon for a www.domain.com URL yet return the proper icon for just domain.com.
Hope this helps in some way.
As of Oct 2020, it appears chrome extensions using manifest version 3 are no longer able to access chrome://favicon/* urls. I haven't found the 'dedicated API' the message refers to.
Manifest v3 and higher extensions will not have access to the
chrome://favicon host; instead, we'll provide a dedicated API
permission and different URL. This results in being able to
tighten our permissions around the chrome:-scheme.
In order to use chrome://favicon/some-site in extension. manifest.json need to be updated:
"permissions": ["chrome://favicon/"],
"content_security_policy": "img-src chrome://favicon;"
Test on Version 63.0.3239.132 (Official Build) (64-bit)
chrome://favicon url is deprecated in favor of new favicon API with manifest v3.
// manifest.json
{
"permissions": ["favicon"]
}
// utils.js
function getFaviconUrl(url) {
return `chrome-extension://${chrome.runtime.id}/_favicon/?pageUrl=${encodeURIComponent(url)}&size=32`;
}
Source: https://groups.google.com/a/chromium.org/g/chromium-extensions/c/qS1rVpQVl8o/m/qmg1M13wBAAJ
I inspected the website-icon in Chrome history page and found this simpler method.
You can get the favicon url by --
favIconURL = "chrome://favicon/size/16#1x/" + tab.url;
Don't forget to add "permissions" and "content_security_policy" to Chrome. (https://stackoverflow.com/a/48304708/9586876)
In the latest version of Chrome, Version 78.0.3904.87 (Official Build) (64-bit)) when tested, adding just img-src chrome://favicon; as content_security_policy will still show 2 warnings:
'content_security_policy': CSP directive 'script-src' must be specified (either explicitly, or implicitly via 'default-src') and must whitelist only secure resources.
And:
'content_security_policy': CSP directive 'object-src' must be specified (either explicitly, or implicitly via 'default-src') and must whitelist only secure resources.
To get rid of them use:
"permissions": ["chrome://favicon/"],
"content_security_policy": "script-src 'self'; object-src 'self'; img-src chrome://favicon;"
Now you can use chrome://favicon/http://example.com without getting any errors or warnings.