AnyEvent-MPV

 view release on metacpan or  search on metacpan

MPV.pm  view on Meta::CPAN


      } elsif ($INPUT eq "mpv/idle") { # normal end-of-file
         last;

      } elsif ($INPUT eq "return") {
         $status = 1;
         last;

Or the code that actually starts playback, once the file is loaded:

   our %SAVE_PROPERTY = (aid => 1, sid => 1, "audio-delay" => 1);
   
   ...

   my $oid = 100;

      } elsif ($INPUT eq "mpv/file-loaded") { # start playing, configure video
         $mpv->cmd ("seek", $playback_start, "absolute+exact") if $playback_start > 0;

         my $target_fps = eval { $mpv->cmd_recv ("get_property", "container-fps") } || 60;
         $target_fps *= play_video_speed_mult;
         set_fps $target_fps;

         unless (eval { $mpv->cmd_recv ("get_property", "video-format") }) {
            $mpv->cmd ("set", "file-local-options/lavfi-complex", "[aid1] asplit [ao], showcqt=..., format=yuv420p [vo]");
         };

         for my $prop (keys %SAVE_PROPERTY) {
            if (exists $PLAYING_STATE->{"mpv_$prop"}) {
               $mpv->cmd ("set", "$prop", $PLAYING_STATE->{"mpv_$prop"} . "");
            }

            $mpv->cmd ("observe_property", ++$oid, $prop);
         }

         play_video_set_speed;
         $mpv->cmd ("set", "osd-level", "$OSD_LEVEL");
         $mpv->cmd ("observe_property", ++$oid, "osd-level");
         $mpv->cmd ("set", "pause", "no");

         $mpv->cmd ("set_property", "deinterlace", "yes")
            if $initial_deinterlace;

There is a lot going on here. First it seeks to the actual playback
position, if it is not at the start of the file (it would probaby be more
efficient to set the starting position before loading the file, though,
but this is good enough).

Then it plays with the display fps, to set it to something harmonious
w.r.t. the video framerate.

If the file does not have a video part, it assumes it is an audio file and
sets a visualizer.

Also, a number of properties are not global, but per-file. At the moment,
this is C<audio-delay>, and the current audio/subtitle track, which it
sets, and also creates an observer. Again, this doesn'T use the observe
functionality of this module, but handles it itself, assigning obsevrer
ids 100+ to temporary/per-file observers.

Lastly, it sets some global (or per-youtube-uploader) parameters, such as
speed, and unpauses. Property changes are handled like other input events:

      } elsif ($INPUT eq "mpv/property-change") {
         my $prop = $INPUT_DATA->{name};

         if ($prop eq "chapter-metadata") {
            if ($INPUT_DATA->{data}{TITLE} =~ /^\[SponsorBlock\]: (.*)/) {
               my $section = $1;
               my $skip;

               $skip ||= $SPONSOR_SKIP{$_}
                  for split /\s*,\s*/, $section;

               if (defined $skip) {
                  if ($skip) {
                     # delay a bit, in case we get two metadata changes in quick succession, e.g.
                     # because we have a skip at file load time.
                     $skip_delay = AE::timer 2/50, 0, sub {
                        $mpv->cmd ("no-osd", "add", "chapter", 1);
                        $mpv->cmd ("show-text", "skipped sponsorblock section \"$section\"", 3000);
                     };
                  } else {
                     undef $skip_delay;
                     $mpv->cmd ("show-text", "NOT skipping sponsorblock section \"$section\"", 3000);
                  }
               } else {
                  $mpv->cmd ("show-text", "UNRECOGNIZED sponsorblock section \"$section\"", 60000);
               }
            } else {
               # cancel a queued skip
               undef $skip_delay;
            }

         } elsif (exists $SAVE_PROPERTY{$prop}) {
            $PLAYING_STATE->{"mpv_$prop"} = $INPUT_DATA->{data};
            ::state_save;
         }

This saves back the per-file properties, and also handles chapter changes
in a hacky way.

Most of the handlers are very simple, though. For example:

      } elsif ($INPUT eq "pause") {
         $mpv->cmd ("cycle", "pause");
         $PLAYING_STATE->{curpos} = $mpv->cmd_recv ("get_property", "playback-time");
      } elsif ($INPUT eq "right") {
         $mpv->cmd ("osd-msg-bar", "seek",  30, "relative+exact");
      } elsif ($INPUT eq "left") {
         $mpv->cmd ("osd-msg-bar", "seek", -5, "relative+exact");
      } elsif ($INPUT eq "up") {
         $mpv->cmd ("osd-msg-bar", "seek", +600, "relative+exact");
      } elsif ($INPUT eq "down") {
         $mpv->cmd ("osd-msg-bar", "seek", -600, "relative+exact");
      } elsif ($INPUT eq "select") {
         $mpv->cmd ("osd-msg-bar", "add", "audio-delay", "-0.100");
      } elsif ($INPUT eq "start") {
         $mpv->cmd ("osd-msg-bar", "add", "audio-delay", "0.100");
      } elsif ($INPUT eq "intfwd") {
         $mpv->cmd ("no-osd", "frame-step");



( run in 0.796 second using v1.01-cache-2.11-cpan-b16cb0d3907 )