I am scratching my head over inconsistencies on youtube embeds playback quality on mobile devices.
I am using the iframe api and I have created a demo to showcase the code: https://ancientoffbeatrotation--five-nine.repl.co/
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>repl.it</title>
<link href="index.css" rel="stylesheet" type="text/css" />
</head>
<body>
<script src="index.js"></script>
<iframe id="ytplayer" type="text/html" style="position:absolute; top:0px; left:0px; bottom:0px; right:10px; border:none; margin:0; padding:0; overflow:hidden; z-index:999999;" src="https://www.youtube-nocookie.com/embed/_r3LynEZuko?playlist=_r3LynEZuko&rel=0&autoplay=1&playsinline=1&controls=0&showinfo=0&enablejsapi=1" frameborder="0" allowfullscreen></iframe>
</body>
</html>
JS
var tag = document.createElement('script');
tag.src = "//www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('ytplayer', {
events: {
'onReady': onPlayerReady,
'onPlaybackQualityChange': onPlayerPlaybackQualityChange,
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerReady() {
player.playVideo();
player.mute();
}
function onPlayerPlaybackQualityChange(event) {
var available_qualities = player.getAvailableQualityLevels();
alert("Available qualities are" + available_qualities);
var displayed_quality= player.getPlaybackQuality();
alert("Used quality is" + displayed_quality);
}
function onPlayerStateChange(event) {
if(event.data === YT.PlayerState.PLAYING){
event.target.setSize( width=7000, height=10000 ); //huge dimensions
}
}
Note: I used repl.it instead of jsfiddle or codenpen because the two latter use iframes so it tampares/modifies the pixels available for the youtube iframe which can make our observations wrong. Instead, repl.it does not use any iframe and deploys a real html page so we can trust it more for this experiments.
In theory
Youtube says it will use the height of the video to set the resolution (even if it can change it based on other factors it can alone decide like speed of connection...):
The list below shows the playback quality levels that correspond to different standard player sizes. We recommend that you set the height of your video player to one of the values listed below and that you size your player to use 16:9 aspect ratio.
As stated above, even if you choose a standard player size, we also recommend that you set the suggestedQuality parameter value to default to enable YouTube to select the most appropriate playback quality.
small: Player height is 240px, and player dimensions are at least 320px by 240px for 4:3 aspect ratio. medium: Player height is 360px, and player dimensions are 640px by 360px (for 16:9 aspect ratio) or 480px by 360px (for 4:3 aspect ratio).
large: Player height is 480px, and player dimensions are 853px by 480px (for 16:9 aspect ratio) or 640px by 480px (for 4:3 aspect ratio).
hd720: Player height is 720px, and player dimensions are 1280px by 720px (for 16:9 aspect ratio) or 960px by 720px (for 4:3 aspect ratio).
hd1080: Player height is 1080px, and player dimensions are 1920px by 1080px (for 16:9 aspect ratio) or 1440px by 1080px (for 4:3 aspect ratio).
highres: Player height is greater than 1080px, which means that the player's aspect ratio is greater than 1920px by 1080px. default: YouTube selects the appropriate playback quality.
This setting effectively reverts the quality level to the default state and nullifies any previous efforts to set playback quality using the cueVideoById, loadVideoById or setPlaybackQuality functions.
I insist on the fact I am not using in the demo code the method setPlaybackquality which has not been working at all for the past few months, even if it is still undocumented ( see here, or here), so this is not about I think the issue of the method setPlaybackQuality.
In practice: The gist of the bug
I am just setting the size with setSize() and youtube is accordingly changing the video resolution. And I observe that changing it does on a desktop perfectly works according to this table given by google. but on mobile it's like it works...until a certain point, it's like there is a "ceiling", a resolution which is the maximum allowed by Youtube, based on unknown and very odd (see my experiments further below) criteria to me, which is capping the resolution that can be set. On my iphone 7 it's always capped at "HD720". On my Huawei Android P SMart it's always capped at "Large". So I don't get it: I mean on a super fast wifi at home even I can't get for huge dimensions of the demo video (height >5000px) hd 1080 and I am always maxed at hd720.
Here is a demo to share my findings so far: https://ancientoffbeatrotation--five-nine.repl.co/
Note that all tests are performed on a very recent chrome (>=64); safari on ios behaves the same way in my experiments.
on a chrome large desktop display window of 1800 x 945, I get a youtube video with a resolution of hd 1080 (highest available cool): perfect, as expected
chrome dev tools > emulate iphone7 so it takes dimensions of 375px x 667px => 1080hd is used, perfect, as expected
then on a real iphone 7 or browserstack (service to use real devices on the cloud): here the resolution used is hd720 despite the huge vidoe dimensions that should ensure it loads in hd1080. Right here is the issue. Context: very good wifi connection, full batteries (no low battery mode that could add constraint on rich media download) Same issue with my android phone where it does not even make it to hd720 and is set to "large".
Another "fascinating" observation is : I decided to add in the code an alert to know which so that which quality is available, the mystery deepens
function onPlayerPlaybackQualityChange(event) {
var available_qualities = player.getAvailableQualityLevels();
alert("Available qualities are" + available_qualities);
}
And the mystery clarifies but re-depeens again :( as shown below:
on desktop: I read for this alert "available qualities are: hd1080, hd720,large, medium, tiny, auto" => so in the observations above, I got indeed the highest possible quality, which is fine given the video dimensions
on the real iphone 7: I read for this alert "available qualities are: hd720, medium, small, auto" So I thought, haha that's why I am getting hd720 maybe as it's the maximum availmable. But why? my connection speed i super strong and my phone pretty modern (iphone 7).
but the mystery deepens because with the above observation on iphone 7, I thought "ok at least I understand a little bit more now, I got the highest resolution available, it's just that hd720 was the maximum available for some reason", but the mystery deepens when I test on my huawei P Smart : here I read on the alert "available qualities are: hd1080, hd720, large, mediom, small, tiny, auto" so I would expect to get the highest hd1080 resolution...but no I am getting ..."large" (not even hd720!). So my theory goes down. Plus why on earth would iphone 7 get in available qualities hd720 as highest resolution and huawei P Smart hd1080 (note: when I checked the screen resolution of the phone it said: 2160 x 1080)
I thought maybe like some people mentioned in the press, my internet operator (free mobile in France) is doing the same throttling a verizon or t-mobile in the US for youtube, but I tried with various proxies in the world and observations are always the same. so the issue is likely not related to this.
I'm a super lost here, anybody has an idea what's going on ?