From Code to Community: Sponsoring The Perl and Raku Conference 2025 Learn more

#!/usr/bin/perl -w
use strict;
use File::Temp qw/tempdir/;
use Mojo::JSON qw/true/;
my $inputfile = undef;
my $talkid = undef;
my $talknonce = undef;
my $talkslug = undef;
my $help = undef;
my $audionormal = undef;
GetOptions("t|talkid=i" => \$talkid,
"n|nonce=s" => \$talknonce,
"s|slug=s" => \$talkslug,
"i|input=s" => \$inputfile,
"a|audionormal" => \$audionormal,
"h|help" => \$help) or pod2usage("command line invalid");
if($help) {
pod2usage(0);
}
die "require an input file name\n" unless defined($inputfile);
die "Require exactly one of a nonce, a talk ID, or a talk slug\n" unless scalar(grep({defined}($talkid, $talknonce, $talkslug))==1);
my $config = SReview::Config::Common::setup();
my $talk;
if(defined($talknonce)) {
$talk = SReview::Talk->by_nonce($talknonce);
} elsif(defined($talkid)) {
$talk = SReview::Talk->new(talkid => $talkid);
} elsif(defined($talkslug)) {
$talk = SReview::Talk->by_slug($talkslug);
}
$talk->set_state("injecting", "running");
$talk = SReview::Talk->new(talkid => $talk->talkid);
my $input = Media::Convert::Asset->new(url => $inputfile);
my $output_coll = SReview::Files::Factory->create("intermediate", $config->get("pubdir"));
my $outputfile = $output_coll->add_file(relname => $talk->relative_name . "/main.mkv");
$output_coll->delete_files(relnames => [dirname($talk->relative_name)]);
my $checks = $config->get("inject_transcode_skip_checks");
my $do_transcode = 0;
if(defined($checks)) {
foreach my $prop(keys %$checks) {
my $attr = $input->meta->find_attribute_by_name($prop);
my $val = $attr->get_value($input);
if(!defined($val)) {
print("Skip check failed: value for $prop not defined for input video. Retranscoding.\n");
$do_transcode = 1;
last;
}
if(exists($checks->{$prop}{min}) && exists($checks->{$prop}{max})) {
if(($val > $checks->{$prop}{max}) || ($val < $checks->{$prop}{min})) {
print("Skip check failed: value for $prop out of bounds on input video. Retranscoding.\n");
$do_transcode = 1;
last;
} else {
next;
}
}
if(exists($checks->{$prop}{val})) {
if($val ne $checks->{$prop}{val}) {
print("Skip check failed: value for $prop does not string-equal expected value. Retranscoding.\n");
$do_transcode = 1;
last;
} else {
next;
}
}
print("Skip check failed: configuration for $prop does not have both a minimum and maximum, or misses exact value. Retranscoding.\n");
last;
}
}
if(!$do_transcode) {
print("Skip check successful; not transcoding, just copying data around.\n");
Media::Convert::Pipe->new(inputs => [$input], output => Media::Convert::Asset->new(url => $outputfile->filename), vcopy => 1, acopy => 1)->run();
} else {
if($audionormal) {
my $dirname = tempdir("injectXXXXXX", DIR => $config->get("workdir"), CLEANUP => 1);
my $normalized = Media::Convert::Asset->new(url => join("/", $dirname, basename($inputfile)));
Media::Convert::Normalizer->new(input => $input, output => $normalized)->run();
$input = Media::Convert::Asset->new(url => $normalized->url);
}
my $profile = Media::Convert::Asset::ProfileFactory->create($config->get("input_profile"), $input, $config->get('extra_profiles'));
Media::Convert::Pipe->new(inputs => [$input], output => Media::Convert::Asset->new(url => $outputfile->filename, reference => $profile), vcopy => 0, acopy => 0)->run();
}
$outputfile->store_file;
$talk->set_flag('is_injected' => true);
$talk->add_correction(serial => -1);
$talk->done_correcting;
$talk->state_done("injecting");