#!/usr/bin/perl -w package main; use warnings; use strict; use 5.008; use Getopt::Long; use Pod::Usage; use English qw(-no_match_vars); use FLV::Cut; our $VERSION = '0.24'; my %opts = ( keyframes => 0, verbose => 0, help => 0, version => 0, ); Getopt::Long::Configure('bundling'); GetOptions( 'k|keyframes' => \$opts{keyframes}, 'v|verbose' => \$opts{verbose}, 'h|help' => \$opts{help}, 'V|version' => \$opts{version}, ) or pod2usage(1); if ($opts{help}) { pod2usage(-exitstatus => 0, -verbose => 2); } if ($opts{version}) { print "v$VERSION\n"; exit 0; } if (3 > @ARGV) { pod2usage(1); } if (1 != (@ARGV % 2)) { pod2usage(1); } my $infile = shift; my $flv = FLV::File->new; $flv->parse($infile); my @keyframe_times; if ($opts{keyframes}) { $flv->populate_meta; @keyframe_times = @{ $flv->get_meta('keyframes')->{millis} }; } my $converter = FLV::Cut->new; while (@ARGV) { my $outfile = shift; my $times = shift; if ($times =~ m/\A (\d+|) : (\d+|) \z/xms) { my $cutin = $1 || undef; my $cutout = $2 || undef; if (@keyframe_times) { $cutin = _round_to_keyframe($cutin, \@keyframe_times, $opts{verbose}); $cutout = _round_to_keyframe($cutout, \@keyframe_times, $opts{verbose}); } $converter->add_output($outfile, $cutin, $cutout); } else { pod2usage(1); } } $converter->parse_flv($flv); $converter->save_all; sub _round_to_keyframe { my $cut = shift; # millisecs my $times = shift; # arrayref of millisecs my $verbose = shift; # bool return $cut if !defined $cut; my $best_time = -1; my $best_diff = 1_000_000_000; for my $time_ms (@{ $times }) { my $diff = abs($cut - $time_ms); if ($diff < $best_diff) { $best_diff = $diff; $best_time = $time_ms; } } $best_time = $best_time < 0 ? $cut : $best_time; if ($verbose && $cut != $best_time) { print "Rounding time from $cut to $best_time (milliseconds)\n"; } return $best_time < 0 ? $cut : $best_time; } __END__ =for stopwords FLV flv2flv flvsplice in.flv out.flv inms:outms flvcut =head1 NAME flvcut - Extract one or more time segments from an FLV file =head1 SYNOPSIS flvcut [options] in.flv out.flv inms:outms [out.flv inms:outms ...] Options: -k --keyframes Round specified times to the nearest keyframe time -v --verbose Print diagnostic messages -h --help Verbose help message -V --version Print version Either of the in or out files can be C<->, meaning STDIN or STDOUT. =head1 DESCRIPTION Sometimes you have an FLV that is too long, or has extraneous content. This tool lets you efficiently split the FLV into one or more segments. The in and out times are in milliseconds. Either (or both!) can be omitted, which implies the ends of the input file. You should probably always use the C<-k> option. Otherwise, if your times are wrong, the video is going to look terrible at the start of the clip. =head1 SEE ALSO flv2flv flvsplice L =head1 AUTHOR Chris Dolan, I =cut