I currently try to build a webrtc application that uses the RTCRtpTransceiver-Objects of the WebRTC standard. I add video and audio tracks to the connection and then, some time later, I try to remove them.
I do this with the following lines:
// part of a method, that searches the transceiver to stop and assigned it to the 'transceiver' variable
peerconnection.removeTrack(transceiver.sender);
if (transceiver.direction === "sendrecv") transceiver.direction = "recvonly";
else transceiver.direction = "inactive";
I know that this will set the remote track just to muted state and is like replacing the transceivers sender track with null, but Chrome has not implemented direction="stopped" or transceiver.stop() yet, see Issue 980879.
So what to do instead?
The remote peer just sees the current direction of the receiver becoming inactive and the receiver track gets muted.
Ergo, it does not remove the track for the remote peer in my application and muted tracks accumulate over time and even worse for video tracks: they get displayed like normal muted tracks.
I also cannot remove every muted track, since my application is required to allow muted and unmuted tracks (- muted by the user, not muted due to being stopped).
Muting tracks by entirely removing them will lead to another offer-answer exchange and this takes some time. I would prefer to just mute by replacing the track with null (without having to send sdp back and forth), as the WebRTC standard seems to allow and Chrome already implements.
The next option would be correlating the transceivers on both ends and sending a message from the stopping peer to the remote one to make the remote one stop the received track. This may be possible (I believe the transceivers mid should be the same, according to the spec), but in my opinion it is also an ugly way.
What i cannot do is just sending over the media track id, since this one is different for the stopping peer and the remote peer, so I cannot just send a message like 'please stop your track with id xyz' (it would make things easy, but well, it just doesn't work like this).
So, now I have the following questions:
What is the current 'standard' way in which you and other webrtc developers solve this, as long stopping transceivers will not work in every browser? (chrome fixing it for current versions will probably take some time but being the most used browser, we cannot just ignore it)
Did someone somehow (by abusing DTFM, using magic or whatever...) bodged a polyfill together? (I believe Adapter.js hasn't made this somehow possible)
Is there another way besides muting=removing and sending remote-track-stop messages over the signaler? If not, what is the better option?
What I ended up doing is choosing the signaling-solution.
I basically do
// part of a method, that searches the transceiver to stop and assigned it to the 'transceiver' variable
peerconnection.removeTrack(transceiver.sender);
if (transceiver.direction === "sendrecv") transceiver.direction = "recvonly";
else transceiver.direction = "inactive";
signaler.send({type: 'transceiver:stop', data: transceiver.mid});
And on the other side
// received sent message and called this method with message.data
onTransceiverStopMessage(mid){
const transceiverToStop = peerconnection.getTransceivers().filter(transceiver => transceiver.mid === mid);
transceiverToStop.receiver.track.stop()
transceiverToStop.receiver.track.dispatchEvent(new Event('ended'));
}
The dispatchEvent-Call is necessary, since calling stop on a track does not trigger the ended-Event.
It works well for my purpose, but I am still waiting for a solution to the piling up inactive transceivers (since they still impact performance, as the chrome issue states)
Related
I have a system where I need to be able to view 4 rtsp feeds with a web browser in and amongst other web content. The feeds are coming from "Amcrest ProHD 1080P PTZ Camera Outdoor, 2MP Outdoor Vandal Dome IP PoE Camera" units. All of the connectivity is wired within the same intranet. I'm viewing the cameras on Insignia Amazon Fire TVs, and I'm not getting the results that I expected.
In order to get it working, I installed streamedian on my Windows machine and got that configured properly. I didn't change much about the default configuration of the proxy server except the port number it was using the serve the feeds on. On the browser side, I included the necessary JavaScript files (again, only changing the port numbers) and made my call to load the players. Currently, that code looks like this:
var playerOptions = {
socket: 'ws://192.168.1.253:8080/ws/',
redirectNativeMediaErrors: true,
bufferDuration: 5,
continuousFileLength: 5000,
eventFileLength: 5000,
errorHandler: function (err) {
console.log(err.message);
},
};
setTimeout(function () {
player1 = Streamedian.player("p1", playerOptions);
player2 = Streamedian.player("p2", playerOptions);
player3 = Streamedian.player("p3", playerOptions);
player4 = Streamedian.player("p4", playerOptions);
}, 100);
Each of the players look like this in the HTML:
<video id="p1" controls autoplay>
<source src="rtsp://path.to.camera" type="application/x-rtsp">
</video>
The players do load, and appear to be attempting to start the stream. However, they quickly start buffering and never come out of it to start showing anything resembling a live feed. Any ideas on what I can do to try to get this running? Am I even heading down a valid path to get where I need to be?
I'm not worried about rewind, or anything in the past. This is purely for live streaming and only needs to show "now". Saving anything more than necessary is not required in order to meet the needs.
I've tried dropping the frame rate to 4fps. It didn't seem to help.
The Windows machine has average power at best. I've opened Task Manager while the streams are running, but nothing appears to be pegged out. Am I just running an under-powered machine for what I'm asking it to do?
Are the browsers in the TV, or the TV itself, just not capable of getting it done and processing that much information? I've tried viewing the pages on my laptop as well (separate from the Windows server, and plenty powerful), but the results do not improve.
Should I be trying something else on my server side? I came across iSpyConnect this evening as I was searching for other (preferably free) options, but I can't tell for sure if it will get me what I need. I've also started looking at signboard applications for the TVs, but they all have a cost associated with them that I'd like to avoid if at all possible.
If anyone has any thoughts, ideas, comments, suggestions or questions about what I have in place, please let me know so that I can try to get something up and running within the facility.
Thanks!
I have a simple setup for Desktop Capturing using html5 libraries.
This includes a simple webpage and a chrome-extension. I am using
Extension to get the sourceId
Using the sourceId I call navigator.mediaDevices.getUserMedia to get the MediaStream
This MediaStream is then fed into an instance of MediaRecorder for recording.
This setup works most of the times, but a few times I see that requestData() on MediaRecorder instance returns blob with empty data consistently. I am clueless as to what can cause a running setup to start misbehaving sometimes.
Some weird behaviour that I noticed in the bad state:
When I try to close/refresh the window it doesn't respond.
The MediaStreamTrack object in Step 2) above is 'live' but as soon as I go to Step 3) it becomes 'muted'.
There's no pattern to it, sometimes it even happens when I request for the MediaStreams the very first time(which rules out the possibility that there could be some dangling resources eating up the contexts)
Is there anything that I am doing wrong and am unaware of? Any help/pointers would be highly appreciated!
I am developing an IIS8 website where users can log in and once logged in watch videos. I want to serve my videos, which may be up to 6 hours long, using HTML5 <video />. I want to limit users to one login only so they can not share their login credentials with others, this will be a pay site. For static pages (non-video) this is easy, but I'm not sure how to do it for video. Once a HTML5 video starts playing how can I prevent the user from loggin in again? Or, if he does log in again, it there a way to interrupt the video playback from the 1st login? I'd love to hear ideas...
thanks
David
While I'm not sure enough about your framework and criteria, have you considered using jQuery and aJax to send requests to your server every X minutes to verify that the session is still active? Here is some sample untested ajax -- just use Javascript's setTimeout function to send every x minutes:
$.ajax({
url: "yourpage.asp",
type: "post",
data: "sessionId=sessionIdVal",
dataType: "json",
success: function(msg){
//Do Logic Here with msg
}
});
And documentation.
Good luck.
elaborating on sgeddes's answer a solution I've used in the past is
- when the user logs in generate a GUID that gets stored both as a cookie for the user and in a lookup table... so if the user logs in again the GUID (and timestamp) will change
- every n seconds have the client poll the server to make sure they still have the right GUID and if not stop the video so only the most recent log-in continues to work
however... there are a couple of issues with this. If the video is a single progressive stream once connected there's nothing to stop the user downloading it and watching it locally, and if they want to get really tricky they could interrupt the polling javascript and simply stop the check.
If you want to go a bit further you can implement a server side handler that checks the validity of the cookie token before delivering more of the video (something similar to http://blog.offbeatmammal.com/post/2006/06/30/Using-ASPNET-to-restrict-access-to-images.aspx) though because the <video> element does it's best to download enough of the video to play without buffering depending on how long it is and how much pre-buffering is done by the time that check kicks in it may be too late.
We are using a Cumulus server as our RTMFP server to implement a voice chat.
The voice streaming with NetStreams works perfectly fine almost no delay here, but we also want to transfer the activity level of the microphone of each member of the NetGroup.
So we tried transferring the data using NetGroup.post(data). That worked well, but had a delay of ~500ms even when testing with multiple clients on the same machine!
Obviously, half a second in microphone activity is just waaay to much delay to display it in any way.
Now we are trying to use direct routing with NetGroup.sendToAllNeighbors(, but it simply does nothing. I have read all the documentation on it and normally a NetGroup status event with "NetGroup.SendTo.Notify" should be triggered on the receiving clients. Instead, nothing happens.
Here is the code, which is called each frame:
var tsObject :TimestampedObject = new TimestampedObject();
tsObject.timestamp = (new Date()).getTime();
tsObject.sender = _netConnection.nearID;
tsObject.object = _mic.activityLevel;
_netGroup.sendToAllNeighbors(tsObject);
I know each frame is a bit much, but for now it is just a test case.
What are we doing wrong? As I said, voice communication itself works fine. As does Netgroup.post(data), which is just way too slow to use for this use case.
We want to create a Windows desktop version of our weather widget
There are 2 special things about the widget.
It consumes a lot of processor time
while active - it displays an
animated picture (Flash without GPU acceleration, unfortunately).
It updates the weather from our
server (frequent server requests from all widget users).
When the user does not look at the widget there is no need for animation and weather loading.
So I have an idea of putting my widget to sleep when it is not visible and hense not used.
Is it possible to detect whether the widget is used or not.
Speaking precisely I need to know whether the widget is covered by other windows?
I mostly interested in Vista/7 gadgets engine, however I also would like to know if this problem is solved in these widget engines
Yahoo widgets
Google desktop
Hope to find some desktop widget guru here.
Pasha
If you InvalidateRect and don't get a subsequent WM_PAINT message, than your window is hidden. You can call UpdateWindow after InvalidateRect to force the WM_PAINT message to happen (or not happen) right away.
So you could do something like this
request server data (and cancel request timer if any)
when data arrives InvalidateRect
when WM_PAINT message arrives, draw the data and set a timer for next request
when timer arrives, goto 1
When you stop getting WM_PAINT messages, you stop re-setting your timer, and you therefor stop requesting updates from the server. When the WM_PAINT message happens (because you are no longer covered). You start requesting data again.