YouTube iFrame API "setPlaybackQuality" or "suggestedQuality" not working
Asked Answered
H

6

22

I'm having some trouble setting the quality settings on a video via the Youtube iFrame API. This is my code:

var player;

player = new YT.Player('player', {
    height: '490',
    width: '725',
    videoId: yturl,
    /* setPlaybackQuality: 'hd720', <-- DOES NOT WORK */
    /* suggestedQuality: 'hd720',   <-- DOES NOT WORK */
    events: {
        'onReady': onPlayerReady
    }
});

function onPlayerReady(event) {
    player.setPlaybackQuality('hd720');       // <-- DOES NOT WORK
    event.target.setPlaybackQuality('hd720'); // <-- DOES NOT WORK
    player.setVolume(100);                    // <-- DOES WORK
    console.log(player.getPlaybackQuality()); // <-- Prints 'small' to console
    event.target.playVideo();
}

The funny thing is that my call to player.setPlaybackQuality or event.target.setPlaybackQuality doesn't give any errors. It just looks as if the player ignores it. A call to, say, player.setSuggestedQuality (a function that doesn't exist) throws an error as expected.

I've tried all the valid string parameters as outlined in the API reference ('medium', 'large', 'hd720' etc). None of them work.

Anyone have any suggestions to how I'm supposed to set this property?

Hyssop answered 10/1, 2012 at 11:24 Comment(2)
Only solution i could find - https://mcmap.net/q/588303/-set-jw-player-youtube-video-playback-qualityLeopold
For anyone finding this several years later, the setPlaybackQuality function is no longer supported. See the revision history for October 24, 2019: developers.google.com/youtube/…Illiterate
S
29

I have the exact same problem and workaround. I think what's happening is that YouTube is only allowing quality levels based on the actual size of the display, so unless you have your video 720px tall you can't default to 720p before it's actually playing. Then the user controls kick in and YouTube stops being a dick.


EDIT

Just hit a breakthrough: If you use event 3 (buffering) instead of event 5 (playing) there's no stutter for the user. Quality is changed as soon as it starts loading. Only weird thing is you need to set it in onPlayerReady as well or it doesn't work.

function onPlayerReady(event) {
    event.target.setPlaybackQuality('hd720');
}
function onPlayerStateChange(event) {
    if (event.data == YT.PlayerState.BUFFERING) {
        event.target.setPlaybackQuality('hd720');
    }
}
Statius answered 25/5, 2012 at 16:8 Comment(5)
worked for me ! hey do you think it is because of the init video has to have the same playback quality ? I am really interested why onPlayerStateChange() would not be enough ?Pantomime
This no longer seems to be working (April 2018). I posted a workaround that uses css to trick YouTube into loading a higher quality video. Definitely not as elegant as this solution, so I hope they'll fix the setPlaybackQuality in the future.Parkin
ios simulator always uses mediumBen
It was 2012, mb it was working that time, but it doesn't work with iOS 12Ben
For anyone finding this several years later, the setPlaybackQuality function is no longer supported. See the revision history for October 24, 2019: developers.google.com/youtube/…Illiterate
H
5

Found a possible hack/solution.

If I wait until the video has started playing, then apply setPlaybackQuality - it works. Thusly:

player = new YT.Player('player', {
    height: '490',
    width: '725',
    videoId: yturl,
    events: {
        'onReady': onPlayerReady,
        'onStateChange': onPlayerStateChange
    }
});

function onPlayerReady(event) {
    player.setVolume(100);
    event.target.playVideo();
}

function onPlayerStateChange(event) {
    if (event.data == YT.PlayerState.PLAYING) {
        event.target.setPlaybackQuality('hd720');  // <-- WORKS!
    }
}

However, the solution isn't ideal as the video first starts to buffer on a lower quality - then switch to 720 once it starts playing. Any comments or alternative solutions will be appreciated.

Hyssop answered 10/1, 2012 at 12:30 Comment(2)
This will work ONLY if the player size is at least 720px in height.Leatherleaf
I tried it with UIWebView and WKWebView and it doesn't work!Ben
R
3

Problem is YouTube selects the most appropriate playback quality, so it overrides setPlaybackQuality() in the onPlayerReady() function.

I've found a solution to force YouTube's player to play in any quality you desire no matter the width and height of the player:

var player;
function onYouTubeIframeAPIReady() {
    player = new YT.Player('player', {
        height: '180',
        width: '320',
        videoId: 'M7lc1UVf-VE',
        events: {
        'onReady': onPlayerReady,
        'onPlaybackQualityChange': onPlayerPlaybackQualityChange,
        'onStateChange': onPlayerStateChange
        }
    });
}


function onPlayerReady(event) {
    event.target.playVideo();
}

function onPlayerPlaybackQualityChange(event) {
    var playbackQuality = event.target.getPlaybackQuality();
    var suggestedQuality = 'hd720';

    console.log("Quality changed to: " + playbackQuality );

    if( playbackQuality !== 'hd720') {
        console.log("Setting quality to " + suggestedQuality );
        event.target.setPlaybackQuality( suggestedQuality );
    }
}

The code ensures the quality change is the suggested.

Keep in mind: the user couldn't change the video quality with the player button with that code.

Anyway, you could force the suggested quality just once.

Tested in GChrome, Firefox, and Safari.

Roseline answered 10/6, 2014 at 4:47 Comment(2)
Can you test it with iOS app and its WKWebView?Ben
"player.getplaybackquality()" returns with hd1080 when it's supposed to be hd720? Why is this? ThanksClachan
B
1

i found a solution that works perfectly for me:

 function onPlayerStateChange(event) {
   //Some code...

   $(".btn-change-quality").on("click",  function(){
       pauseVideo();
       player.setPlaybackQuality('hd720');
       playVideo();
    });
} 
Bejewel answered 6/1, 2014 at 3:0 Comment(1)
That worked for me. Additionaly i've added variable first_play = false and placed onclick code into if stament (if( ! first_play )). Then just add first_play = true in if statement, and works perfectJonna
L
0

I've played a little bit with this function and setPlaybackQuality in the onPlayerReady works. The only problem is that the assignment is not immediate, in fact getPlaybackQuality is returning the correct value just after the video is started. Actually before the video is started getPlaybackQuality will return always small. But one time the video starts is using the correct playBackQuality.

I've also tried with different player size combinations and it even works.

note: I'm using IFrame API.

Ligni answered 30/7, 2012 at 11:11 Comment(1)
obviously is impossible to set a playbackQuality if the video doesn't support it.Ligni
G
-1

another solution, stop video and use seekTo(). for live streaming you can skip seekTo(). The bad it will show buffering but the good is you have full control no matter what the player size.

var player = YT.get('videoid');
rate = 'small';
var currentTime = player.getCurrentTime();
player.stopVideo();
player.setPlaybackQuality(rate);
player.playVideo();
player.seekTo(currentTime, false);
Grano answered 10/5, 2017 at 17:6 Comment(1)
it doesn't work with iOS 12, no effect, can't set hd720Ben

© 2022 - 2024 — McMap. All rights reserved.