Acting as a proxy for multipart/x-mixed-replace streaming

531 views
Skip to first unread message

henriz

unread,
Jul 21, 2012, 4:45:55 PM7/21/12
to mojol...@googlegroups.com
Hi everyone,

So far everything has been straightforward with Mojolicious, but now I could need some advice.

I try to 'embed' my IP webcam within a page of my website, which runs on the Mojolicious built-in web server (behind a Nginx reverse proxy).
The IP webcam streams video over http as 'multipart/x-mixed-replace' content, each part being an image/jpeg.
(In the prototype code below, the URL for the webcam is 'http://cam/videostream.cgi?user=guest&pwd=guest').

My web server has to somehow act as a proxy between the browser and the IP webcam, relaying this video stream from the webcam to the browser.

browser <--> web server <--> IP webcam

As a first approach, I built a quick Mojolicous::Lite prototype (cf. code below) based on the Streaming response example in the Mojolicious cookbook:

----------------- Prototype Start  ----------------------------

use Mojolicious::Lite;

get '/' => sub {

  my $self = shift;
  $self->render('index');
} => 'index';

get '/cam' => sub {

    my $self = shift;

    $self->res->code(200);
    $self->res->headers->content_type('multipart/x-mixed-replace;boundary=ipcamera');
    $self->res->headers->accept_ranges('bytes');

    my $tx = $self->ua->build_tx(GET => 'http://cam/videostream.cgi?user=guest&pwd=guest');

    $tx->res->content->unsubscribe('read')->on(read => sub {
        my ($content, $chunk) = @_;
        $self->write($chunk);
    });

    $self->ua->start($tx);
} => 'cam';

app->start;

__DATA__

@@ index.html.ep

<!DOCTYPE html>
<html>
    <head><title>Webcam</title></head>
    <body>
        <iframe width=320 height=240 scrolling=no frameborder=1 src= <%= url_for 'cam' %> >Webcam video stream.</iframe>
    </body>
</html>


----------------- Prototype End  ----------------------------


These are the results I get:

* On the web server, I see the stream coming continuously in from the IP webcam, triggering 'read' events on an ongoing basis.
* But the browser is sitting idle, waiting for data on the iframe related "/cam" request and does not see any of the chunks which the 'read' callback writes back to the browser. 
* It is only after about 30 to 50 secs of waiting that the browser actually receives a couple of images but the stream then stops.

A first reason why this cannot work I guess is that the "$self->ua->start($tx);" actually starts a blocking transaction. To make it unblocking, the documentation says to append a callback, e.g.:
 $ua->start($tx => sub {
   my ($ua, $tx) = @_;
   say $tx->res->body;
 });
The problem is that I have the impression that this only works with a "finite" response (cf. say $tx->res->body;) and not with a streaming response.

That is where I stand for now. Any hint, advice or direction on this would be welcome.

Kind regards,
Henri
Reply all
Reply to author
Forward
0 new messages