Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Re^3: Serving video files in specific byte-ranges

by Corion (Pope)
on Aug 31, 2011 at 14:16 UTC ( #923437=note: print w/ replies, xml ) Need Help??


in reply to Re^2: Serving video files in specific byte-ranges
in thread Serving video files in specific byte-ranges

Have you tried seek together with the appropriate Content-Range headers in your response? What were the problems you encountered?

Also see Simple HTTP in under 100 lines, which supports Range: queries and responses.


Comment on Re^3: Serving video files in specific byte-ranges
Select or Download Code
Replies are listed 'Best First'.
Re^4: Serving video files in specific byte-ranges
by goofball (Acolyte) on Sep 06, 2011 at 19:29 UTC
    That's a helpful link - thanks! Although, that code uses an HTTP::Response object to pass back to the daemon. Any advice on printing out the response object when not using a daemon? The CPAN docs are entirely clear on this (HTTP::Response and HTTP::Message), and when I implement the print $response->decoded_content in the following code, I get an error of Can't decode ref content at /usr/local/lib/perl5/site_perl/5.8.9/HTTP/Message.pm line 294.
    use HTTP::Response; use IO::File; my $response = new HTTP::Response( 404,undef,undef,"404 - Not foun +d." ); $|=1; my $file = new IO::File "< $path"; if (defined $file) { $response->code( 200 ); binmode $file; my $size = -s $file; my ($startrange, $endrange) = (0,$size-1); if (defined $ENV{HTTP_RANGE} and $ENV{HTTP_RANGE} =~ /bytes\s* +=\s*(\d+)-(\d+)?/) { $response->code( 206 ); ($startrange,$endrange) = ($1,$2 || $endrange); }; $file->seek($startrange,0); $response->header(Content_Length => $endrange-$startrange); $response->header(Content_Range => "bytes $startrange-$endrang +e/$size"); $response->content( sub { sysread($file, my ($buf), 16*1024); # No error checking ?? +? return $buf; }); }; print $response->decoded_content;

    Another option I tried, just printing the HTTP headers and content to STDOUT, follows below. This prints the requested ranges using a Transfer-Encoding method of chunked, as described here: w3.org and here: Wiki. There are no server-side errors using this script, but the iPhone Safari client still shows a broken file.

    my @ranges; if($ENV{HTTP_RANGE} =~ s/^bytes=//i) { @ranges = split /,/, $ENV{HTTP_RANGE}; print "Transfer-Encoding: chunked\n"; warn "printing ranges @ranges\n"; } else { print "Content-length: $filesize\n\n"; } if(@ranges) { open my $fh, '<', $path; foreach $range (@ranges) { my($begin, $end) = split /-/, $range; print "Content_Range: bytes $begin-$end/$filesize\ +n\n"; my $whence = ($begin)? 0 : 2; my $position = ($begin)? $begin : 0 - $end; seek $fh, $position, $whence; if($end) { $range = ($begin)? $end - $begin : $end; my $chunk_header = sprintf("%x", $range); print "$chunk_header\r\n"; sysread $fh, $_ , $range; print "$_\r\n"; warn "printed range of $range bytes from $begi +n to $end\n"; } else { while(<$fh>) { print } } } close $fh; print "0\r\n"; } else { open(FILE, $path) or die; while(<FILE>) { print } close(FILE); }

      Looking at the source of HTTP::Message, it just does not want to decode the content delivered by a callback:

      ... $content_ref = $self->content_ref; die "Can't decode ref content" if ref($content_ref) ne "SCALAR"; ...

      Either you fix HTTP::Message or you try it with ->content() instead of ->decoded_content. Alternatively, look at Plack as your server framework - it should handle callback responses more gracefully than your approach.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://923437]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (18)
As of 2015-07-28 19:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (258 votes), past polls