Created
March 9, 2012 08:32
-
-
Save aanoaa/2005657 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package Streaming; | |
# This example application demos simple streaming support in Catalyst | |
# by streaming an mp3 file to a media player. You will need to point the MP3 | |
# variable to an mp3 file. Then access http://localhost:3000/mp3 in your | |
# favorite mp3 player. | |
# | |
# Works with: | |
# HTTP server | |
# CGI | |
# FastCGI | |
# Apache | |
# | |
# Known issues: | |
# When the client disconnects under FastCGI, the process appears to get killed | |
# instead of being allowed to clean up. | |
# | |
use strict; | |
use Catalyst qw/-Debug/; | |
use File::Basename; | |
use MP3::Info; | |
use FindBin; | |
my $bin = $FindBin::Bin; | |
use Path::Class; | |
my $mp3file = Path::Class::File->new($bin)->parent->file('test.mp3'); | |
our $VERSION = '0.01'; | |
# change this | |
our $MP3 = "$mp3file"; | |
Streaming->config( name => 'Streaming' ); | |
Streaming->setup; | |
sub default : Private { | |
my ( $self, $c ) = @_; | |
$c->res->output( 'Access /mp3 to run the demo' ); | |
} | |
sub mp3 : Local { | |
my ( $self, $c ) = @_; | |
my $size = (stat( $MP3 ))[7]; | |
my $basename = basename( $MP3 ); | |
# note that headers are sent automatically as soon as we access the | |
# response handle via $c->res->handle, so we don't have to send them | |
# manually | |
$c->res->content_type( 'audio/mpeg-3' ); | |
$c->res->content_length( $size ); | |
$c->res->header( 'Content-Disposition' => 'filename=' . $basename ); | |
$c->res->header( 'Accept-Ranges' => 'bytes' ); | |
# support seeking in mp3 file | |
my $offset = 0; | |
if ( my $range = $c->req->header( 'Range' ) ) { | |
$range =~ m/bytes=(\d+)-/xms; | |
$offset = $1; | |
warn "Got Range request, seeking to $offset\n"; | |
if ( $offset < $size ) { | |
$c->res->status( 206 ); | |
$c->res->header( 'Content-Ranges' => "bytes $offset-$size/$size" ); | |
} | |
else { | |
$offset = 0; | |
} | |
} | |
open my $fh, '<', $MP3 || die "Unable to open $MP3 for reading"; | |
binmode $fh; | |
if ( seek $fh, $offset, 0 ) { | |
# write chunks at mp3 bitrate + 1K | |
my $info = get_mp3info( $MP3 ); | |
my $bitrate = $info->{BITRATE}; | |
my $bytes = ( ($bitrate / 8) * 1024 ) + 1024; | |
STREAM: | |
while ( read( $fh, my $buffer, $bytes ) ) { | |
warn "Writing " . length($buffer) . " bytes to client\n"; | |
# write until the client drops connection | |
last STREAM unless $c->write( $buffer ); | |
} | |
} | |
warn "Closing file and finishing up\n"; | |
close $fh; | |
} | |
1; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment