Youtube のビデオを Web アプリからダウンロード・エンコードできるようにしていたのですが、この Web アプリの実装は、ダウンロード及びエンコードの間レスポンスはユーザに返却されないというクソ実装でした。
リクエスト自体は XHR で行うのですが、Catalyst に付いてくる開発用サーバは (たしか) 1 プロセス・1 スレッドで動作します。結果として、ダウンロードとエンコードが完了するまでの間、当該プロセスは占有され、いかなる処理も実施できないという困った状態に陥っていました。
この状況を打破するために、ジョブキューでダウンロード・エンコードを行うようにすることを決意。また、これを機に、Youtube からのダウンローダを独自実装から、xaicron さんの WWW::YouTube::Download に差し換えてみました。
worker 実装は以下の通り。
use strict; use warnings; use WWW::YouTube::Download; use Gearman::Worker; use Storable qw(thaw); use Getopt::Long; use Time::Piece; use Path::Class; use IPC::Run3 qw(run3); GetOptions( 'from=s' => \my $from, 'to=s' => \my $to, ) or die "GetOptions error: @ARGV"; my $ymd = localtime()->ymd; my $fromdir = dir($from); my $todir = dir($to, $ymd); $todir->mkpath unless -e $todir; my $dler = WWW::YouTube::Download->new; my $worker = Gearman::Worker->new; $worker->job_servers(qw(localhost)); $worker->register_function( download => sub { my $job = shift; my $video_id = ${ thaw($job->arg) }; my $filepath = $fromdir->file($video_id . $dler->get_suffix( $video_id )); $dler->download( $video_id => { file_name => $filepath->stringify() }); encode( $filepath ); } ); $worker->work while 1; sub encode { my ($from_file) = @_; -e $from_file or do { warn "$from_file is not found\n"; return; }; -r _ or do { warn "$from_file is not readable\n"; return; }; my $to_file = $todir->file( $from_file->basename() . ".m4a" )->absolute(); my $cmd = [qw(ffmpeg -i), $from_file, qw(-vn -acodec libfaac -ab 256k -y), $to_file ]; run3 $cmd, \undef, \undef, \my $err; warn "err: $err\n" unless $?; return 1 if $? == 0; }