App-MHFS
view release on metacpan or search on metacpan
lib/MHFS/Plugin/Youtube.pm view on Meta::CPAN
my $youtubequery = 'q=' . (uri_escape($request->{'qs'}{'q'}) // '') . '&maxResults=' . ($request->{'qs'}{'maxResults'} // '25') . '&part=snippet&key=' . $self->{'settings'}{'Youtube'}{'key'};
$youtubequery .= '&type=video'; # playlists not supported yet
my $tosend = '';
my @curlcmd = ('curl', '-G', '-d', $youtubequery, 'https://www.googleapis.com/youtube/v3/search');
print "$_ " foreach @curlcmd;
print "\n";
state $tprocess;
$tprocess = MHFS::Process->new(\@curlcmd, $evp, {
'SIGCHLD' => sub {
my $stdout = $tprocess->{'fd'}{'stdout'}{'fd'};
my $buf;
while(length($tosend) == 0) {
while(read($stdout, $buf, 24000)) {
say "did read sigchld";
$tosend .= $buf;
}
}
undef $tprocess;
$request->{'qs'}{'fmt'} //= 'html';
if($request->{'qs'}{'fmt'} eq 'json'){
$request->SendBytes('application/json', $tosend);
}
else {
$self->sendAsHTML($request, $tosend);
}
},
});
$request->{'process'} = $tprocess;
return -1;
}
sub downloadAndServe {
my ($self, $request, $video) = @_;
weaken($request);
my $filename = $video->{'out_filepath'};
my $sendit = sub {
# we can send the file
if(! $request) {
return;
}
say "sending!!!!";
$request->SendLocalFile($filename);
};
my $qs = $request->{'qs'};
my @cmd = ($self->{'youtube-dl'}, '--no-part', '--print-traffic', '-f', $self->{'fmts'}{$qs->{"media"} // "video"} // "best", '-o', $video->{"out_filepath"}, '--', $qs->{"id"});
$request->{'process'} = MHFS::Process->new_cmd_process($request->{'client'}{'server'}{'evp'}, \@cmd, {
'on_stdout_data' => sub {
my ($context) = @_;
# determine the size of the file
# relies on receiving content-length header last
my ($cl) = $context->{'stdout'} =~ /^.*Content\-Length:\s(\d+)/s;
return 1 if(! $cl);
my ($cr) = $context->{'stdout'} =~ /^.*Content\-Range:\sbytes\s\d+\-\d+\/(\d+)/s;
if($cr) {
say "cr $cr";
$cl = $cr if($cr > $cl);
}
say "cl is $cl";
UNLOCK_WRITE($filename);
LOCK_WRITE($filename, $cl);
# make sure the file exists and within our parameters
my $st = stat($filename);
$st or return;
my $minsize = 16384;
$minsize = $cl if($cl < $minsize);
return if($st->size < $minsize);
say "sending, currentsize " . $st->size . ' totalsize ' . $cl;
# dont need to check the new data anymore
$context->{'on_stdout_data'} = undef;
$sendit->();
$request = undef;
},
'at_exit' => sub {
my ($context) = @_;
UNLOCK_WRITE($filename);
# last ditch effort, try to send it if we haven't
$sendit->();
}
});
return 1;
}
sub getOutBase {
my ($self, $qs) = @_;
return undef if(! $qs->{'id'});
my $media;
if(defined $qs->{'media'} && (defined $self->{'fmts'}{$qs->{'media'}})) {
$media = $qs->{'media'};
}
else {
$media = 'video';
}
return $qs->{'id'} . '_' . $media;
}
sub new {
my ($class, $settings, $server) = @_;
my $self = {'settings' => $settings};
bless $self, $class;
$self->{'routes'} = [
['/youtube', sub {
my ($request) = @_;
$self->onYoutube($request);
}],
['/yt', sub {
my ($request) = @_;
$self->onYoutube($request);
}],
['/ytmusic', sub {
my ($request) = @_;
$request->{'qs'}{'media'} //= 'music';
$self->onYoutube($request);
}],
['/ytaudio', sub {
my ($request) = @_;
$request->{'qs'}{'media'} //= 'music';
$self->onYoutube($request);
}],
['/ytplayer', sub {
my ($request) = @_;
my $html = $self->searchbox($request);
$html .= $self->ytplayer($request);
$request->SendHTML($html);
}],
( run in 0.982 second using v1.01-cache-2.11-cpan-39bf76dae61 )