otsune's SnakeOil RSSフィード

python -c "print''.join([chr(x) for x in 111&1101,110+~-~11,10^11*11,110+~-~11,-~101,-~11^11*11,~-110,111&11*11,11+11+10,11|~-0110,1-~11^11*11,10^11*11,-~11^11*11,110,101])"

2006-09-01

Filter::FetchEnclosure::Mmsripでストリーミングラジオをripping

Filter::FetchEnclosure::Mmsripでストリーミングラジオをripping - otsune's SnakeOil  を含むブックマーク はてなブックマーク - Filter::FetchEnclosure::Mmsripでストリーミングラジオをripping - otsune's SnakeOil  Filter::FetchEnclosure::Mmsripでストリーミングラジオをripping - otsune's SnakeOil  のブックマークコメント

基本的にPlagger+ネトラジ+Podcastの続き - はこべにっき ?mplayerでもrip出来るンだけど、依存ライブラリの多さがアレなので、より特化したmmsripを使うように。

FreeBSDだと/usr/ports/multimedia/mmsrip/でインストールできるし。(同じコンセプトでmmsclientというのもある)

プラグインは実質Curlを数行書き換えただけ。

package Plagger::Plugin::Filter::FetchEnclosure::Mmsrip;
use strict;
use base qw(Plagger::Plugin::Filter::FetchEnclosure);

use POE;
use POE::Session;
use POE::Wheel::Run;

sub register {
    my($self, $context) = @_;
    $context->register_hook(
        $self,
        'update.entry.fixup' => \&enqueue,
        'update.fixup'       => \&fetch,
    );
}

sub enqueue {
    my($self, $context, $args) = @_;

    for my $enclosure ($args->{entry}->enclosures) {
        # TODO: do all of this in the base class ::Command
        my $feed_dir = File::Spec->catfile($self->conf->{dir}, $args->{feed}->id_safe);
        unless (-e $feed_dir && -d _) {
            $context->log(info => "mkdir $feed_dir");
            mkdir $feed_dir, 0777;
        }

        my $path = File::Spec->catfile($feed_dir, $enclosure->filename);

        if ($enclosure->length && -e $path && -s _ == $enclosure->length) {
            # TODO: if-none-match
            $context->log(debug => $enclosure->url . "is already stored in $path");
            next;
        }

        $context->log(info => "fetch " . $enclosure->url . " to " . $path);

        my $delay;
        if ($self->conf->{delay}) {
            $delay = $self->conf->{delay};
            $context->log(debug => "save the stream during $delay seconds: " . $args->{entry}->permalink);
        }

        my $trick = $self->conf->{trick};

        # TODO: max connections per domain to respect RFC
        POE::Session->create(
            inline_states => {
                _start => sub {
                    $_[HEAP]->{wheel} = POE::Wheel::Run->new(
                        Program => [
                            'mmsrip',
                            '--quiet',
                            ($trick ? '--trick' : ''),
                            ($delay ? ('--delay='.$delay) : ())
                            '--output='.$path,
                            $enclosure->url,
                        ],
                        StderrEvent => 'stderr',
                        ErrorEvent => 'wheel_close',
                        CloseEvent => 'wheel_close',
                    );
                },
                stderr => sub {
                    if ($_[ARG0] =~ /^100\s+(\d+)/m) { # xxx it doesn't work
                        my $length = -s $path;
                        $enclosure->local_path($path);
                        $enclosure->length($length);
                        $context->log(info => "Download to $path is done [$length]");
                    }

                    $context->log(debug => $_[ARG0]);
                },
                wheel_close => sub {
                    delete $_[HEAP]->{wheel};
                },
            },
        );
    }
}

sub fetch {
    Plagger->context->log(info => "Start downloading files using mmsrip.");
    POE::Kernel->run;
    Plagger->context->log(info => "w00t! Downloading finished.");
}

1;

__END__

=head1 NAME

Plagger::Plugin::Filter::FetchEnclosure::Mmsrip - Rip enclosures using mmsrip

=head1 SYNOPSIS

  - module: Filter::FetchEnclosure::Mmsrip
    config:
      dir: /path/to/download
      trick: 1
      delay: 2

=head1 DESCRIPTION

This pluguins uses mmsrip command to download enclosure files.

=head1 CONFIG

=over 4

=item trick

Attempt to trick recalcitrant servers by sending alternative local info
(mmsrip will act as an old version of MediaPlayer). Defaults to undef.

=back

=over 4

=item delay

Save the stream during delay seconds and exit.

=back

=head1 AUTHOR

Tatsuhiko Miyagawa
Masafumi Otsune

=head1 SEE ALSO

L<Plagger>, L<http://nbenoit.tuxfamily.org/projects.php?rq=mmsrip>

=cut
トラックバック - http://subtech.g.hatena.ne.jp/otsune/20060901