Skip to content

Commit

Permalink
- Added support for ignoring high frame rate (HFR) videos. (#274)
Browse files Browse the repository at this point in the history
Provided via the `hfr` config-option. When set to "0", HFR videos will be ignored.

The option is also available as a command-line argument:

	$ youtube-viewer --no-hfr

By default, the value of `hfr` is set to "1".
  • Loading branch information
trizen committed Jul 10, 2020
1 parent 8e7ece4 commit 5d498e1
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 120 deletions.
4 changes: 3 additions & 1 deletion bin/gtk2-youtube-viewer
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#-------------------------------------------------------
# GTK YouTube Viewer
# Created on: 12 September 2010
# Latest edit on: 29 May 2020
# Latest edit on: 11 July 2020
# https://github.com/trizen/youtube-viewer
#-------------------------------------------------------

Expand Down Expand Up @@ -187,6 +187,7 @@ my %CONFIG = (
prefer_mp4 => 0,
prefer_av1 => 0,
maxResults => 10,
hfr => 1,
resolution => 'best',
videoDimension => undef,
videoEmbeddable => undef,
Expand Down Expand Up @@ -2894,6 +2895,7 @@ sub get_streaming_url {
my ($streaming, $resolution) =
$yv_itags->find_streaming_url(
urls => $urls,
hfr => $CONFIG{hfr},
resolution => $CONFIG{resolution},
dash => $CONFIG{dash_support},
dash_mp4_audio => $CONFIG{dash_mp4_audio},
Expand Down
4 changes: 3 additions & 1 deletion bin/gtk3-youtube-viewer
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#-------------------------------------------------------
# GTK YouTube Viewer
# Created on: 12 September 2010
# Latest edit on: 29 May 2020
# Latest edit on: 11 July 2020
# https://github.com/trizen/youtube-viewer
#-------------------------------------------------------

Expand Down Expand Up @@ -188,6 +188,7 @@ my %CONFIG = (
prefer_mp4 => 0,
prefer_av1 => 0,
maxResults => 10,
hfr => 1,
resolution => 'best',
videoDimension => undef,
videoEmbeddable => undef,
Expand Down Expand Up @@ -3049,6 +3050,7 @@ sub get_streaming_url {
my ($streaming, $resolution) =
$yv_itags->find_streaming_url(
urls => $urls,
hfr => $CONFIG{hfr},
resolution => $CONFIG{resolution},
dash => $CONFIG{dash_support},
dash_mp4_audio => $CONFIG{dash_mp4_audio},
Expand Down
9 changes: 7 additions & 2 deletions bin/youtube-viewer
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#-------------------------------------------------------
# youtube-viewer
# Created on: 02 June 2010
# Latest edit on: 29 May 2020
# Latest edit on: 11 July 2020
# https://github.com/trizen/youtube-viewer
#-------------------------------------------------------

Expand Down Expand Up @@ -198,6 +198,7 @@ my %CONFIG = (
dash_mp4_audio => 1,
dash_segmented => 1, # may load slow
maxResults => 20,
hfr => 1,
resolution => 'best',
videoDefinition => undef,
videoDimension => undef,
Expand Down Expand Up @@ -727,6 +728,7 @@ usage: $execname [options] ([url] | [keywords])
--vd=s : set the video definition (any, high or standard)
--page=i : get results starting with a specific page number
--results=i : how many results to display per page (max: 50)
--hfr! : prefer high frame rate (HFR) videos
-2 -3 -4 -7 -1 : resolutions: 240p, 360p, 480p, 720p and 1080p
--resolution=s : supported resolutions: best, 2160p, 1440p,
1080p, 720p, 480p, 360p, 240p, 144p, audio.
Expand Down Expand Up @@ -1512,6 +1514,8 @@ sub parse_arguments {
'480p|4' => sub { $opt{resolution} = 480 },
'720p|7' => sub { $opt{resolution} = 720 },
'1080p|1' => sub { $opt{resolution} = 1080 },

'hfr!' => \$opt{hfr},
'res|resolution=s' => \$opt{resolution},

'comments=s' => \$opt{get_comments},
Expand Down Expand Up @@ -3075,6 +3079,7 @@ sub get_streaming_url {
$yv_itags->find_streaming_url(
urls => $urls,
resolution => ($opt{novideo} ? 'audio' : $opt{resolution}),
hfr => $opt{hfr},
dash => $dash,
dash_mp4_audio => ($opt{novideo} ? 1 : $opt{dash_mp4_audio}),
dash_segmented => ($opt{download_video} ? 0 : $opt{dash_segmented}),
Expand Down Expand Up @@ -3776,7 +3781,7 @@ sub print_videos {
sprintf(
"%s. %s (by %s) [%s]\n",
colored(sprintf('%2d', $i + 1), 'bold'), $yv_utils->get_title($video),
$yv_utils->get_channel_title($video), $yv_utils->get_time($video),
$yv_utils->get_channel_title($video), $yv_utils->get_time($video),
);
}
}
Expand Down
3 changes: 2 additions & 1 deletion lib/WWW/YoutubeViewer.pm
Original file line number Diff line number Diff line change
Expand Up @@ -850,9 +850,10 @@ sub get_streaming_urls {
my @audio_urls;

require WWW::YoutubeViewer::Itags;
state $itags = WWW::YoutubeViewer::Itags::get_itags();

my %audio_itags;
@audio_itags{@{WWW::YoutubeViewer::Itags->get_itags->{audio}}} = ();
@audio_itags{map { $_->{value} } @{$itags->{audio}}} = ();

foreach my $url (@streaming_urls) {

Expand Down
212 changes: 97 additions & 115 deletions lib/WWW/YoutubeViewer/Itags.pm
Original file line number Diff line number Diff line change
Expand Up @@ -39,118 +39,102 @@ Reference: http://en.wikipedia.org/wiki/YouTube#Quality_and_formats
=cut

sub get_itags {
#<<<
scalar {

'best' => [
38, # mp4 (3072p) (v-a)
[138, # mp4 (2160p-4320p) (v)
266, # mp4 (2160p-2304p) (v)
],
],
'best' => [{value => 38, format => 'mp4'}, # mp4 (3072p) (v-a)
{value => 138, format => 'mp4', dash => 1}, # mp4 (2160p-4320p) (v)
{value => 266, format => 'mp4', dash => 1}, # mp4 (2160p-2304p) (v)
],

'2160' => [
[
315, # webm HFR (v)
272, # webm (v)
313, # webm (v)
401, # av1 (v)
],
],
{value => 315, format => 'webm', dash => 1, hfr => 1}, # webm HFR (v)
{value => 272, format => 'webm', dash => 1}, # webm (v)
{value => 313, format => 'webm', dash => 1}, # webm (v)
{value => 401, format => 'av1', dash => 1}, # av1 (v)
],

'1440' => [
[
308, # webm HFR (v)
271, # webm (v)
264, # mp4 (v)
400, # av1 (v)
],
],
{value => 308, format => 'webm', dash => 1, hfr => 1}, # webm HFR (v)
{value => 271, format => 'webm', dash => 1}, # webm (v)
{value => 264, format => 'mp4', dash => 1}, # mp4 (v)
{value => 400, format => 'av1', dash => 1}, # av1 (v)
],

'1080' => [
[303, # webm HFR (v)
299, # mp4 HFR (v)
],
[248, # webm (v)
137, # mp4 (v)
399, # av1 (v)
],
46, # webm (v-a)
37, # mp4 (v-a)
301, # mp4 (live) (v-a)
96, # ts (live) (v-a)
],
{value => 303, format => 'webm', dash => 1, hfr => 1}, # webm HFR (v)
{value => 299, format => 'mp4', dash => 1, hfr => 1}, # mp4 HFR (v)
{value => 248, format => 'webm', dash => 1}, # webm (v)
{value => 137, format => 'mp4', dash => 1}, # mp4 (v)
{value => 399, format => 'av1', dash => 1}, # av1 (v)
{value => 46, format => 'webm'}, # webm (v-a)
{value => 37, format => 'mp4'}, # mp4 (v-a)
{value => 301, format => 'mp4', live => 1}, # mp4 (live) (v-a)
{value => 96, format => 'ts', live => 1}, # ts (live) (v-a)
],

'720' => [
[302, # webm HFR (v)
298, # mp4 HFR (v)
],
[247, # webm (v)
136, # mp4 (v)
398, # av1 (v)
],
45, # webm (v-a)
22, # mp4 (v-a)
300, # mp4 (live) (v-a)
120, # flv (live) (v-a)
95, # ts (live) (v-a)
],
{value => 302, format => 'webm', dash => 1, hfr => 1}, # webm HFR (v)
{value => 298, format => 'mp4', dash => 1, hfr => 1}, # mp4 HFR (v)
{value => 247, format => 'webm', dash => 1}, # webm (v)
{value => 136, format => 'mp4', dash => 1}, # mp4 (v)
{value => 398, format => 'av1', dash => 1}, # av1 (v)
{value => 45, format => 'webm'}, # webm (v-a)
{value => 22, format => 'mp4'}, # mp4 (v-a)
{value => 300, format => 'mp4', live => 1}, # mp4 (live) (v-a)
{value => 120, format => 'flv', live => 1}, # flv (live) (v-a)
{value => 95, format => 'ts', live => 1}, # ts (live) (v-a)
],

'480' => [
[244, # webm (v)
135, # mp4 (v)
397, # av1 (v)
],
44, # webm (v-a)
35, # flv (v-a)
94, # mp4 (live) (v-a)
],
{value => 244, format => 'webm', dash => 1}, # webm (v)
{value => 135, format => 'mp4', dash => 1}, # mp4 (v)
{value => 397, format => 'av1', dash => 1}, # av1 (v)
{value => 44, format => 'webm'}, # webm (v-a)
{value => 35, format => 'flv'}, # flv (v-a)
{value => 94, format => 'mp4', live => 1}, # mp4 (live) (v-a)
],

'360' => [
[243, # webm (v)
134, # mp4 (v)
396, # av1 (v)
],
43, # webm (v-a)
34, # flv (v-a)
93, # mp4 (live) (v-a)
18, # mp4 (v-a)
],
{value => 243, format => 'webm', dash => 1}, # webm (v)
{value => 134, format => 'mp4', dash => 1}, # mp4 (v)
{value => 396, format => 'av1', dash => 1}, # av1 (v)
{value => 43, format => 'webm'}, # webm (v-a)
{value => 34, format => 'flv'}, # flv (v-a)
{value => 93, format => 'mp4', live => 1}, # mp4 (live) (v-a)
{value => 18, format => 'mp4'}, # mp4 (v-a)
],

'240' => [
[242, # webm (v)
133, # mp4 (v)
395, # av1 (v)
],
6, # flv (270p) (v-a)
5, # flv (v-a)
36, # 3gp (v-a)
13, # 3gp (v-a)
92, # mp4 (live) (v-a)
132, # ts (live) (v-a)
],
{value => 242, format => 'webm', dash => 1}, # webm (v)
{value => 133, format => 'mp4', dash => 1}, # mp4 (v)
{value => 395, format => 'av1', dash => 1}, # av1 (v)
{value => 6, format => 'flv'}, # flv (270p) (v-a)
{value => 5, format => 'flv'}, # flv (v-a)
{value => 36, format => '3gp'}, # 3gp (v-a)
{value => 13, format => '3gp'}, # 3gp (v-a)
{value => 92, format => 'mp4', live => 1}, # mp4 (live) (v-a)
{value => 132, format => 'ts', live => 1}, # ts (live) (v-a)
],

'144' => [
[278, # webm (v)
160, # mp4 (v)
394, # av1 (v)
],
17, # 3gp (v-a)
91, # mp4 (live) (v-a)
151, # ts (live) (v-a)
],

'audio' => [172, # webm (192 kbps)
251, # webm opus (128-160 kbps)
171, # webm vorbis (92-128 kbps)
140, # mp4a (128 kbps)
141, # mp4a (256 kbps)
250, # webm opus (64 kbps)
249, # webm opus (48 kbps)
139, # mp4a (48 kbps)
{value => 278, format => 'webm', dash => 1}, # webm (v)
{value => 160, format => 'mp4', dash => 1}, # mp4 (v)
{value => 394, format => 'av1', dash => 1}, # av1 (v)
{value => 17, format => '3gp'}, # 3gp (v-a)
{value => 91, format => 'mp4'}, # mp4 (live) (v-a)
{value => 151, format => 'ts'}, # ts (live) (v-a)
],

'audio' => [{value => 172, format => 'webm', kbps => 192}, # webm (192 kbps)
{value => 251, format => 'webm', kbps => 160}, # webm opus (128-160 kbps)
{value => 171, format => 'webm', kbps => 128}, # webm vorbis (92-128 kbps)
{value => 140, format => 'mp4', kbps => 128}, # mp4a (128 kbps)
{value => 141, format => 'mp4', kbps => 256}, # mp4a (256 kbps)
{value => 250, format => 'webm', kbps => 64}, # webm opus (64 kbps)
{value => 249, format => 'webm', kbps => 48}, # webm opus (48 kbps)
{value => 139, format => 'mp4', kbps => 48}, # mp4a (48 kbps)
],
};
#>>>
}

=head2 get_resolutions()
Expand Down Expand Up @@ -188,42 +172,40 @@ sub _find_streaming_url {

foreach my $itag (@{$args{itags}->{$resolution}}) {

if (ref($itag) eq 'ARRAY') {
next if not exists $stream->{$itag->{value}};

$args{dash} || next;

foreach my $i (@{$itag}) {
if ($itag->{hfr}) {
$args{hfr} || next; # skip high frame rate (HFR) videos
}

next if not exists $stream->{$i};
if ($itag->{dash}) {
$args{dash} || next;

my $video_info = $stream->{$i};
my $audio_info = $self->_find_streaming_url(%args, resolution => 'audio', dash => 0);
my $video_info = $stream->{$itag->{value}};
my $audio_info = $self->_find_streaming_url(%args, resolution => 'audio', dash => 0);

if (defined $audio_info) {
$video_info->{__AUDIO__} = $audio_info;
return $video_info;
}
if (defined($audio_info)) {
$video_info->{__AUDIO__} = $audio_info;
return $video_info;
}

next;
}

if (exists $stream->{$itag}) {
if ($resolution eq 'audio' and not $args{dash_mp4_audio}) {
if ($itag == 140 or $itag == 141 or $itag == 139) {
next; # skip mp4 audio URLs
}
if ($resolution eq 'audio' and not $args{dash_mp4_audio}) {
if ($itag->{format} eq 'mp4') {
next; # skip mp4 audio URLs
}
}

my $entry = $stream->{$itag};

# Ignore segmented DASH URLs (they load pretty slow in mpv)
if (not $args{dash_segmented}) {
next if ($entry->{url} =~ m{^https://manifest\.googlevideo\.com/api/manifest/dash/});
}
my $entry = $stream->{$itag->{value}};

return $entry;
# Ignore segmented DASH URLs (they load pretty slow in mpv)
if (not $args{dash_segmented}) {
next if ($entry->{url} =~ m{^https://manifest\.googlevideo\.com/api/manifest/dash/});
}

return $entry;
}

return;
Expand Down

0 comments on commit 5d498e1

Please sign in to comment.