Using YouTube API to get all comments from a video with the JSON feed

10,281

Solution 1

I just came across this question and I notice that its been quite some time when this was asked. But since nobody answered it yet, I think I should do that.

What you should ideally do is, use Youtube's PHP API (using Zend_GData) and use the following code in PHP:

<?php

    require_once 'Zend/Loader.php'; // the Zend dir must be in your include_path
Zend_Loader::loadClass('Zend_Gdata_YouTube');

$yt = new Zend_Gdata_YouTube();
$yt->setMajorProtocolVersion(2);
$video = parse_url("http://www.youtube.com/watch?v=K-ob8sr9ZX0");
parse_str(urldecode($video['query']), $query);
$videoId = $query['v'];

$commentFeed = $yt->retrieveAllEntriesForFeed($yt->getVideoCommentFeed($videoId));

foreach ($commentFeed as $commentEntry) {
    echo "Full text: " . $commentEntry->content->text . "<br />";
}

The key element here is the retrieveAllEntriesForFeed() method.

Instead of echo-ing all the comments, you can construct a JSON and send it back to the waiting Javascript.

It does not use the max-results or start-index, but does the job well without them.

Solution 2

Use the 'orderby' parameter of the api and set it to 'published' to retrieve almost all the comments.

https://gdata.youtube.com/feeds/api/videos/<videoID>/comments?max-results=50&alt=json&orderby=published

You can still use the start-index parameter to loop through the comments but it is not a good idea.

From the documentation: API responses use tags to identify pagination links for the previous and/or next page of entries in a feed. To avoid pagination problems, we recommend that you use these links to enable users to link to different pages of API results.

If a feed contains a previous page of results, the API response will contain a tag with a rel attribute value of previous. If a feed contains a next page of results, the API response will contain a tag with a rel attribute value of next.

https://developers.google.com/youtube/2.0/reference#Paging_through_Results

This way you won't get any nested feeds. To get the next set of results simply use the link given on the previous page of results! Hope this helps. It worked for me!

Share:
10,281
Mark Lyons
Author by

Mark Lyons

Updated on June 04, 2022

Comments

  • Mark Lyons
    Mark Lyons almost 2 years

    I'm using the YouTube API to get comments for a video with a parameterized query like the following:

    http://gdata.youtube.com/feeds/api/videos/theVideoID/comments?v=2&alt=json

    The problem with this is that the maximum number of results you can get per query is 50. I want to get every comment. I'm currently using the start-index and max-results parameters to solve this. I had a bit of trouble doing iterations of 50 at a time because sometimes the iteration would have a start-index above the number of comments and I couldn't figure that out, so I just tried to work out one at a time. It may be better to do 50 at a time, so let me know if that is the better solution. For now:

    I'm using PHP to get the amount of comments:

    <?php
        $video_ID = 'gT2HYxOdxUk';
        $JSON = file_get_contents("https://gdata.youtube.com/feeds/api/videos/{$video_ID}?v=2&alt=json");
        $JSON_Data = json_decode($JSON);
        $commentCount = $JSON_Data->{'entry'}->{'gd$comments'}->{'gd$feedLink'}->{'countHint'};
    ?>
    

    And then I'm calling a JavaScript/jQuery function to load all comments into an array. For testing, it prints them into a div. For starters, here's how I'm calling the function:

    <body onLoad="loadComments('<?php echo $commentCount; ?>', '<?php echo $video_ID; ?>')">
    

    Next, the actual function:

    function loadComments(count, videoID) {     
        for(i = 1; i <= count; i++) {
            $.ajax({
                url: "http://gdata.youtube.com/feeds/api/videos/" + videoID + "/comments?v=2&alt=json&max-results=1" + "&start-index=" + i,
                dataType: "jsonp",
                success: function(data){
                    $.each(data.feed.entry, function(key, val) {
                        comments.push(val.content.$t);
                        $('#commentOutput').append(val.content.$t + '<br>'); //Just for testing purposes.
                    });
                }
    
            });
        }
    }
    

    The problem is that it is really iffy. When I use the count variable as the terminating part of the for loop like this, it always gets like, for example, 45 out of 211 comments. If I manually enter 211, it will go to around 195. If I put in a low number, like 1-15, it pretty much always gets them all. 20+, it's never right.

    I need to figure out how to get this to consistently get all the comments of a given video by taking advantage of the max-results and start-index parameters. Thanks!