I just implemented something similar. I have an IP webcam on my network, but I noticed that the built-in viewer uses 30% cpu time on my laptop when I view it in Chrome. (20% on Firefox, about the same on IE using an ActiveX version of the client.) The built-in viewer supports a 'cell phone' mode that sends a stream of jpegs, but in an awful way that uses even more cpu time. I decided to write my own wrapper around the url it uses to get a jpeg of the current camera view.
This uses requestAnimationFrame, and lets me set the max framerate I want. Since I'm just watching my dog Mischa and she sleeps most of the time, I set it to 0.5fps which keeps my cpu usage around 1%.
<div>
<img id="mischacam" />
<br />
<span id="time"/>
</div>
<script type="text/javascript">
var camURL = "....";
var msPerFrame = 2000;
var loading = false;
function update(timestamp) {
if (loading) return;
loading = true;
lastFrameTime = timestamp;
$("#mischacam").attr("src", camURL + "/snapshot.cgi?_=" + Math.random());
$("#time").html(new Date().toString());
}
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function( callback ){
window.setTimeout(callback, 1000 / 60);
};
})();
var lastFrameTime;
function animloop(timestamp){
if (lastFrameTime == null) lastFrameTime = timestamp;
if (timestamp - lastFrameTime > msPerFrame)
update(timestamp);
requestAnimFrame(animloop);
}
$(document).ready(function () {
$("#mischacam").on("load", function () { loading = false; });
animloop(0);
});
</script>
mannix is right; to get the browser to reload the image I have to change the url every time. You'd think in a well-designed webcam API the image would come back with appropriate headers to prevent caching, but I didn't even bother to check. The webcam software is not well-designed.
It's not very clear from the article why this solution is superior to using a x-mixed-replace/multipart stream that contains image/jpeg bodies. If you don't have any audio just stream your jpegs using the x-mixed-replace HTTP response type. All browsers support it (even IE6).
Better quality and framerate with lower bandwidth usage. At peak, the example in the article served 250 clients with smooth 30fps video while using about 120mbit/s.
I agree that this is a huge hack and just serving JPGs would be much easier, but this hack turned out to work pretty well.
Unfortunately iOS broke the functionality somewhere around 5.1; it was still broken in 6 and I haven't checked iOS 7 yet. Animated gifs have the same issue: MobileSafari waits until the connection is closed before rendering anything.
Super cool. I just submitted a pull request to jsmpeg to move some of the RGB conversion stuff to the GPU using WebGL. Reduces CPU usage by 5-10%. https://github.com/phoboslab/jsmpeg/pull/1
It's awkward that in 2013 we have to complexify design to this point :
"Streaming video through WebSocket (thus over http upgrade) through a plain-tcp-to-websocket-proxy on top of...".
It feels over-engineered and like TCP-Sockets are a revolution. I know, we can't easily expose plain-socket because of security but still... What's next? UDP for 2018? Socket-binding for 2022?
Well, traditionally this would be done using something like Flash and RTMP, but Flash is dead on mobile - Apple considered it too CPU and battery hungry and a poor user experience, so they banned it. Hence MPEG decoders implemented in JavaScript.
I think you missed my point. I'm not criticising what phobolabs (who is very talented BTW) has done or what any end-developer is doing.
It's just crazy how the standard is slow to come up with new basic APIs.
I mean, you can make a P2P video streaming application since 1995 using straightforward architecture in a desktop App using less cpu, less middleware and less engineering.
I just tried your instant webcam app, and omg it is so cool. I've been looking for something like that. Very impressive low latency.
It's free too, how are you making money? Thanks for making it! (Now I just need something for streaming video between laptops, between laptop and mobile device. I find it very annoying how FaceTime doesn't let you call yourself from one device to another.)
I was just wondering the same thing. Is there some other reason why he would not use the GPU to do h264 encode/decode? It appears that ffmpeg does support it.
Just released something that streams video like this using MJPEG: https://igorpartola.com/projects/hawkeye/. I thought about using WebSockets but MJPEG seemed to be reasonably well supported by all the browsers I cared about do I chose to use it instead.
I wonder if you could just encode each frame as a gif and send it to the browser as part of an animated gif a la gifsockets (https://github.com/videlalvaro/gifsockets)?
Very cool! I like the simple approach of foregoing all the fancy new tech and doing the simplest possible thing (though the quality/bitrate does suffer)
This uses requestAnimationFrame, and lets me set the max framerate I want. Since I'm just watching my dog Mischa and she sleeps most of the time, I set it to 0.5fps which keeps my cpu usage around 1%.