our
$VERSION
;
has
'url'
=> (
is
=>
'rw'
,
required
=> 1,
);
has
'mtime'
=> (
is
=>
'ro'
,
lazy
=> 1,
builder
=>
'_probe_mtime'
,
);
sub
_probe_mtime {
my
$self
=
shift
;
if
(
$self
->has_reference) {
return
$self
->reference->mtime;
}
my
@statdata
=
stat
(
$self
->url);
if
(
scalar
(
@statdata
) == 0) {
return
;
}
return
$statdata
[9];
}
has
'canonical_duration'
=> (
is
=>
'ro'
,
isa
=>
'Str'
,
default
=>
'container'
,
);
has
'duration'
=> (
is
=>
'rw'
,
builder
=>
'_probe_duration'
,
lazy
=> 1,
);
sub
_probe_duration {
my
$self
=
shift
;
if
(
$self
->has_reference) {
return
$self
->reference->duration;
}
if
(
$self
->duration_style eq
"seconds"
) {
if
(
$self
->canonical_duration eq
'container'
) {
return
$self
->_get_probedata->{
format
}{duration};
}
elsif
(
$self
->canonical_duration eq
'video'
) {
return
$self
->_get_videodata->{duration};
}
elsif
(
$self
->canonical_duration eq
'audio'
) {
return
$self
->_get_audiodata->{duration};
}
else
{
...
}
}
else
{
return
$self
->duration_frames;
}
}
has
'duration_frames'
=> (
is
=>
'rw'
,
builder
=>
'_probe_duration_frames'
,
lazy
=> 1,
);
sub
_probe_duration_frames {
return
shift
->_get_videodata->{duration_ts};
}
sub
_warn_duration {
carp
"setting duration_style is deprecated. Rather use duration_frames."
}
has
'duration_style'
=> (
is
=>
'rw'
,
default
=>
'seconds'
,
trigger
=> \
&_warn_duration
,
);
has
'force_key_frames'
=> (
is
=>
'rw'
,
isa
=>
'Maybe[Str]'
,
builder
=>
'_probe_force_key_frames'
,
lazy
=> 1,
predicate
=>
'has_force_key_frames'
,
);
sub
_probe_force_key_frames {
my
$self
=
shift
;
if
(
$self
->has_reference) {
return
$self
->reference->force_key_frames;
}
return
;
}
has
'video_codec'
=> (
is
=>
'rw'
,
builder
=>
'_probe_videocodec'
,
lazy
=> 1,
);
sub
_probe_videocodec {
my
$self
=
shift
;
if
(
$self
->has_reference) {
return
$self
->reference->video_codec;
}
return
$self
->_get_videodata->{codec_name};
}
has
'audio_codec'
=> (
is
=>
'rw'
,
builder
=>
'_probe_audiocodec'
,
lazy
=> 1,
);
sub
_probe_audiocodec {
my
$self
=
shift
;
if
(
$self
->has_reference) {
return
$self
->reference->audio_codec;
}
return
$self
->_get_audiodata->{codec_name};
}
has
'video_size'
=> (
is
=>
'rw'
,
builder
=>
'_probe_videosize'
,
lazy
=> 1,
predicate
=>
'has_video_size'
,
);
sub
_probe_videosize {
my
$self
=
shift
;
if
(
$self
->has_reference) {
return
$self
->reference->video_size;
}
my
$width
=
$self
->video_width;
my
$height
=
$self
->video_height;
return
unless
defined
(
$width
) &&
defined
(
$height
);
return
$self
->video_width .
"x"
.
$self
->video_height;
}
has
'video_width'
=> (
is
=>
'rw'
,
builder
=>
'_probe_width'
,
lazy
=> 1,
);
sub
_probe_width {
my
$self
=
shift
;
if
(
$self
->has_reference) {
return
$self
->reference->video_width;
}
if
(
$self
->has_video_size) {
return
(
split
/x/,
$self
->video_size)[0];
}
else
{
return
$self
->_get_videodata->{width};
}
}
has
'video_height'
=> (
is
=>
'rw'
,
builder
=>
'_probe_height'
,
lazy
=> 1,
);
sub
_probe_height {
my
$self
=
shift
;
if
(
$self
->has_reference) {
return
$self
->reference->video_height;
}
if
(
$self
->has_video_size) {
return
(
split
/x/,
$self
->video_size)[1];
}
else
{
return
$self
->_get_videodata->{height};
}
}
has
'video_bitrate'
=> (
is
=>
'rw'
,
builder
=>
'_probe_videobitrate'
,
lazy
=> 1,
);
sub
_probe_videobitrate {
my
$self
=
shift
;
if
(
$self
->has_reference) {
return
$self
->reference->video_bitrate;
}
my
$bitrate
=
$self
->_get_videodata->{bit_rate};
if
(
defined
(
$bitrate
) && (!(
$bitrate
=~ /k/))) {
return
$bitrate
/ 1000;
}
return
$bitrate
;
}
has
'video_minrate'
=> (
is
=>
'rw'
,
builder
=>
'_probe_videominrate'
,
lazy
=> 1,
);
sub
_probe_videominrate {
my
$self
=
shift
;
my
$rate
;
if
(
$self
->has_reference) {
$rate
=
$self
->reference->video_minrate;
if
(
defined
(
$rate
)) {
return
$rate
;
}
}
$rate
=
$self
->video_bitrate;
if
(
defined
(
$rate
)) {
return
$rate
* 0.5;
}
return
;
}
has
'video_maxrate'
=> (
is
=>
'rw'
,
builder
=>
'_probe_videomaxrate'
,
lazy
=> 1,
);
has
'video_preset'
=> (
is
=>
'rw'
,
builder
=>
'_probe_video_preset'
,
lazy
=> 1,
);
sub
_probe_video_preset {
my
$self
=
shift
;
if
(
$self
->has_reference) {
return
$self
->reference->video_preset;
}
return
;
}
sub
_probe_videomaxrate {
my
$self
=
shift
;
my
$rate
;
if
(
$self
->has_reference) {
$rate
=
$self
->reference->video_maxrate;
if
(
defined
(
$rate
)) {
return
$rate
;
}
}
$rate
=
$self
->video_bitrate;
if
(
defined
(
$rate
)) {
return
$rate
* 1.45;
}
return
;
}
has
'aspect_ratio'
=> (
is
=>
'rw'
,
builder
=>
'_probe_aspect_ratio'
,
lazy
=> 1,
);
sub
_probe_aspect_ratio {
my
$self
=
shift
;
if
(
$self
->has_reference) {
return
$self
->reference->aspect_ratio;
}
return
$self
->_get_videodata->{display_aspect_ratio};
}
has
'audio_bitrate'
=> (
is
=>
'rw'
,
builder
=>
'_probe_audiobitrate'
,
lazy
=> 1,
);
sub
_probe_audiobitrate {
my
$self
=
shift
;
if
(
$self
->has_reference) {
return
$self
->reference->audio_bitrate;
}
return
$self
->_get_audiodata->{bit_rate};
}
has
'audio_samplerate'
=> (
is
=>
'rw'
,
builder
=>
'_probe_audiorate'
,
lazy
=> 1,
);
sub
_probe_audiorate {
my
$self
=
shift
;
if
(
$self
->has_reference) {
return
$self
->reference->audio_samplerate;
}
return
$self
->_get_audiodata->{sample_rate};
}
has
'video_framerate'
=> (
is
=>
'rw'
,
builder
=>
'_probe_framerate'
,
lazy
=> 1,
);
sub
_probe_framerate {
my
$self
=
shift
;
if
(
$self
->has_reference) {
return
$self
->reference->video_framerate;
}
my
$framerate
=
$self
->_get_videodata->{r_frame_rate};
return
$framerate
;
}
has
'fragment_start'
=> (
is
=>
'rw'
,
predicate
=>
'has_fragment_start'
,
);
has
'quality'
=> (
is
=>
'rw'
,
builder
=>
'_probe_quality'
,
lazy
=> 1,
);
sub
_probe_quality {
my
$self
=
shift
;
if
(
$self
->has_reference) {
return
$self
->reference->quality;
}
return
;
}
has
'metadata'
=> (
traits
=> [
'Hash'
],
isa
=>
'HashRef[Str]'
,
is
=>
'ro'
,
handles
=> {
add_metadata
=>
'set'
,
drop_metadata
=>
'delete'
,
},
predicate
=>
'has_metadata'
,
);
has
'reference'
=> (
isa
=>
'Media::Convert::Asset'
,
is
=>
'ro'
,
predicate
=>
'has_reference'
,
);
has
'pix_fmt'
=> (
is
=>
'rw'
,
builder
=>
'_probe_pix_fmt'
,
lazy
=> 1,
);
sub
_probe_pix_fmt {
my
$self
=
shift
;
if
(
$self
->has_reference) {
return
$self
->reference->pix_fmt;
}
return
$self
->_get_videodata->{pix_fmt};
}
has
'astream_id'
=> (
is
=>
'rw'
,
builder
=>
'_probe_astream_id'
,
lazy
=> 1,
);
sub
_probe_astream_id {
my
$self
=
shift
;
return
$self
->_get_audiodata->{
index
};
}
has
blackspots
=> (
is
=>
'ro'
,
isa
=>
'ArrayRef[HashRef[Num]]'
,
builder
=>
'_probe_blackspots'
,
lazy
=> 1,
);
sub
_probe_blackspots {
my
$self
=
shift
;
my
$blacks
= [];
pipe
my
$R
,
my
$W
;
if
(
fork
== 0) {
open
STDERR,
">"
,
"$W"
;
open
STDOUT,
">"
,
"$W"
;
my
@cmd
= (
"ffmpeg"
,
"-threads"
,
"1"
,
"-nostats"
,
"-i"
,
$self
->url,
"-vf"
,
"blackdetect=d=0:pix_th=.01"
,
"-f"
,
"null"
,
"/dev/null"
);
exec
@cmd
;
die
"exec failed"
;
}
close
$W
;
while
(<
$R
>) {
if
(/blackdetect.
*black_start
:(?<start>[\d\.]+)\sblack_end:(?<end>[\d\.]+)\sblack_duration:(?<duration>[\d\.]+)/) {
push
@$blacks
, { %+ };
}
}
close
(
$R
);
return
$blacks
;
}
has
'channel_layouts'
=> (
is
=>
'rw'
,
traits
=> [
'Array'
],
isa
=>
'ArrayRef[Str]'
,
builder
=>
'_probe_channel_layouts'
,
lazy
=> 1,
);
sub
_probe_channel_layouts {
my
$self
=
shift
;
my
$rv
= [];
foreach
my
$stream
(@{
$self
->_get_probedata->{streams}}) {
if
(
$stream
->{codec_type} eq
"audio"
) {
push
@$rv
,
$stream
->{channel_layout};
}
}
return
$rv
;
}
has
'astream_ids'
=> (
is
=>
'rw'
,
traits
=> [
'Array'
],
isa
=>
'ArrayRef[Int]'
,
builder
=>
'_probe_astream_ids'
,
lazy
=> 1,
handles
=> {
astream_count
=>
"count"
,
},
);
sub
_probe_astream_ids {
my
$self
=
shift
;
my
$rv
= [];
foreach
my
$stream
(@{
$self
->_get_probedata->{streams}}) {
if
(
$stream
->{codec_type} eq
"audio"
) {
push
@$rv
,
$stream
->{
index
};
}
}
return
$rv
;
}
has
'audio_channel_count'
=> (
is
=>
'rw'
,
isa
=>
'Int'
,
lazy
=> 1,
builder
=>
'_probe_audio_channel_count'
,
);
sub
_probe_audio_channel_count {
my
$self
=
shift
;
if
(
$self
->has_reference) {
return
$self
->reference->audio_channel_count;
}
return
$self
->_get_audiodata->{channels};
}
has
'vstream_id'
=> (
is
=>
'rw'
,
builder
=>
'_probe_vstream_id'
,
lazy
=> 1,
);
sub
_probe_vstream_id {
my
$self
=
shift
;
return
$self
->_get_videodata->{
index
};
}
has
'extra_params'
=> (
traits
=> [
'Hash'
],
isa
=>
'HashRef[Str]'
,
is
=>
'ro'
,
handles
=> {
add_param
=>
'set'
,
drop_param
=>
'delete'
,
},
builder
=>
"_probe_extra_params"
,
lazy
=> 1,
);
sub
_probe_extra_params {
my
$self
=
shift
;
if
(
$self
->has_reference) {
return
$self
->reference->extra_params;
}
return
{};
}
has
'input_params'
=> (
traits
=> [
'Hash'
],
isa
=>
'HashRef[Str]'
,
is
=>
'ro'
,
handles
=> {
add_input_param
=>
'set'
,
drop_input_param
=>
'delete'
,
},
builder
=>
"_probe_input_params"
,
lazy
=> 1,
);
sub
_probe_input_params {
my
$self
=
shift
;
if
(
$self
->has_reference) {
return
$self
->reference->input_params;
}
return
{};
}
has
'time_offset'
=> (
isa
=>
'Num'
,
is
=>
'ro'
,
predicate
=>
'has_time_offset'
,
);
has
'pass'
=> (
is
=>
'rw'
,
predicate
=>
'has_pass'
,
clearer
=>
'clear_pass'
,
);
has
'videodata'
=> (
is
=>
'bare'
,
reader
=>
'_get_videodata'
,
builder
=>
'_probe_videodata'
,
lazy
=> 1,
);
has
'audiodata'
=> (
is
=>
'bare'
,
reader
=>
'_get_audiodata'
,
builder
=>
'_probe_audiodata'
,
lazy
=> 1,
);
has
'probedata'
=> (
is
=>
'bare'
,
reader
=>
'_get_probedata'
,
builder
=>
'_probe'
,
clearer
=>
'clear_probedata'
,
lazy
=> 1,
);
sub
readopts {
my
$self
=
shift
;
my
@opts
= ();
if
(
$self
->has_time_offset) {
push
@opts
, (
"-itsoffset"
,
$self
->time_offset);
}
if
(
scalar
(
keys
(%{
$self
->input_params})) > 0) {
foreach
my
$param
(
keys
%{
$self
->input_params}) {
push
@opts
, (
"-$param"
,
$self
->input_params->{
$param
});
}
}
push
@opts
, (
"-i"
,
$self
->url);
return
@opts
;
}
sub
writeopts {
my
$self
=
shift
;
my
$pipe
=
shift
;
my
@opts
= ();
if
(!
$pipe
->vcopy && !
$pipe
->vskip) {
push
@opts
, (
'-threads'
,
'1'
);
if
(
defined
(
$self
->video_codec)) {
push
@opts
, (
'-c:v'
, detect_to_write(
$self
->video_codec));
}
if
(
defined
(
$self
->video_bitrate)) {
push
@opts
, (
'-b:v'
,
$self
->video_bitrate .
"k"
,
'-minrate'
,
$self
->video_minrate .
"k"
,
'-maxrate'
,
$self
->video_maxrate .
"k"
);
}
if
(
defined
(
$self
->video_framerate)) {
push
@opts
, (
'-r:v'
,
$self
->video_framerate);
}
if
(
defined
(
$self
->quality)) {
push
@opts
, (
'-crf'
,
$self
->quality);
}
if
(
defined
(
$self
->speed)) {
push
@opts
, (
'-speed'
,
$self
->speed);
}
if
(
defined
(
$self
->video_preset)) {
push
@opts
, (
'-preset'
,
$self
->video_preset);
}
if
(
defined
(
$self
->force_key_frames)) {
push
@opts
, (
'-force_key_frames'
,
$self
->force_key_frames);
}
if
(
$self
->has_pass) {
push
@opts
, (
'-pass'
,
$self
->pass,
'-passlogfile'
,
$self
->url .
'-multipass'
);
}
}
if
(!
$pipe
->acopy && !
$pipe
->askip) {
if
(
defined
(
$self
->audio_codec)) {
push
@opts
, (
'-c:a'
, detect_to_write(
$self
->audio_codec));
}
if
(
defined
(
$self
->audio_bitrate)) {
push
@opts
, (
'-b:a'
,
$self
->audio_bitrate);
}
if
(
defined
(
$self
->audio_samplerate)) {
push
@opts
, (
'-ar'
,
$self
->audio_samplerate);
}
}
if
(
$self
->has_fragment_start) {
push
@opts
, (
'-ss'
,
$self
->fragment_start);
}
if
(
defined
(
$self
->duration)) {
if
(
$self
->duration_style eq
'seconds'
) {
push
@opts
, (
'-t'
,
$self
->duration);
}
else
{
push
@opts
, (
'-frames:v'
,
$self
->duration);
}
}
elsif
(
defined
(
$self
->duration_frames)) {
push
@opts
, (
'-frames:v'
,
$self
->duration_frames);
}
if
(
defined
(
$self
->pix_fmt)) {
push
@opts
, (
'-pix_fmt'
,
$self
->pix_fmt);
}
if
(
$self
->has_metadata) {
foreach
my
$meta
(
keys
%{
$self
->metadata}) {
push
@opts
, (
'-metadata'
,
$meta
.
'='
.
$self
->metadata->{
$meta
});
}
}
if
(!
defined
(
$self
->duration) && $
push
@opts
,
'-shortest'
;
}
if
(
scalar
(
keys
(%{
$self
->extra_params}))>0) {
foreach
my
$param
(
keys
%{
$self
->extra_params}) {
push
@opts
, (
"-$param"
,
$self
->extra_params->{
$param
});
}
}
if
(
exists
(
$ENV
{SREVIEW_NONSTRICT})) {
push
@opts
, (
"-strict"
,
"-2"
);
}
push
@opts
,
$self
->url;
return
@opts
;
}
sub
_probe {
my
$self
=
shift
;
if
(
$self
->has_reference) {
return
$self
->reference->_get_probedata;
}
if
(-e
$self
->url) {
open
my
$jsonpipe
,
"-|:encoding(UTF-8)"
,
"ffprobe"
,
"-loglevel"
,
"quiet"
,
"-print_format"
,
"json"
,
"-show_format"
,
"-show_streams"
,
$self
->url;
my
$json
=
""
;
while
(<
$jsonpipe
>) {
$json
.=
$_
;
}
close
$jsonpipe
;
return
decode_json(
$json
);
}
return
{};
}
sub
_probe_audiodata {
my
$self
=
shift
;
if
(!
exists
(
$self
->_get_probedata->{streams})) {
return
{};
}
foreach
my
$stream
(@{
$self
->_get_probedata->{streams}}) {
if
(
$stream
->{codec_type} eq
"audio"
) {
return
$stream
;
}
}
return
{};
}
sub
_probe_videodata {
my
$self
=
shift
;
if
(!
exists
(
$self
->_get_probedata->{streams})) {
return
{};
}
foreach
my
$stream
(@{
$self
->_get_probedata->{streams}}) {
if
(
$stream
->{codec_type} eq
"video"
) {
return
$stream
;
}
}
return
{};
}
sub
speed {
my
$self
=
shift
;
if
(
$self
->has_reference) {
return
$self
->reference->speed;
}
return
4;
}
no
Moose;
1;